Search code examples
sortingxslt-1.0xsl-fomuenchian-groupingxslkey

xsl:sort with preceding-sibling XSLT 1.0 XSL-FO muenchian xsl:key


I would like to access preceding-siblings in a sorted list. I'm using Antenna House 6.2 and XSLT 1.0. I tried using the msxsl extension with node-set() but calls to node-set() failed. Some say accessing the preceding-sibling in a sorted list can't be done in 1.0 and others mentioned Muenching Grouping and using xsl:key so I'm trying that now. I've looked at this page: http://www.jenitennison.com/xslt/grouping/muenchian.html

The table is sorted correctly, but I haven't been able to figure out how to retrieve the preceding-sibling of the sorted list with the key. Do I need more keys? I'm sorting on partNumberValue and then figureNumber, and figureNumber may have a figureNumberVariant. Any suggestions are appreciated.

XML:

<illustratedPartsCatalog>
            <figure id="fig1">...</figure>
            <catalogSeqNumber assyCode="05" figureNumber="01" indenture="0" item="000" subSubSystemCode="1" subSystemCode="1" systemCode="15">
<itemSeqNumber itemSeqNumberValue="00A">
<quantityPerNextHigherAssy>AT</quantityPerNextHigherAssy>
<partRef manufacturerCodeValue="01233" partNumberValue="8910-276">
</partRef>
<partSegment>
<itemIdentData>
<descrForPart>GGACC AIR VALVE ASSEMBLY</descrForPart></itemIdentData>
</partSegment><applicabilitySegment><usableOnCodeAssy>A</usableOnCodeAssy>
</applicabilitySegment></itemSeqNumber></catalogSeqNumber>
<catalogSeqNumber assyCode="05" figureNumber="01" indenture="0" item="001" itemVariant="A" subSubSystemCode="1" subSystemCode="2" systemCode="15">
<itemSeqNumber itemSeqNumberValue="00A">
<quantityPerNextHigherAssy>RF</quantityPerNextHigherAssy>
<partRef manufacturerCodeValue="01233" partNumberValue="8910-281">
</partRef>
<partSegment>
<itemIdentData>
<descrForPart>JJACC AIR VALVE ASSEMBLY</descrForPart></itemIdentData>
</partSegment><applicabilitySegment><usableOnCodeAssy>B</usableOnCodeAssy>
</applicabilitySegment></itemSeqNumber></catalogSeqNumber>
<catalogSeqNumber assyCode="05" figureNumber="01" indenture="1" item="000" subSubSystemCode="1" subSystemCode="1" systemCode="1">
<itemSeqNumber itemSeqNumberValue="00A">
<quantityPerNextHigherAssy>1</quantityPerNextHigherAssy>
<partRef manufacturerCodeValue="01233" partNumberValue="2079-1302-1">
</partRef>
<partSegment>
<itemIdentData>
<descrForPart>NAMEPLATE COVER</descrForPart></itemIdentData>
</partSegment>
<partLocationSegment>
<attachStoreShipPart attachStoreShipPartCode="1"/></partLocationSegment>
</itemSeqNumber></catalogSeqNumber>
            <figure id="fig2">...</figure>
            <catalogSeqNumber assyCode="05" figureNumber="02" indenture="1" item="030" subSubSystemCode="1" subSystemCode="2" systemCode="15">
<itemSeqNumber itemSeqNumberValue="00A">
<quantityPerNextHigherAssy>AR</quantityPerNextHigherAssy>
<partRef manufacturerCodeValue="01233" partNumberValue="63358">
</partRef>
<partSegment>
<itemIdentData>
<descrForPart>LOCK WIRE</descrForPart></itemIdentData></partSegment>
</itemSeqNumber></catalogSeqNumber>
<catalogSeqNumber assyCode="05" figureNumber="02" indenture="1" item="040" subSubSystemCode="1" subSystemCode="2" systemCode="15">
<itemSeqNumber itemSeqNumberValue="00A">
<quantityPerNextHigherAssy>1</quantityPerNextHigherAssy>
<partRef manufacturerCodeValue="01233" partNumberValue="1476-3248-1">
</partRef>
<partSegment>
<itemIdentData>
<descrForPart>SHIELD</descrForPart></itemIdentData></partSegment>
</itemSeqNumber></catalogSeqNumber>
<catalogSeqNumber assyCode="05" figureNumber="02" indenture="1" item="050" subSubSystemCode="1" subSystemCode="2" systemCode="15">
<itemSeqNumber itemSeqNumberValue="00A">
<quantityPerNextHigherAssy>2</quantityPerNextHigherAssy>
<partRef manufacturerCodeValue="01233" partNumberValue="1025-129">
</partRef>
<partSegment>
<itemIdentData>
<descrForPart>SCREW</descrForPart></itemIdentData></partSegment>
<partLocationSegment>
<attachStoreShipPart attachStoreShipPartCode="1"/></partLocationSegment>
</itemSeqNumber></catalogSeqNumber>
        </illustratedPartsCatalog>

