2014-12-04 2 views
0

입력 :그룹화의 그룹화 된 데이터

<persons> 
    <person name="John" role="Writer"/> 
    <person name="John" role="Poet"/> 
    <person name="Jacob" role="Writer"/> 
    <person name="Jacob" role="Poet"/> 
    <person name="Joe" role="Poet"/> 
</persons> 

예상 출력 :

<groups> 
    <group roles="Wriet, Poet" persons="John, Jacob"/> 
    <group roles="Poet" persons="Joe"/> 
</groups> 

위의 예에서와 같이, 나는 첫 번째 사람의 이름을 그룹에 필요 모든 사람의 역할을 찾을 수 있습니다. 두 명 이상의 사람이 동일한 역할 세트를 갖고있는 경우 (예 : John과 Jacob이 모두 작가이자 시인 인 경우) 각 역할 세트를 그룹화하고 사람 이름을 나열해야합니다.

I 등 Muenchian 방법 또는 EXSLT set:distinct을 사용하여 그룹핑의 제 수준이 할 수

위는 XSLT 1.0 EXSLT하여 형질 전환
<groups> 
    <group roles="Wriet, Poet" persons="John"/> 
    <group roles="Wriet, Poet" persons="Jacob"/> 
    <group roles="Poet" persons="Joe"/> 
</groups> 

:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:sets="http://exslt.org/sets" extension-element-prefixes="sets"> 
    <xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/> 
    <xsl:key name="persons-by-name" match="person" use="@name"/> 
    <xsl:template match="persons"> 
     <groups> 
      <xsl:for-each select="sets:distinct(person/@name)"> 
       <group> 
        <xsl:attribute name="persons"><xsl:value-of select="."/></xsl:attribute> 
        <xsl:attribute name="roles"> 
         <xsl:for-each select="key('persons-by-name', .)"> 
          <xsl:value-of select="@role"/> 
          <xsl:if test="position()!=last()"><xsl:text>, </xsl:text></xsl:if> 
         </xsl:for-each> 
        </xsl:attribute> 
       </group> 
      </xsl:for-each> 
     </groups> 
    </xsl:template> 
</xsl:stylesheet> 

하지만, I가 필요 그룹화 된 역할을 그룹화하는 방법을 이해하는 데 도움이됩니다.

XSLT 1.0 솔루션을 사용할 수없는 경우 XSLT 2.0 접근 방식을 적극 권장하십시오.

+1

당신은 XSLT를 표시 할 수 있습니다 현재 출력을 얻으려고 현재 사용하고 있습니까? 감사! –

+0

@ TimC 물론, 내 질문에 EXSLT 버전을 추가했습니다. – Somu

답변

1

이렇게 해보시겠습니까?

는 XSLT 1.0

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
xmlns:exsl="http://exslt.org/common" 
xmlns:set="http://exslt.org/sets" 
extension-element-prefixes="exsl set"> 
<xsl:output method="xml" encoding="UTF-8" indent="yes" /> 

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

<xsl:variable name="distinct-persons"> 
    <xsl:for-each select="set:distinct(/persons/person/@name)"> 
     <person name="{.}"> 
      <xsl:attribute name="roles"> 
       <xsl:for-each select="key('person-by-name', .)/@role"> 
        <xsl:sort/> 
        <xsl:value-of select="." /> 
        <xsl:if test="position()!=last()"> 
         <xsl:text>, </xsl:text> 
        </xsl:if> 
       </xsl:for-each> 
      </xsl:attribute> 
     </person> 
    </xsl:for-each> 
</xsl:variable> 

<xsl:template match="/"> 
    <groups> 
     <xsl:for-each select="set:distinct(exsl:node-set($distinct-persons)/person/@roles)"> 
      <group roles="{.}"> 
       <xsl:attribute name="names"> 
        <xsl:for-each select="key('person-by-roles', .)/@name"> 
         <xsl:value-of select="." /> 
         <xsl:if test="position()!=last()"> 
          <xsl:text>, </xsl:text> 
         </xsl:if> 
        </xsl:for-each> 
       </xsl:attribute> 
      </group> 
     </xsl:for-each> 
    </groups> 
</xsl:template> 


</xsl:stylesheet> 

결과 (EXSLT 노드 집합()와 별개의() 함수를 사용하여) :

<?xml version="1.0" encoding="UTF-8"?> 
<groups> 
    <group roles="Poet, Writer" names="John, Jacob"/> 
    <group roles="Poet" names="Joe"/> 
</groups> 
+0

'xalan-j 2.7.2' 해석 프로세서에서는 잘 작동하지만 XSLTC 프로세서에서는 잘 동작하지 않습니다. Java 1.7.0_71 또는 1.8.0_25와 함께 번들로 제공되는 기본 xalan 프로세서에서도 작동하지 않습니다. – Somu

+0

그것은 거의 놀라운 일이 아닙니다. –

1

나는 당신이 이미했던 것과 똑같은 일을 한 다음 단계를 더 진행하고 다시 그룹화했습니다. 지금은 귀하의 의견과 함께 다음과 같은 출력을 얻을 :

<?xml version="1.0" encoding="UTF-8"?> 
<groups> 
    <group roles="Writer,Poet" persons="John,Jacob"/> 
    <group roles="Poet" persons="Joe"/> 
</groups> 

이 역할도 분류 얻을 XSLT 2.0

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet xmlns="" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:avintis="http://www.avintis.com/esb" exclude-result-prefixes="#all" version="2.0"> 
    <xsl:output method="xml" encoding="UTF-8" indent="yes"/> 

    <xsl:template match="/persons"> 
     <groups> 
      <xsl:variable name="persons" select="."/> 

      <!-- create a temporary variable containing all roles of a person --> 
      <xsl:variable name="roles"> 
       <xsl:for-each select="distinct-values(person/@name)"> 
        <xsl:sort select="."/> 
        <xsl:variable name="name" select="."/> 
        <xsl:element name="group"> 
         <xsl:attribute name="roles"> 
          <!-- sort the roles of each person --> 
          <xsl:variable name="rolesSorted"> 
           <xsl:for-each select="$persons/person[@name=$name]"> 
            <xsl:sort select="@role"/> 
            <xsl:copy-of select="."/> 
           </xsl:for-each> 
          </xsl:variable> 
          <xsl:value-of select="string-join($rolesSorted/person/@role,',')"/> 
         </xsl:attribute> 
         <xsl:attribute name="persons" select="."/> 
        </xsl:element> 
       </xsl:for-each> 
      </xsl:variable> 

      <!-- now loop again over all roles of the persons and group persons having the same roles --> 
      <xsl:for-each select="distinct-values($roles/group/@roles)"> 
       <xsl:element name="group"> 
        <xsl:variable name="name" select="."/> 
        <xsl:attribute name="roles" select="$name"/> 
        <xsl:attribute name="persons"> 
         <xsl:value-of select="string-join($roles/group[@roles=$name]/@persons,',')"/> 
        </xsl:attribute> 
       </xsl:element> 
      </xsl:for-each> 
     </groups> 
    </xsl:template> 

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

</xsl:stylesheet> 

입니다 - 역할과 사람들의 입력 순서에서 너무 독립적.

+1

아름다운. 첫 번째 그룹핑의 결과를 변수로 가져와 올바른 위치에 놓습니다. 감사! 그러나 그는 XSLT 1.0 솔루션을 제공하면서 @ michael.hor257k의 대답을 받아들입니다. – Somu

관련 문제