基于属性将元素分组到新元素

时间:2015-01-13 15:16:24

标签: xslt

我需要将没有属性的元素分组到一个新元素中。取决于属性@single h2应该放在新容器中,还是与h2s按顺序分组而没有@single的位置。我正在与小组争论2,3,4。我是否需要为h1创建一个模板,然后我们为xsl:for-each创建一个模板?有更聪明的方法吗?

来源:

<h1>
    <h2 single="true" />
    <h2 single="true" />
    <h2>1</h2>
    <h2 single="true" />
    <h2>2</h2>
    <h2>3</h2>
    <h2>4</h2>
    <h2 single="true" />
    <h2>5</h2>
</h1>

结果

<h1>
    <containertypeA>
        <h2 single="true" />
    </containertypeA>
    <containertypeA>
        <h2 single="true" />
    </containertypeA>
    <containertypeB>
        <h2>1</h2>
    </containertypeB>
    <containertypeA>
        <h2 single="true" />
    </containertypeA>
    <containertypeB>
        <h2>2</h2>
        <h2>3</h2>
        <h2>4</h2>
    </containertypeB>
    <containertypeA>
        <h2 single="true" />
    </containertypeA>
    <containertypeB>
        <h2>5</h2>
    </containertypeB>
</h1>

1 个答案:

答案 0 :(得分:0)

一种可能的XSLT 1.0解决方案是遵循XSLT:

<?xml version="1.0" encoding="UTF-8" ?>
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 version="1.0">
<xsl:output method="xml" omit-xml-declaration="yes" encoding="UTF-8" 
 indent="yes" />
<xsl:strip-space elements="*"/>
  <xsl:template match="/">
    <xsl:apply-templates/> 
  </xsl:template>
  <xsl:template match="@*|node()">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
  </xsl:template>
  <xsl:template match="h2[@single='true']">
    <containertypeA>
      <xsl:copy>
        <xsl:apply-templates select="@*|node()"/>
      </xsl:copy>
    </containertypeA>
  </xsl:template> 
  <xsl:template match="h2[not(@single='true') and 
       not(preceding-sibling::h2[1][not(@single='true')])]">
    <containertypeB>
      <xsl:copy>
        <xsl:apply-templates select="@*|node()"/>
      </xsl:copy>
      <xsl:for-each select="following-sibling::h2[1][not(@single='true')]">
        <xsl:apply-templates select="." mode="sibling"/>
      </xsl:for-each>
    </containertypeB>
  </xsl:template>
  <xsl:template match="h2" mode="sibling">
    <xsl:apply-templates select="." mode="copy"/>
      <xsl:for-each select="following-sibling::h2[1][not(@single='true')]">
        <xsl:apply-templates select="." mode="sibling"/>
      </xsl:for-each>
  </xsl:template>
  <xsl:template match="h2[not(@single='true') and 
   preceding-sibling::h2[1][not(@single='true')]]" mode="copy">
    <xsl:copy-of select="."/>
  </xsl:template>
  <xsl:template match="h2[not(@single='true') and 
    preceding-sibling::h2[1][not(@single='true')]]"/>
</xsl:transform>

当应用于输入XML时产生输出

<h1>
   <containertypeA>
      <h2 single="true"/>
   </containertypeA>
   <containertypeA>
     <h2 single="true"/>
   </containertypeA>
   <containertypeB>
     <h2>1</h2>
   </containertypeB>
   <containertypeA>
     <h2 single="true"/>
   </containertypeA>
   <containertypeB>
     <h2>2</h2>
     <h2>3</h2>
     <h2>4</h2>
   </containertypeB>
   <containertypeA>
     <h2 single="true"/>
   </containertypeA>
   <containertypeB>
     <h2>5</h2>
   </containertypeB>
</h1>

模板

<xsl:template match="h2[@single='true']">

h2中复制每个匹配的<containertypeA> 模板

<xsl:template match="h2[not(@single='true') and 
     not(preceding-sibling::h2[1][not(@single='true')])]">

将没有h2属性且价值为@single的所有true与没有h2的前一个兄弟@single='true'匹配。此模板将匹配的h2包含在<containertypeB>中,并将template mode="sibling"应用于以下第一个没有@single='true'的兄弟:

<xsl:for-each select="following-sibling::h2[1][not(@single='true')]">
  <xsl:apply-templates select="." mode="sibling"/>

<xsl:template match="h2" mode="sibling">使用模板复制h2模式=&#34;复制&#34;:

 <xsl:apply-templates select="." mode="copy"/>

并适用于所有以下没有@single='true'的第一个兄弟姐妹:

<xsl:for-each select="following-sibling::h2[1][not(@single='true')]">
  <xsl:apply-templates select="." mode="sibling"/>
</xsl:for-each>

最后,空模板

<xsl:template match="h2[not(@single='true') and 
preceding-sibling::h2[1][not(@single='true')]]"/>

匹配已复制到h2的所有<containertypeB>元素。