XSLT:

<xsl:key name="kfigNo" match="catalogSeqNumber" use="@figureNumber" />

    <xsl:template match="illustratedPartsCatalog">
        <xsl:apply-templates />
        <fo:table>
            <fo:table-header>
                <fo:table-row>
                    <fo:table-cell>
                        <fo:block>PART</fo:block>
                        <fo:block>NUMBER</fo:block>
                    </fo:table-cell>
                    <fo:table-cell>
                        <fo:block>FIG</fo:block>
                        <fo:block>NO.</fo:block>
                    </fo:table-cell>
<fo:table-cell>
                        <fo:block>ITEM</fo:block>
                        <fo:block>NO.</fo:block>
                    </fo:table-cell>
<fo:table-cell>
                                                <fo:block>QTY.</fo:block>
                    </fo:table-cell>

                </fo:table-row>
            </fo:table-header>
            <fo:table-body>
                <xsl:call-template name="SortParts"/>
            </fo:table-body>
        </fo:table>
    </xsl:template>


<xsl:template name="SortParts">
    <xsl:for-each select="catalogSeqNumber[key('kfigNo', @figureNumber)]">
        <xsl:sort select="concat(itemSeqNumber/partRef/@partNumberValue, @figureNumber,@item)"/>
        <xsl:call-template name="catalogSeqNumber-NI">
                    <xsl:with-param name="figNo" select="concat(@figureNumber,@figureNumberVariant)"/>
                    <xsl:with-param name="prfigNo" select="concat(preceding-sibling::catalogSeqNumber/@figureNumber,preceding-sibling::catalogSeqNumber/@figureNumberVariant)" />
                </xsl:call-template>
    </xsl:for-each>
</xsl:template>



    <xsl:template name="catalogSeqNumber-NI">
                <xsl:param name="figNo"/>
                <xsl:param name="prfigNo" />        
                    <fo:table-row>
                        <fo:table-cell>
                            <fo:block>
                                <xsl:value-of select=" ./itemSeqNumber/partRef/@partNumberValue"/>
                            </fo:block>
                        </fo:table-cell>
                        <fo:table-cell>
                            <xsl:choose>
                                <xsl:when test="$figNo">
                                    <fo:block>
                                        <xsl:text> </xsl:text><xsl:value-of select="$figNo"/><xsl:text> </xsl:text> <xsl:value-of select="$prfigNo"/>
                                    </fo:block>
                                </xsl:when>
                                <xsl:otherwise>
                                        <fo:block />
                                </xsl:otherwise>
                            </xsl:choose>
                        </fo:table-cell>
<fo:table-cell>
                <fo:block>                                      <xsl:value-of select="concat(@item,@itemVariant)"/>             </fo:block>
            </fo:table-cell>

            <fo:table-cell>
                <fo:block>
                    <xsl:value-of select="./itemSeqNumber/quantityPerNextHigherAssy"/>
                </fo:block>
            </fo:table-cell>
                    </fo:table-row>
                </xsl:template>

Expected output:

<fo:table-row>
        <fo:table-cell><fo:block>1025-129</fo:block></fo:table-cell>
        <fo:table-cell><fo:block> 02</fo:block></fo:table-cell>
        <fo:table-cell><fo:block> 050</fo:block></fo:table-cell>
        <fo:table-cell><fo:block>1</fo:block></fo:table-cell>
</fo:table-row>
<fo:table-row>
        <fo:table-cell><fo:block>1476-3248-1</fo:block></fo:table-cell>
        <fo:table-cell><fo:block> 02 02</fo:block></fo:table-cell>
        <fo:table-cell><fo:block> 040</fo:block></fo:table-cell>
        <fo:table-cell><fo:block>1</fo:block></fo:table-cell>
