2012-07-21 2 views
3

저는 xsl을 처음 사용합니다. 비슷한 것을 찾았지만 제 사용법에 맞게 조정할 수는 없습니다.XSLT - 인접한 요소를 특정 속성으로 묶는 방법

입력 :

<section> 
    <heading>some heading text</heading> 
    <amendment chapter="1"> 
    <foo/> 
    </amendment> 
    <amendment chapter="2"> 
    <bar/> 
    </amendment> 
    <amendment chapter="3"> 
    <baz/> 
    </amendment> 
    <heading>some heading text</heading> 
    <amendment chapter="1"> 
    <baz/> 
    </amendment> 
</section> 

속성 "장 = '1'또는 제 = '2' '와 소자 포장. 출력 :

<section> 
    <heading>some heading text</heading> 
    <newwrapper> 
    <amendment chapter="1"> 
     <foo/> 
    </amendment> 
    <amendment chapter="2"> 
     <bar/> 
    </amendment> 
    </newwrapper> 
    <amendment chapter="3"> 
    <baz/> 
    </amendment> 
    <heading>some heading text</heading> 
    <newwrapper> 
    <amendment chapter="1"> 
     <baz/> 
    </amendment> 
    </newwrapper> 
</section> 

답변

1

I.이 XSLT 2.0 변환 :

<section> 
    <heading>some heading text</heading> 
    <amendment chapter="1"> 
     <foo/> 
    </amendment> 
    <amendment chapter="2"> 
     <bar/> 
    </amendment> 
    <amendment chapter="3"> 
     <baz/> 
    </amendment> 
    <heading>some heading text</heading> 
    <amendment chapter="1"> 
     <baz/> 
    </amendment> 
</section> 

가 원하는 정확한 결과를 생성한다 : 제공된 XML 문서에 적용

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

<xsl:template match="/*"> 
    <section> 
    <xsl:for-each-group select="*" 
         group-adjacent="self::amendment and @chapter =(1,2)"> 
    <xsl:choose> 
     <xsl:when test="current-grouping-key()"> 
     <newwrapper> 
      <xsl:sequence select="current-group()"/> 
     </newwrapper> 
     </xsl:when> 
     <xsl:otherwise> 
     <xsl:sequence select="current-group()"/> 
     </xsl:otherwise> 
    </xsl:choose> 
    </xsl:for-each-group> 
    </section> 
</xsl:template> 
</xsl:stylesheet> 

:

<section> 
    <heading>some heading text</heading> 
    <newwrapper> 
     <amendment chapter="1"> 
       <foo/> 
     </amendment> 
     <amendment chapter="2"> 
       <bar/> 
     </amendment> 
    </newwrapper> 
    <amendment chapter="3"> 
      <baz/> 
     </amendment> 
    <heading>some heading text</heading> 
    <newwrapper> 
     <amendment chapter="1"> 
       <baz/> 
     </amendment> 
    </newwrapper> 
</section> 

설명 다음 group-adjacent 속성 xsl:for-each-group

적절한 사용.

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="kFollowing" match="amendment[not(@chapter >2)]" use= 
"generate-id(preceding-sibling::* 
       [not(self::amendment and @chapter &lt;= 2)][1])"/> 

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


<xsl:template match= 
"*[not(self::amendment and @chapter &lt;= 2) 
    and 
    following-sibling::*[1][self::amendment and not(@chapter >2)] 
    ]"> 
    <xsl:call-template name="identity"/> 
    <newwrapper> 
    <xsl:apply-templates mode="inGroup" 
         select="key('kFollowing', generate-id())"/> 
    </newwrapper> 
</xsl:template> 

<xsl:template match="*" mode="inGroup"> 
    <xsl:call-template name="identity"/> 
</xsl:template> 
<xsl:template match="amendment[not(@chapter >2)]"/> 
</xsl:stylesheet> 

, 동일 dorrect 결과를 생성한다.

설명 다음 identity rule

  1. 이 활용하고 오버라이드 (override) :

    적절한 사용. chapter 해당 그룹에 대한 직접적인 항 - 동위 원소의 generate-id()의 함수로서 2 이하인 특성으로

  2. Keys

    인접 amendment 요소의 그룹을 정의한다.

+0

XSLT 2.0 솔루션을 사용할 수 없습니다. 그리고 XSLT 1.0 솔루션은 어떤 이유로 작동하지 않습니다. 내가 얻는 결과는 다음과 같습니다.

일부 표제 텍스트 <개정 장 ="2 "> <개정 장 ="3 "> 일부 제목 텍스트
속성 챕터는 숫자가 아닌 문자열이어야합니다. –

+0

@dcdc : 죄송합니다. 이것은 불쾌한 SO 코드 형식화 버그입니다. XPath는 대개 XPath를 대체합니다 '[1]'을'[2]'와 비교하여 HTML 앵커라고 생각합니다. '[2]'를 지금 [1]'로 되돌리고, 변환은 원하는 결과를 생성한다. 시도 해봐. –

0

Dimitre Novatchev, 나는 특성을 문자열로 수정하고 xslt가 작동합니다. 감사.

<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="kFollowing" match="amendment[(@chapter='1' or @chapter='2')]" use="generate-id(preceding-sibling::*[not(self::amendment and (@chapter='1' or @chapter='2'))][1])"/> 
    <xsl:template match="node()|@*" name="identity"> 
     <xsl:copy> 
      <xsl:apply-templates select="node()|@*"/> 
     </xsl:copy> 
    </xsl:template> 
    <xsl:template match="*[not(self::amendment and (@chapter='1' or @chapter='2')) and following-sibling::*[1][self::amendment and (@chapter='1' or @chapter='2')]]"> 
     <xsl:call-template name="identity"/> 
     <newwrapper> 
      <xsl:apply-templates mode="inGroup" select="key('kFollowing', generate-id())"/> 
     </newwrapper> 
    </xsl:template> 
    <xsl:template match="*" mode="inGroup"> 
     <xsl:call-template name="identity"/> 
    </xsl:template> 
    <xsl:template match="amendment[(@chapter='1' or @chapter='2')]"/> 
</xsl:stylesheet> 
관련 문제