2012-07-21 63 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> 
相關問題