2012-07-21 87 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转化

<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> 

当所提供的XML文档应用:

<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> 

产生想要的,正确的结果:

<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> 

说明

正确使用xsl:for-each-groupgroup-adjacent属性。


二, XSLT 1.0解

当这种转化是在同一个XML文档(以上)应用,同样的,dorrect结果产生

说明

正确使用方法:

  1. 利用和压倒一切的identity rule

  2. Keys以限定一组相邻amendment元素与属性chapter不大于2更大,由于该组的直接前同辈元件的generate-id()的功能。

+0

我无法使用XSLT 2.0解决方案。由于某些原因,XSLT 1.0解决方案不起作用。我得到的输出是:

某些标题文本 <修正案章=” 2 “> <修正案章=” 3 “> 一些标题文本
而属性章节需要是字符串,而不是数字 – 2012-07-26 21:46:57

+0

@dcdc:对不起,这是一个令人讨厌的SO代码格式化错误 - 它经常替代XPath ''[1]'用'[2]',认为这是一个HTML锚点现在将[2]'回到[1]'并且转换产生(再次:))所需的结果。尝试一下。 – 2012-07-26 23:53:35

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> 
相关问题