xsl将其他节点之间的节点分组?

时间:2010-10-27 17:55:23

标签: xslt xpath

我无法弄清楚create xsl如何在其他节点之间对某些节点进行分组。基本上,每当我看到'SPLIT'时,我必须结束div并创建一个新的。

xml看起来像这样:

<data name="a" />
<data name="b" />
<data name="c" />
<data name="SPLIT" />
<data name="d" />
<data name="e" />
<data name="SPLIT" />
<data name="f" />
<data name="g" />
<data name="h" />

输出需要看起来像这样

<div>
a
b
c
</div>

<div>
d
e
</div>

<div>
f
g
h
</div>

我知道如何通过'作弊'来做到这一点,但想知道是否有正确的方法:

<div>
<xsl:for-each select="data">
    <xsl:choose>
    <xsl:when test="@name='SPLIT'">
        <xsl:text disable-output-escaping="yes"> &lt;/div&gt; &lt;div&gt;</xsl:text>
    </xsl:when>
    <xsl:otherwise>
        <xsl:value-of select="@name"/>
    </xsl:otherwise>
</xsl:for-each>
</div>

2 个答案:

答案 0 :(得分:2)

此转化

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

 <xsl:key name="kFollowing" match="data[not(@name='SPLIT')]"
 use="generate-id(preceding-sibling::data[@name='SPLIT'][1])"/>

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

 <xsl:template match="data[@name='SPLIT']" name="regularSplit">
  <div>
   <xsl:apply-templates mode="copy"
    select="key('kFollowing', generate-id())"/>
  </div>
 </xsl:template>

  <xsl:template match="data[@name='SPLIT'][
              not(preceding-sibling::data[@name='SPLIT'])]">
  <div>
   <xsl:apply-templates mode="copy"
    select="preceding-sibling::data"/>
  </div>
   <xsl:call-template name="regularSplit"/>
 </xsl:template>

 <xsl:template match="*" mode="copy">
  <xsl:call-template name="identity"/>
 </xsl:template>
<xsl:template match="data[not(@name='SPLIT')]"/>
</xsl:stylesheet>

应用于提供的XML文档(包装到顶部元素中以形成格式良好):

<t>
    <data name="a" />
    <data name="b" />
    <data name="c" />
    <data name="SPLIT" />
    <data name="d" />
    <data name="e" />
    <data name="SPLIT" />
    <data name="f" />
    <data name="g" />
    <data name="h" />
</t>

生成想要的正确结果

<t>
    <div>
        <data name="a"></data>
        <data name="b"></data>
        <data name="c"></data>
    </div>
    <div>
        <data name="d"></data>
        <data name="e"></data>
    </div>
    <div>
        <data name="f"></data>
        <data name="g"></data>
        <data name="h"></data>
    </div>
</t>

请注意:键用于方便快捷地指定紧跟“SPLIT”元素的所有“非SPLIT”元素。

答案 1 :(得分:2)

此样式表:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:strip-space elements="*"/>
    <xsl:template match="node()">
        <xsl:apply-templates 
                   select="node()[1]|following-sibling::node()[1]"/>
    </xsl:template>
    <xsl:template match="data">
        <div>
            <xsl:call-template name="open"/>
        </div>
        <xsl:apply-templates 
                   select="following-sibling::data[@name='SPLIT'][1]
                                    /following-sibling::node()[1]"/>
    </xsl:template>
    <xsl:template match="data" mode="open" name="open">
        <xsl:value-of select="concat(@name,'&#xA;')"/>
        <xsl:apply-templates select="following-sibling::node()[1]" 
                             mode="open"/>
    </xsl:template>
    <xsl:template match="data[@name='SPLIT']" mode="open"/>
</xsl:stylesheet>

输出:

<div>
a
b
c
</div>
<div>
d
e
</div>
<div>
f
g
h
</div>

注意:细粒度遍历。