2013-05-28 120 views
2

相等的節點應置於單個計數器元素下。 輸入:節點上的XSLT 1.0邏輯

<Move-Afile> 
    <Afile> 
    <Item> 
    <PACK050> 
     <PackNumber>1234</PackNumber> 
     </PACK050> 
    </Item> 
    <Item> 
    <PACK050> 
     <PackNumber>567</PackNumber> 
     </PACK050> 
    </Item> 
    <Item> 
    <PACK050> 
     <PackNumber>567</PackNumber> 
     </PACK050> 
    </Item> 
    <Item> 
    <PACK050> 
     <PackNumber>126</PackNumber> 
     </PACK050> 
    </Item> 
    <Item> 
    <PACK050> 
     <PackNumber>567</PackNumber> 
     </PACK050> 
    </Item> 
    </Afile> 
</Move-Afile> 

因爲我們需要增加計數器變量中的每個包號,但這裏有一個條件是存在一樣,如果以前是等於當前我們必須忽略計數器(有沒有需要增加)像下面的output.all相等的節點下一個計數器下面的輸出。

XSLT模板應該包含如下結構的<for-each>

<xsl:template match="/"> 
    <A> 
    <target> 
     <xsl:for-each select="/Move-Afile/Afile/Item/PACK050/PackNumber"> 

     <xsl:variable name="count"> 
      <!-- get the count here--> 
     </xsl:variable> 

     <counter>$count</counter> 
     <PNumber><xsl:value-of select="."/></PNumber> 

     </xsl:for-each> 
    </target> 
    </A> 
</xsl:template> 

輸出:

<A> 
    <target> 
    <Item> 
    <PACK050> 
     <counter>1</counter><!-- if previous <PackNumber> is not equal to current <PackNumber> increment the count--> 
     <PNumber>1234</PNumber> 
     </PACK050> 
    </Item> 
    <Item 
    <PACK050> 
     <counter>2</counter><!-- if previous <PackNumber> is not equal to current <PackNumber> increment the count--> 
     <PNumber>567</PNumber> 
     </PACK050> 
    </Item> 
    <Item><!-- if previous <PackNumber> is equal to current <PackNumber> ignore the counter --> 
     <PACK050> 
     <PNumber>567</PNumber> 
     </PACK050> 
    </Item> 
    <Item><!-- if previous <PackNumber> is equal to current <PackNumber> ignore the counter --> 
     <PACK050> 
     <PNumber>567</PNumber> 
     </PACK050> 
    </Item> 
    <Item> 
    <PACK050> 
     <counter>3</counter><!-- if previous <PackNumber> is not equal to current <PackNumber> increment the count--> 
     <PNumber>126</PNumber> 
     </PACK050> 
    </Item> 

    </target> 
</A> 

回答

2

此問題實際上可以通過使用公知的Muenchian分組的方法對XSLT 1.0來解決。

當該XSLT:

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

    <xsl:key name="kItemByPackNo" match="Item" use="*/PackNumber"/> 

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

    <xsl:template match="/*"> 
    <A> 
     <target> 
     <xsl:apply-templates 
      select="*/Item[generate-id() = 
         generate-id(key('kItemByPackNo', */PackNumber)[1])]"/> 
     </target> 
    </A> 
    </xsl:template> 

    <xsl:template match="Item"> 
    <Item> 
     <counter> 
     <xsl:value-of select="position()"/> 
     </counter> 
     <xsl:apply-templates/> 
    </Item> 
    <xsl:copy-of 
     select="key('kItemByPackNo', */PackNumber)[ 
       not(generate-id() = generate-id(current())) 
       ]"/> 
    </xsl:template> 

    <xsl:template match="PackNumber"> 
    <PNumber> 
     <xsl:apply-templates/> 
    </PNumber> 
    </xsl:template> 

</xsl:stylesheet> 

...抵靠提供的XML應用:

<Move-Afile> 
    <Afile> 
    <Item> 
     <PACK050> 
     <PackNumber>1234</PackNumber> 
     </PACK050> 
    </Item> 
    <Item> 
     <PACK050> 
     <PackNumber>567</PackNumber> 
     </PACK050> 
    </Item> 
    <Item> 
     <PACK050> 
     <PackNumber>567</PackNumber> 
     </PACK050> 
    </Item> 
    <Item> 
     <PACK050> 
     <PackNumber>126</PackNumber> 
     </PACK050> 
    </Item> 
    <Item> 
     <PACK050> 
     <PackNumber>567</PackNumber> 
     </PACK050> 
    </Item> 
    </Afile> 
</Move-Afile> 

...所期望的結果是產生的:

<A> 
    <target> 
    <Item> 
     <counter>1</counter> 
     <PACK050> 
     <PNumber>1234</PNumber> 
     </PACK050> 
    </Item> 
    <Item> 
     <counter>2</counter> 
     <PACK050> 
     <PNumber>567</PNumber> 
     </PACK050> 
    </Item> 
    <Item> 
     <PACK050> 
     <PackNumber>567</PackNumber> 
     </PACK050> 
    </Item> 
    <Item> 
     <PACK050> 
     <PackNumber>567</PackNumber> 
     </PACK050> 
    </Item> 
    <Item> 
     <counter>3</counter> 
     <PACK050> 
     <PNumber>126</PNumber> 
     </PACK050> 
    </Item> 
    </target> 
</A> 
3

不要認爲它是遞增計數器,可以認爲它是分組類似的節點。你在這裏要做的是將Item元素分組PackNumber,然後爲每個組寫出第一個匹配的Item,其值爲counter,其餘值不包含。

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> 
    <xsl:key name="itemByPnum" match="Item" use="PACK050/PackNumber" /> 

    <xsl:template match="/"> 
    <A> 
     <target> 
     <xsl:apply-templates select="Move-Afile/Afile/Item[generate-id() = 
      generate-id(key('itemByPnum', PACK050/PackNumber)[1])]" /> 
     </target> 
    </A> 
    </xsl:template> 

    <xsl:template match="Item"> 
    <xsl:apply-templates select="." mode="copy"> 
     <xsl:with-param name="counter"> 
     <counter><xsl:value-of select="position()" /></counter> 
     </xsl:with-param> 
    </xsl:apply-templates> 
    <!-- copy without the <counter> all matching Items except the first one --> 
    <xsl:apply-templates mode="copy" 
      select="key('itemByPnum', PACK050/PackNumber) 
      [generate-id() != generate-id(current())]" /> 
    </xsl:template> 

    <xsl:template match="Item" mode="copy"> 
    <xsl:param name="counter" /> 
    <Item> 
     <PACK050> 
     <xsl:copy-of select="$counter" /> 
     <PNumber><xsl:value-of select="PACK050/PackNumber" /></PNumber> 
     </PACK050> 
    </Item> 
    </xsl:template> 
</xsl:stylesheet> 

這是一個稱爲Muenchian分組的技術示例。 /模板中的初始apply-templates提取了第一個Item,其中每個PackNumberItem模板然後爲該組生成正確的輸出。

+0

+1我的回答有些sl;,你的更完整。 – ABach