mnvbrtn
mnvbrtn

Reputation: 568

Sorting the XML with XSLT

Input XML:

<soap-env:Envelope xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/">
    <soap-env:Header>
        <wsse:Security xmlns:wsse="http://schemas.xmlsoap.org/ws/2002/12/secext">
            <wsse:Username>User</wsse:Username>
            <wsse:Password>Password</wsse:Password>
        </wsse:Security>
    </soap-env:Header>
    <soap-env:Body>
        <soap-env:CustomerRs>
            <Information>
                <Identity Code="DFW">
                    <User LoginID="123456" />
                </Identity>
                <User>
                    <Customer Gender="Male">
                        <Person>
                            <GivenName>Tester2</GivenName>
                            <LastName>Tester</LastName>
                        </Person>
                        <Telephone Type="Business" InfoNo="1" SeqNo="1">
                            <Number Area="456" Phone="7878787" />
                        </Telephone>
                        <Info InfoNo="2" SeqNo="1">
                            <LastName>Wilson</LastName>
                            <GivenName>Kelley</GivenName>
                        </Info>
                        <Info InfoNo="4" SeqNo="1">
                            <LastName>Graham</LastName>
                            <GivenName>Tom</GivenName>
                        </Info>
                        <Info InfoNo="1" SeqNo="3">
                            <LastName>Fisher</LastName>
                            <GivenName>Elaine</GivenName>
                        </Info>
                        <Info InfoNo="1" SeqNo="2">
                            <LastName>Gary</LastName>
                            <GivenName>Jerry</GivenName>
                        </Info>
                        <Info InfoNo="1" SeqNo="1">
                            <LastName>Timothy</LastName>
                            <GivenName>Kathy</GivenName>
                        </Info>
                        <Info InfoNo="3" SeqNo="1">
                            <LastName>Tim</LastName>
                            <GivenName>Kerry</GivenName>
                        </Info>
                        <Info InfoNo="1" SeqNo="4">
                            <LastName>Rob</LastName>
                            <GivenName>Tony</GivenName>
                        </Info>
                        <Address Type="Business" InfoNo="1" SeqNo="1">
                            <Line1>Menands Ln</Line1>
                            <City>Albany</City>
                        </Address>
                    </Customer>
                    <Order type="S">
                        <Ref>ABC123</Ref>
                        <OrderedBy>
                            <Debtor code="BLABLA"></Debtor>
                        </OrderedBy>
                        <DeliveryMethod code="Barefoot"></DeliveryMethod>
                        <OrderLine line="1">
                            <Item code="QQQ123456"></Item>
                            <Quantity>1</Quantity>
                        </OrderLine>
                    </Order>
                </User>
            </Information>
        </soap-env:CustomerRs>
    </soap-env:Body>
</soap-env:Envelope>

Expected Output XML Response:

