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

하지만 여기에 하나 개의 조건이 이의 제기를 무시해야 할 전류 같다 이전 경우처럼 존재 같은 (증가 할 필요가 없다) 아래 출력과 같은 하나의 카운터 아래에 동일한 노드가 있습니다.

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

이 문제가 실제로 XSLT 1.0 공지 Muenchian 그룹화 방법을 이용하여 해결 될 수있다.

이 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으로 그룹화 한 다음 각 그룹에 대해 counter 값을 갖는 첫 번째 일치 항목 Item을 쓰고 나머지는 제외합니다.

<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과 각 PackNumber을 추출한 다음 Item 템플릿은 해당 그룹의 올바른 출력을 생성합니다.

+0

+1 나는 내 대답에 조금 엉성했다. 네가 더 완벽 해. – ABach