3

我是 xsl 的新手。我发现了类似的东西,但不能完全适应我的使用。

输入:

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

用属性“chapter='1' or chapter='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>
4

2 回答 2

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-groupwithgroup-adjacent属性。


二、XSLT 1.0 解决方案

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

当此转换应用于同一个 XML 文档(上图)时,会产生相同的、正确的结果

说明

正确使用:

  1. 使用和覆盖身份规则

  2. 用于定义属性不大于的一组相邻amendment元素的键,作为该组的前一个兄弟元素的函数chapter2generate-id()

于 2012-07-21T23:33:09.350 回答
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>
于 2012-07-27T16:08:20.613 回答