2013-05-28 82 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