XSLT合并多个节点

时间:2014-06-11 18:41:09

标签: xml xslt

最近我试图用XSLT稍微收看一下,目前我遇到了一个问题,我认为这是非常具体的。

我希望组合多个节点,直到出现具有特殊属性的节点,然后将节点文本合并到一个新节点中。

<paragraph>
    <row>
        <text>Text1</text>
    </row>
    <row>
        <properties>
            <vertAlign val="superscript"/>
        </properties>
        <text>2</text>
    </row>
    <row>
        <text>Text2</text>
    </row>
    <row>
        <text>Text3</text>
    </row>
    <row>
        <properties>
            <vertAlign val="superscript"/>
        </properties>
        <text>1</text>
    </row>
    <row>
        <text>Text4</text>
    </row>
    <row>
        <text>Text5</text>
    </row>
    <row>
        <text>Text6</text>
    </row>
    <row>
        <properties>
            <vertAlign val="superscript"/>
        </properties>
        <text>1</text>
    </row>
    <row>
        <text>Text7</text>
    </row>
    <row>
        <properties>
            <vertAlign val="superscript"/>
        </properties>
        <text>1</text>
    </row>
</paragraph>

在这个例子中,我想收集所有行/文本,直到row / properties / vertAlign [@ val =“superscript”]。  输出应为:

<root>
    <node>Text1</node>
    <node>Text2Text3</node>
    <node>Text4Text5Text6</node>
    <node>Text7</node>
</root>

感谢您的所有帮助, ASMO

2 个答案:

答案 0 :(得分:1)

假设您使用XSLT 2.0

<xsl:template match="paragraph">
  <root>
    <xsl:for-each-group select="row" group-ending-with="row[properties/vertAlign/@val = 'superscript']">
      <node>
        <xsl:value-of select="current-group()[position() ne last()]/text" separator=""/>
      </node>
    </xsl:for-each-group>
  </root>
</xsl:template>

答案 1 :(得分:1)

如果您当前正在使用XSLT 1.0,那么您需要阅读一种名为Muenchian Grouping的技术。假设某个点的正常行后面总会有一个“属性”行,您可以按行第一个“属性”行的唯一ID对行元素进行“分组”。这意味着像这样定义一个键:

<xsl:key name="rows" 
        match="row[not(properties)]" 
        use="generate-id(following-sibling::row[properties][1])" />

然后您可以选择每个组中的第一行......

<xsl:apply-templates 
     select="row[generate-id() = generate-id(key('rows', generate-id(following-sibling::row[properties][1]))[1])]" />

然后,在匹配该行的模板中,您可以再次使用该键获取该组中每行的文本:

<xsl:apply-templates select="key('rows', generate-id(following-sibling::row[properties][1]))/text" />

这将利用XSLT的内置模板,它将迭代(但不复制)元素,但输出文本节点,找到它们。

试试这个XSLT

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

    <xsl:key name="rows" match="row[not(properties)]" use="generate-id(following-sibling::row[properties][1])" />

    <xsl:template match="paragraph">
        <root>
            <xsl:apply-templates select="row[generate-id() = generate-id(key('rows', generate-id(following-sibling::row[properties][1]))[1])]" />
        </root>
    </xsl:template>

    <xsl:template match="row">
        <node>
            <xsl:apply-templates select="key('rows', generate-id(following-sibling::row[properties][1]))/text" />
        </node>
    </xsl:template>
</xsl:stylesheet>