</fo:table-row>
<fo:table-row>
        <fo:table-cell><fo:block>2079-1302-1</fo:block></fo:table-cell>
        <fo:table-cell><fo:block> 01 02</fo:block></fo:table-cell>
        <fo:table-cell><fo:block> 000</fo:block></fo:table-cell>
        <fo:table-cell><fo:block>1</fo:block></fo:table-cell>
</fo:table-row>
<fo:table-row>
        <fo:table-cell><fo:block>3082-1604-1</fo:block></fo:table-cell>
        <fo:table-cell><fo:block> 01 01</fo:block></fo:table-cell>
        <fo:table-cell><fo:block> 010</fo:block></fo:table-cell>
        <fo:table-cell><fo:block>1</fo:block></fo:table-cell>
</fo:table-row>
<fo:table-row>
        <fo:table-cell><fo:block>63358</fo:block></fo:table-cell>
        <fo:table-cell><fo:block> 02 01</fo:block></fo:table-cell>
        <fo:table-cell><fo:block> 030</fo:block></fo:table-cell>
        <fo:table-cell><fo:block>1</fo:block></fo:table-cell>
</fo:table-row>
<fo:table-row>
        <fo:table-cell><fo:block>8910-276</fo:block></fo:table-cell>
        <fo:table-cell><fo:block> 01 02</fo:block></fo:table-cell>
        <fo:table-cell><fo:block> 000</fo:block></fo:table-cell>
        <fo:table-cell><fo:block>1</fo:block></fo:table-cell>
</fo:table-row> 
<fo:table-row>
        <fo:table-cell><fo:block>8910-281</fo:block></fo:table-cell>
        <fo:table-cell><fo:block> 01 01</fo:block></fo:table-cell>
        <fo:table-cell><fo:block> 001</fo:block></fo:table-cell>
        <fo:table-cell><fo:block>1</fo:block></fo:table-cell>
</fo:table-row>

Solution

  • If node-set() isn't working, then you need to do the sorting again just to get the previous item:

    <xsl:key name="all" match="catalogSeqNumber" use="true()" />
    
    <xsl:template name="SortParts">
      <xsl:apply-templates
          select="catalogSeqNumber[key('kfigNo', @figureNumber)]">
          <xsl:sort select="itemSeqNumber/partRef/@partNumberValue"/>
          <xsl:sort select="@figureNumber"/>
          <xsl:sort select="@item"/>
      </xsl:apply-templates>
    </xsl:template>
    
    <xsl:template match="catalogSeqNumber">
      <xsl:variable
          name="figNo"
          select="concat(@figureNumber,@figureNumberVariant)"/>
      <xsl:variable name="current-position" select="position()"/>
      <xsl:variable name="prfigNo">
        <xsl:for-each select="key('all', true())">
          <xsl:sort select="itemSeqNumber/partRef/@partNumberValue"/>
          <xsl:sort select="@figureNumber"/>
          <xsl:sort select="@item"/>
          <xsl:if test="position() = $current-position - 1">
            <xsl:value-of select="concat(@figureNumber,@figureNumberVariant)" />
          </xsl:if>
        </xsl:for-each>
      </xsl:variable>
      <fo:table-row>
        <fo:table-cell padding="3pt">
          <fo:block>
            <xsl:value-of
                select="itemSeqNumber/partRef/@partNumberValue"/>
          </fo:block>
        </fo:table-cell>
        <fo:table-cell padding="3pt">
          <fo:block>
            <xsl:if test="$figNo">
              <xsl:text> </xsl:text>
              <xsl:value-of select="$figNo"/>
              <xsl:text> </xsl:text>
              <xsl:value-of select="$prfigNo"/>
            </xsl:if>
          </fo:block> 
        </fo:table-cell>
        <fo:table-cell padding="3pt">
          <fo:block>
            <xsl:value-of select="concat(@item,@itemVariant)"/>
          </fo:block>
        </fo:table-cell>
        <fo:table-cell padding="3pt">
          <fo:block>
            <xsl:value-of
                select="itemSeqNumber/quantityPerNextHigherAssy"/>
          </fo:block>
        </fo:table-cell>
      </fo:table-row>
    </xsl:template>