2013-09-16 4 views
0

xml에서 중복을 검색하고 모든 복제를 하나의 노드로 집계하는 방법이 있는지 궁금합니다. F.eksXSLT와 xpath v1.0은 중복을 찾고 집계합니다

<car name="one"> 
<person>john</person> 
<person>Jay</person> 
</car> 
<car name="two"> 
<person>kim</person> 
<person>chris</person> 
</car> 
<car name="one"> 
<person>jane</person> 
<person>liz</person> 
</car> 

은 다음과 같아야합니다

<car name="one"> 
<person>john</person> 
<person>Jay</person> 
<person>jane</person> 
<person>liz</person> 
</car> 
<car name="two"> 
<person>kim</person> 
<person>chris</person> 
</car> 

모든 도움을 많이 감사합니다!

브롬 김

+0

키 기능을 사용해야합니다. –

+0

나는 이것에 관해 갈 여러 가지 방법이 있다고 생각하지만, 당신이 찾고있는 것들 중 하나는 "모든 중복을 제거"하는 것이다. "following-sibling :: car [@name =./@ name]"셀렉터를 사용하면 여기에서 시작할 수 있습니다. –

답변

1

XSLT 1.0에서는 keygenerate-id 함수를 사용하여 요소를 그룹화하는 과정 인 Muenchian Method을 사용해야합니다.

과정은 이런 식입니다 :

먼저 당신이 그룹에 원하는 데이터를 나타내는 키를 정의합니다.

<xsl:key name="car-by-name" match="car" use="@name"/> 

그런 다음 해당 키를 기반으로 ID를 생성하여 템플릿 일치에서 해당 키를 사용합니다.

<xsl:apply-templates select="car[generate-id() = generate-id(key('car-by-name', @name)[1])]" mode="group"/> 

이제 노드를 그룹화 했으므로이 키를 다시 사용하여 해당 키 내의 모든 노드를 가져옵니다. 당신이 (가 잘 형성 할 document 추가)이 XML을 때 그래서 지금

<xsl:apply-templates select="key('car-by-name', @name)"/> 

는 모두 함께 표시합니다.

<document> 
    <car name="one"> 
    <person>john</person> 
    <person>Jay</person> 
    </car> 
    <car name="two"> 
    <person>kim</person> 
    <person>chris</person> 
    </car> 
    <car name="one"> 
    <person>jane</person> 
    <person>liz</person> 
    </car> 
</document> 

그리고이 XSLT

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output method="xml" indent="yes" /> 
    <xsl:key name="car-by-name" match="car" use="@name"/> 

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

    <xsl:template match="document"> 
    <xsl:copy> 
     <xsl:apply-templates select="car[generate-id() = generate-id(key('car-by-name', @name)[1])]" mode="group"/> 
    </xsl:copy> 
    </xsl:template> 

    <xsl:template match="car" mode="group"> 
    <car name="{@name}"> 
     <xsl:apply-templates select="key('car-by-name', @name)"/> 
    </car> 
    </xsl:template> 

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

</xsl:stylesheet> 

그것은이 결과를 생성을 적용합니다.

<?xml version="1.0" encoding="UTF-8"?> 
<document> 
    <car name="one"> 
    <person>john</person> 
    <person>Jay</person> 

    <person>jane</person> 
    <person>liz</person> 
    </car> 
    <car name="two"> 
    <person>kim</person> 
    <person>chris</person> 
    </car> 
</document> 
+0

아하! 고맙습니다. – user2783955

1

당신은 다음과 같이 xsl:for-each-group를 사용할 수있다 XSLT 2.0을 사용하는 경우 다음과 같은 입력에 적용 할 때

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/> 

    <xsl:template match="/data"> 
     <data> 
      <xsl:for-each-group select="car" group-by="@name"> 
       <car name="{current-grouping-key()}"> 
        <xsl:for-each select="current-group()/person"> 
         <person><xsl:value-of select="." /></person> 
        </xsl:for-each> 
       </car> 
      </xsl:for-each-group> 
     </data> 
    </xsl:template> 
</xsl:stylesheet> 

가 :

<?xml version="1.0" encoding="UTF-8"?> 
<data> 
    <car name="one"> 
     <person>john</person> 
     <person>Jay</person> 
    </car> 
    <car name="two"> 
     <person>kim</person> 
     <person>chris</person> 
    </car> 
    <car name="one"> 
     <person>jane</person> 
     <person>liz</person> 
    </car> 
</data> 

그것은 올바른 생산 출력 :

<?xml version="1.0" encoding="UTF-8"?> 
<data> 
    <car name="one"> 
     <person>john</person> 
     <person>Jay</person> 
     <person>jane</person> 
     <person>liz</person> 
    </car> 
    <car name="two"> 
     <person>kim</person> 
     <person>chris</person> 
    </car> 
</data> 
관련 문제