Input is a mutliRef encoded SOAP message/document. How do you use XSLT to flatten multiRefs. Multiref nodes can be referenced used multiple times, and themselves recursive
This stylesheet:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/">
<xsl:key name="kMultiRefById" match="multiRef" use="@id"/>
<xsl:output method="xml"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="getAccountDTOReturn">
<xsl:variable name="vRefer"
select="key('kMultiRefById',substring(@href,2))"/>
<xsl:copy>
<xsl:copy-of select="$vRefer/namespace::*"/>
<xsl:apply-templates select="$vRefer/@*|$vRefer/node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="multiRef|multiRef/@id|multiRef/@soapenc:root"/>
</xsl:stylesheet>
Output:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soapenv:Body>
<ns1:getAccountDTOResponse soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:ns1="http://www.example.com/pw/services/PWServices">
<getAccountDTOReturn soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
xsi:type="ns2:Account"
xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:ns2="urn:PWServices">
<ID href="#id1"></ID>
<accountNumber xsi:type="soapenc:string"></accountNumber>
<accountType xsi:type="soapenc:string"></accountType>
<clientData xsi:type="soapenc:Array" xsi:nil="true"></clientData>
<name xsi:type="soapenc:string"></name>
<parentRef xsi:type="soapenc:string"></parentRef>
</getAccountDTOReturn>
</ns1:getAccountDTOResponse>
</soapenv:Body>
</soapenv:Envelope>
Note: Keys for cross references. Identity rule. Empty rules for stripping. Copying namespaces nodes might not be posible for every XSLT processor, although I only know about Mozilla's TransforMiiX wich doesn't have implemented namespaces::
axis.
Alex, I'm not matching your output completely but here is how you can resolve your document by hrefs.
This stylesheet:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" >
<xsl:key name="multiref-by-id" match="multiRef" use="@id"/>
<xsl:template match="/">
<xsl:copy>
<xsl:apply-templates select="@*|*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="*[starts-with(@href, '#')]">
<xsl:copy>
<xsl:apply-templates select="@* |
key('multiref-by-id', substring-after(@href, '#'))/@* |
key('multiref-by-id', substring-after(@href, '#'))/node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="@href[starts-with(., '#')] | multiRef[@id] | @soapenc:root"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Given this input:
<?xml version="1.0" encoding="utf-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soapenv:Body>
<ns1:getAccountDTOResponse soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:ns1="http://www.example.com/pw/services/PWServices">
<getAccountDTOReturn href="#id0"/>
</ns1:getAccountDTOResponse>
<multiRef id="id0" soapenc:root="0"
soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
xsi:type="ns2:Account"
xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:ns2="urn:PWServices">
<ID href="#id1"/>
<accountNumber xsi:type="soapenc:string"></accountNumber>
<accountType xsi:type="soapenc:string"></accountType>
<clientData xsi:type="soapenc:Array" xsi:nil="true"/>
<name xsi:type="soapenc:string"></name>
<parentRef xsi:type="soapenc:string"></parentRef>
</multiRef>
<multiRef id="id1" soapenc:root="0"
soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
xsi:type="xsd:long"
xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/">
0
</multiRef>
</soapenv:Body>
</soapenv:Envelope>
Produces the following result:
<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soapenv:Body>
<ns1:getAccountDTOResponse xmlns:ns1="http://www.example.com/pw/services/PWServices"
soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<getAccountDTOReturn id="id0" soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
xsi:type="ns2:Account">
<ID xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:ns2="urn:PWServices" id="id1"
soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xsi:type="xsd:long">
0
</ID>
<accountNumber xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:ns2="urn:PWServices"
xsi:type="soapenc:string"/>
<accountType xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:ns2="urn:PWServices"
xsi:type="soapenc:string"/>
<clientData xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:ns2="urn:PWServices"
xsi:type="soapenc:Array" xsi:nil="true"/>
<name xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:ns2="urn:PWServices"
xsi:type="soapenc:string"/>
<parentRef xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:ns2="urn:PWServices"
xsi:type="soapenc:string"/>
</getAccountDTOReturn>
</ns1:getAccountDTOResponse>
</soapenv:Body>
</soapenv:Envelope>
I think that this apporach could be easily customized to fit your needs. I would like to outline that the provided stylesheet operates on @hrefs
and does not take in account any element names. Therefore it can be used flexibly without paying attention to the referring element names. However all the reference should be named multiRef
s but this can be easily customized too.