Sergio B
Sergio B

Reputation: 734

Sorting nodes with xslt not working

I have the following xml and xsl files and I am trying to sort the CARTONDETAIL nodes, but leave the rest of the document as the original.

So far, the top part of my document gets copied over, everything before CARTONDETAIL. After that I just get a lot of empty <CARTONDETAIL> tags, like I am creating an endless loop, because the document never puts the closing brackets at the end nor the other HEADER instance. In the input file I have two instances of the HEADER tree, but I don't see any traces of the second one in my output file.

I am using saxon to parse the documents.

Any help is greatly appreciated.. Thanks all!

XML:

<?xml version="1.0" encoding="UTF-8"?>
<TRUCKSHIPUPLOAD>
    <HEADER>
        <WH>WH1</WH>
        <OWN>FakeOwner</OWN>
        <ORD>1035710</ORD>
        <RELEASE_NUM>1</RELEASE_NUM>
        <ORDER_LINE/>
        <TRUCK>0222001406</TRUCK>
        <ORDERING>1</ORDERING>
        <TRAILER_ID/>
        <WAREHOUSE_ID>UDS01</WAREHOUSE_ID>
        <OWNER_ID>CAYRE</OWNER_ID>
        <IF_SEQ_NUM>222001406</IF_SEQ_NUM>
        <IF_STATUS/>
        <IF_ERROR_MSG/>
        <ORDER_ID>1035710</ORDER_ID>
        <STAT_DATE/>
        .........
        <CARTON>
            <WH>WH1</WH>
            <OWN>FakeOwner</OWN>
            <ORD>1035710</ORD>
            <RELEASE_NUM>1</RELEASE_NUM>
            <ORDER_LINE/>
            <TRUCK>0222001406</TRUCK>
            <ORDERING>4</ORDERING>
            <TRAILER_ID/>
            ....
            <CARTONDETAIL>
                <WH>WH1</WH>
                <OWN>FakeOwner</OWN>
                <ORD>1035710</ORD>
                <RELEASE_NUM>1</RELEASE_NUM>
                <ORDER_LINE>4</ORDER_LINE>
                <TRUCK>0222001406</TRUCK>
                <TRAILER_ID/>
                <WAREHOUSE_ID>WH1</WAREHOUSE_ID>
                <OWNER_ID>FakeOwner</OWNER_ID>
                <IF_SEQ_NUM/>
                <IF_STATUS/>
                <IF_ERROR_MSG/>
                <ORDER_ID>1035710</ORDER_ID>
                <STAT_DATE/>
                ...
            </CARTONDETAIL>

            <CARTONDETAIL>
                <WH>WH1</WH>
                <OWN>FakeOwner</OWN>
                <ORD>1035710</ORD>
                <RELEASE_NUM>1</RELEASE_NUM>
                <ORDER_LINE>8</ORDER_LINE>
                <TRUCK>0222001406</TRUCK>
                <TRAILER_ID/>
                <WAREHOUSE_ID>WH1</WAREHOUSE_ID>
                <OWNER_ID>FakeOwner</OWNER_ID>
                <IF_SEQ_NUM/>
                <IF_STATUS/>
                <IF_ERROR_MSG/>
                <ORDER_ID>1035710</ORDER_ID>
                <STAT_DATE/>
                ...
            </CARTONDETAIL>
            <CARTONDETAIL>
                <WH>WH1</WH>
                <OWN>FakeOwner</OWN>
                <ORD>1035710</ORD>
                <RELEASE_NUM>1</RELEASE_NUM>
                <ORDER_LINE>2</ORDER_LINE>
                <TRUCK>0222001406</TRUCK>
                <TRAILER_ID/>
                <WAREHOUSE_ID>WH1</WAREHOUSE_ID>
                <OWNER_ID>FakeOwner</OWNER_ID>
                <IF_SEQ_NUM/>
                <IF_STATUS/>
                <IF_ERROR_MSG/>
                <ORDER_ID>1035710</ORDER_ID>
                <STAT_DATE/>
                ...
            </CARTONDETAIL>

        </CARTON>
    </HEADER>
</TRUCKSHIPUPLOAD>

XSL:

      <?xml version="1.0" encoding="UTF-8"?>
        <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

           <xsl:output method="xml" indent="yes"/>
            <xsl:template match="CARTONDETAIL">
                <xsl:copy>
                    <xsl:apply-templates select="//CARTONDETAIL">
                        <xsl:sort select="ORDER_LINE" data-type="number"/>
                    </xsl:apply-templates>
                </xsl:copy> 
            </xsl:template>
            <xsl:template match="node()|@*">
                <xsl:copy>
                    <xsl:apply-templates select="node()|@*"/>
                </xsl:copy>
            </xsl:template>
        </xsl:stylesheet>

Upvotes: 0

Views: 68

Answers (3)

mg_kedzie
mg_kedzie

Reputation: 437

Copy all nodes and sort CARTONDETAIL with respect to ORDER_LINE, hope that this is what you wanted.

       <xsl:output method="xml" indent="yes"/>
        <xsl:template match="CARTON">
            <xsl:copy>
                <xsl:apply-templates select="CARTONDETAIL">
                    <xsl:sort select="ORDER_LINE" data-type="number"/>
                </xsl:apply-templates>
            </xsl:copy> 
        </xsl:template>
        <xsl:template match="node()|@*">
            <xsl:copy>
                <xsl:apply-templates select="node()|@*"/>
            </xsl:copy>
        </xsl:template>
    </xsl:stylesheet>

Upvotes: 0

michael.hor257k
michael.hor257k

Reputation: 117073

First thing: you do have an infinite loop here:

<xsl:template match="CARTONDETAIL">
    <xsl:copy>
        <xsl:apply-templates select="//CARTONDETAIL">
     ...

Now, assuming you want to sort the CARTONDETAIL nodes within their parent CARTON, try:

XSLT 1.0

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

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

<xsl:template match="CARTON">
    <xsl:copy>
        <xsl:apply-templates select="@*|node()">
            <xsl:sort select="ORDER_LINE" data-type="number"/>
        </xsl:apply-templates>
    </xsl:copy>
</xsl:template>

</xsl:stylesheet>

Upvotes: 0

Martin Honnen
Martin Honnen

Reputation: 167691

I think instead of

        <xsl:template match="CARTONDETAIL">
            <xsl:copy>
                <xsl:apply-templates select="//CARTONDETAIL">
                    <xsl:sort select="ORDER_LINE" data-type="number"/>
                </xsl:apply-templates>
            </xsl:copy> 
        </xsl:template>

you want

        <xsl:template match="CARTON">
            <xsl:copy>
              <xsl:for-each-group select="*" group-adjacent="boolean(self::CARTONDETAIL)">
               <xsl:choose>
                <xsl:when test="current-grouping-key()">
                 <xsl:apply-templates select="current-group()">
                    <xsl:sort select="ORDER_LINE" data-type="number"/>
                 </xsl:apply-templates>
                </xsl:when>
                <xsl:otherwise>
                   <xsl:apply-templates select="current-group()"/>
                </xsl:otherwise>
            </xsl:copy> 
        </xsl:template>

Upvotes: 3

Related Questions