2012-01-07 4 views
0

입력 XML을 가진 요소에 대한 목록을 작성 :머리를

<root>  
    <com>  
     <head>A</head>  
     <body>Type A</body>  
    </com>  
    <com>  
     <head>B</head>  
     <body>Type B</body>  
    </com>  
    <com>  
     <head>C</head>  
     <body>Type C</body>   
    </com> 
    <com>  
     <head>D</head> 
     <body>Type D</body>  
    </com>  
    <com>  
     <body>Type No</body>  
    </com> 
    <plom>xml type X</plom> 
    <plom>xml type Y</plom> 
    <com>  
     <head>a</head>  
     <body>Type a</body>  
    </com>  
    <com>    <head>b</head>  
     <body>Type c</body>  
    </com>  
    </root>  

필요한 출력 XML :

<root>        
    <l>     
     <li>    
     <lab>A</lab>    
     <text>Type A</text>   
     </li>    
     <li>    
     <lab>B</lab>    
     <text>Type B</text>   
     </li>    
     <li>    
     <lab>C</lab>    
     <text>Type C</text>   
     </li>    
     <li>    
     <lab>D</lab>    
     <text>Type D</text>   
     </li>    
     </l>     
     <p>Type No</p>    
     <p>xml type X</p>   
     <p>xml type Y</p>  
     <l>    
     <li>   
     <lab>a</lab>   
     <text>Type a</text>  
     </li>   
     <li>   
     <lab>b</lab>   
     <text>Type b</text>  
     </li>   
    </l>    
    </root>    

위에 표시된 입력에서 필요한 출력을 얻기에서 저를 도와주십시오. 요구 사항 : com/head이 올 경우 l/li으로 출력되어야합니다. 그러나 머리가있는 <com> 또는 <com> 이외의 요소가 발견되면 <l>이 닫히고 그 요소는 <p>이되고 com/head이 다시 발생하면 <l>이 생성되어야합니다.

+0

(팁 : XML을 그대로 붙여넣고 편집기에서'{} '버튼을 클릭하십시오.) – Mat

+0

선행 형제를 사용해 보았습니다.하지만 여기 저기에 부서지고 있습니다 ...! – Gracious

+0

xslt도 추가하십시오. – rene

답변

0

I.이 XSLT 2.0 변환 :

<root> 
    <l> 
     <li> 
     <lab>A</lab> 
     <type>Type A</type> 
     </li> 
     <li> 
     <lab>B</lab> 
     <type>Type B</type> 
     </li> 
     <li> 
     <lab>C</lab> 
     <type>Type C</type> 
     </li> 
     <li> 
     <lab>D</lab> 
     <type>Type D</type> 
     </li> 
    </l> 
    <p>Type No</p> 
    <p>xml type X</p> 
    <p>xml type Y</p> 
    <l> 
     <li> 
     <lab>a</lab> 
     <type>Type a</type> 
     </li> 
     <li> 
     <lab>b</lab> 
     <type>Type b</type> 
     </li> 
    </l> 
</root> 
:

<root> 
    <com> 
     <head>A</head> 
     <body>Type A</body> 
    </com> 
    <com> 
     <head>B</head> 
     <body>Type B</body> 
    </com> 
    <com> 
     <head>C</head> 
     <body>Type C</body> 
    </com> 
    <com> 
     <head>D</head> 
     <body>Type D</body> 
    </com> 
    <com> 
     <body>Type No</body> 
    </com> 
    <plom>xml type X</plom> 
    <plom>xml type Y</plom> 
    <com> 
     <head>a</head> 
     <body>Type a</body> 
    </com> 
    <com> 
     <head>b</head> 
     <body>Type b</body> 
    </com> 
</root> 

가 원하는 정확한 결과 생산 : 제공된 XML 문서 적용

<xsl:stylesheet version="2.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output omit-xml-declaration="yes" indent="yes"/> 
<xsl:strip-space elements="*"/> 

<xsl:template match="/"> 
    <root> 
    <xsl:for-each-group select="/*/*" 
     group-adjacent="boolean(self::com/head)"> 
     <xsl:apply-templates select="current-group()[1]"> 
     <xsl:with-param name="pGroup" select="current-group()"/> 
     </xsl:apply-templates> 
    </xsl:for-each-group> 
    </root> 
</xsl:template> 

<xsl:template match="com[head]"> 
    <xsl:param name="pGroup"/> 
    <l> 
    <xsl:apply-templates select="$pGroup" mode="inGroup"/> 
    </l> 
</xsl:template> 

<xsl:template match="com[head]" mode="inGroup"> 
    <li> 
    <lab><xsl:value-of select="head"/></lab> 
    <type><xsl:value-of select="body"/></type> 
    </li> 
</xsl:template> 

<xsl:template match="*[not(self::com/head)]"> 
    <xsl:param name="pGroup"/> 

    <xsl:apply-templates select="$pGroup" mode="inGroup"/> 
</xsl:template> 

