2013-05-28 7 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 grouping. Начальный apply-templates в шаблоне / извлекает первыйItem с каждым PackNumber, тогда шаблон Item генерирует правильный выход для этой группы.

+0

+1 Я был немного небрежным в своем ответе; ваш более совершенен. – ABach