<soap-env:Envelope xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/">
    <soap-env:Header>
        <wsse:Security xmlns:wsse="http://schemas.xmlsoap.org/ws/2002/12/secext">
            <wsse:Username>User</wsse:Username>
            <wsse:Password>Password</wsse:Password>
        </wsse:Security>
    </soap-env:Header>
    <soap-env:Body>
        <soap-env:CustomerRs>
            <Information>
                <Identity Code="DFW">
                    <User LoginID="123456" />
                </Identity>
                <User>
                    <Customer Gender="Male">
                        <Person>
                            <GivenName>Tester2</GivenName>
                            <LastName>Tester</LastName>
                        </Person>
                        <Telephone Type="Business" InfoNo="1" SeqNo="1">
                            <Number Area="456" Phone="7878787" />
                        </Telephone>
                        <Info InfoNo="1" SeqNo="1">
                            <LastName>Timothy</LastName>
                            <GivenName>Kathy</GivenName>
                        </Info>
                        <Info InfoNo="1" SeqNo="2">
                            <LastName>Gary</LastName>
                            <GivenName>Jerry</GivenName>
                        </Info>
                        <Info InfoNo="1" SeqNo="3">
                            <LastName>Fisher</LastName>
                            <GivenName>Elaine</GivenName>
                        </Info>
                        <Info InfoNo="1" SeqNo="4">
                            <LastName>Rob</LastName>
                            <GivenName>Tony</GivenName>
                        </Info>
                        <Info InfoNo="2" SeqNo="1">
                            <LastName>Wilson</LastName>
                            <GivenName>Kelley</GivenName>
                        </Info>
                        <Info InfoNo="3" SeqNo="1">
                            <LastName>Tim</LastName>
                            <GivenName>Kerry</GivenName>
                        </Info>
                        <Info InfoNo="4" SeqNo="1">
                            <LastName>Graham</LastName>
                            <GivenName>Tom</GivenName>
                        </Info>
                        <Address Type="Business" InfoNo="1" SeqNo="1">
                            <Line1>Menands Ln</Line1>
                            <City>Albany</City>
                        </Address>
                    </Customer>
                    <Order type="S">
                        <Ref>ABC123</Ref>
                        <OrderedBy>
                            <Debtor code="BLABLA"></Debtor>
                        </OrderedBy>
                        <DeliveryMethod code="Barefoot"></DeliveryMethod>
                        <OrderLine line="1">
                            <Item code="QQQ123456"></Item>
                            <Quantity>1</Quantity>
                        </OrderLine>
                    </Order>
                </User>
            </Information>
        </soap-env:CustomerRs>
    </soap-env:Body>
</soap-env:Envelope>

My xslt that is doing transformation:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output omit-xml-declaration="yes" indent="yes" />
    <xsl:template match="node()|@*">
        <xsl:copy>
            <xsl:apply-templates select="node()|@*" />
        </xsl:copy>
    </xsl:template>
    <xsl:template match="/*[local-name()='Envelope']">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()">
                <xsl:sort select="/*[local-name()='Info']/@*[local-name()='InfoNo']" data-type="number" order="ascending" />
                <xsl:sort select="/*[local-name()='Info']/@*[local-name()='SeqNo']" data-type="number" order="ascending" />
            </xsl:apply-templates>
        </xsl:copy>
    </xsl:template>
</xsl:stylesheet>

I used this stylesheet to sort and arrange but still producing the same input as is. What exactly I'm doing wrong, I'm not able to get the response.

Upvotes: 0

Views: 112

Answers (2)

Michael Kay
Michael Kay

Reputation: 163587

You need to learn about the difference between relative paths and absolute paths. To compute a sort key for an element E, you will (almost) always want to select some value using a path that starts at E, that is, a relative path. A path that starts with "/" is an absolute path, which starts at the top of the document, and therefore computes the same value regardless of where E is. So a sort key computed using an absolute path, like <xsl:sort select="/*[.....]"/>, has to be wrong.

Upvotes: 0

Parfait
Parfait

Reputation: 107737

Consider the following adjustment. For sorting, no need to walk down the entire tree since you use the identity template to copy document as is. Simply add a template for the sorting section, namely the parent tag, here being <Customer> and then sort only its <Info> children.

Also, InfoNo and SeqNo are attributes so should be referenced with @. Finally, as best practice try adding <xsl:strip-space elements="*"/> at top of XSLT to strip out whitespace text nodes which adds a bit of efficiency since such nodes are stripped out from memory.

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output omit-xml-declaration="yes" indent="yes" />
    <xsl:strip-space elements="*"/>

    <xsl:template match="node()|@*">
        <xsl:copy>
            <xsl:apply-templates select="node()|@*" />
        </xsl:copy>
    </xsl:template>

    <xsl:template match="Customer">
        <xsl:copy>
            <xsl:copy-of select="Person|Telephone"/>            
            <xsl:apply-templates select="Info">
                <xsl:sort select="@InfoNo" data-type="number" order="ascending" />
                <xsl:sort select="@SeqNo" data-type="number" order="ascending" />
            </xsl:apply-templates>
            <xsl:copy-of select="Address"/>
        </xsl:copy>
    </xsl:template>

</xsl:stylesheet>

Upvotes: 1

Related Questions