<xsl:template match="*[not(self::com/head)]" mode="inGroup"> 
    <p><xsl:value-of select="."/></p> 
</xsl:template> 
</xsl:stylesheet> 

(210)

설명 : <xsl:for-each-group group-adjacent="...">

  1. 사용. 인접 요소의 선택된 그룹은 각각 boolean(self::com/head) - 모두 true() 또는 모두 거짓 false()에 대해 동일한 값을 갖습니다.

  2. 각 그룹의 첫 번째 요소 처리 만 지정되어 그룹의 모든 요소 시퀀스를 매개 변수로 제공합니다.

  3. 요소 아이 head을 갖는다 com 템플레이트 매칭 (이이 첫번째 요소가 그룹에있는 경우에만 실행을 위해 선택된다)은, l 요소 그룹의 요소의 처리 결과를 모두 감싸는

    후 모드 inGroup에서 그룹의 개별 요소 처리를 시작합니다.

  4. 다른 템플레이트 매칭 (생략 comhead 아이 갖는()가이 그룹의 첫 번째 요소 인 경우에만 실행되도록 선택된다) 단순히 모드 그룹의 개별 요소의 처리를 개시 소자 inGroup

II. XSLT 1.0 용액 :

(위) 같은 XML 문서에 적용
<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output omit-xml-declaration="yes" indent="yes"/> 
<xsl:strip-space elements="*"/> 

<xsl:key name="kComHeadGroup" match="com[head]" 
    use="generate-id(following-sibling::*[not(self::com[head])][1])"/> 

<xsl:key name="kNonComHeadGroup" match="*[not(self::com/head)]" 
    use="generate-id(following-sibling::*[(self::com[head])][1])"/> 

<xsl:template match="/"> 
    <root> 
    <xsl:apply-templates select="/*/*[1]"/> 
    </root> 
</xsl:template> 

<xsl:template match= 
    "com[head 
    and 
     not(preceding-sibling::*[1]/self::com[head]) 
     ]"> 

    <l> 
    <xsl:apply-templates mode="inGroup" select= 
    "key('kComHeadGroup', 
     generate-id 
      (following-sibling::* 
       [not(self::com[head])] 
            [1] 
      ) 
     )"/> 
    </l> 

    <xsl:apply-templates select= 
    "following-sibling::* 
       [not(self::com[head])] 
            [1] 
    "/> 
    </xsl:template> 

<xsl:template match="com[head]" mode="inGroup"> 
    <li> 
    <lab><xsl:value-of select="head"/></lab> 
    <type><xsl:value-of select="body"/></type> 
    </li> 
</xsl:template> 

<xsl:template match="*[not(self::com/head)]"> 
    <xsl:apply-templates mode="inGroup" select= 
    "key('kNonComHeadGroup', 
     generate-id(following-sibling::*[(self::com[head])][1]) 
    ) 
    "/> 
    <xsl:apply-templates select= 
    "following-sibling::com[head][1]"/> 
</xsl:template> 

<xsl:template match="*[not(self::com/head)]" mode="inGroup"> 
    <p><xsl:value-of select="."/></p> 
</xsl:template> 
</xsl:stylesheet> 

은, 다시 같은 원하는은 정확한 결과를 생성한다 :

<root> 
    <l> 
     <li> 
     <lab>A</lab> 
     <type>Type A</type> 
     </li> 
     <li> 
     <lab>B</lab> 
     <type>Type B</type> 
     </li> 
     <li> 
     <lab>C</lab> 
     <type>Type C</type> 
     </li> 
     <li> 
     <lab>D</lab> 
     <type>Type D</type> 
     </li> 
    </l> 
    <p>Type No</p> 
    <p>xml type X</p> 
    <p>xml type Y</p> 
    <l> 
     <li> 
     <lab>a</lab> 
     <type>Type a</type> 
     </li> 
     <li> 
     <lab>b</lab> 
     <type>Type b</type> 
     </li> 
    </l> 
</root> 

설명 : 똑같은 로직 등을 XSLT 2.0 솔루션에 있지만 그룹화 구현에서는 키를 사용합니다.

+0

이것은 대단합니다 .. 감사합니다. Dimitre. 솔루션은 완벽합니다. XSLT 2.0에서 "네임 스페이스의 요소 템플릿 http://www.w3.org/1999/XSL/Transform에 잘못된 자식 요소 'for-each-group'이 있지만 문제가 발생했지만 XSLT 1.0은 아무 문제없이 작동했습니다. 도움과 훌륭한 솔루션에 감사드립니다. :) – Gracious

+0

@Gracious : 오신 것을 환영합니다. 이 오류는 XSLT 프로세서가 XSLT 2.0 프로세서가 아니라는 것을 의미합니다 (XSLT 1.0 만 처리 할 수 ​​있음). 답변을 수락하십시오 (옆에있는 체크 표시를 클릭하십시오). –

+0

맞습니다. 하지만 난 XSLT 1.0 솔루션으로 좋다. 지식을 공유해 주셔서 다시 한번 감사드립니다. – Gracious

관련 문제