将两个元素组合成一个元素XSLT

时间:2014-04-30 12:28:08

标签: xml xslt transformation

我有这个xml:

<root>

    <first>The first</first>

    <second>and the second</second>
</root>

我希望输出为:

<root>

     <firstAndSecond>The first and the second</firstAndSecond>

</root>

但是我找不到任何文章证明如何在xsl中执行此操作,所以如果有人可以提供示例或链接我一篇解释如何执行此操作的文章,我会非常感激。

提前致谢。

2 个答案:

答案 0 :(得分:3)

虽然在这样一个简单的输入XML中可能不是完全必要的,但通常值得从XSLT identity transform开始,它本身就是复制节点,这意味着你只需要为&#编写模板39;例外&#39;

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

在您的情况下,您可以看到问题是将根的第一个子项转换为新元素,因此您将拥有与第一个元素匹配的模板

 <xsl:template match="/*/*[1]">

要使用动态名称创建新元素,请使用 xsl:element 命令,如下所示

<xsl:element name="{local-name()}And{local-name(following-sibling::*[1])}">

或者为了保持更多可读性,请在表达式中使用变量

    <xsl:variable name="second" select="local-name(following-sibling::*[1])" />
    <xsl:element name="{local-name()}And{$second}">

注意这里使用Attribute Value Templates,表示要计算的表达式,而不是字面输出。因此,在这种情况下,正在评估 local-name()以获取元素的名称(不包括名称空间)。

在此范围内,您可以使用 xsl:apply-templates 复制两个子元素的子元素(这将处理除了要复制的文本以外的节点的情况)

        <xsl:apply-templates select="node()" />
        <xsl:text> </xsl:text>
        <xsl:apply-templates select="following-sibling::*[1]/node()"/>

最后,要停止身份转换复制它,您还需要一个模板来排除 root 的第二个孩子

<xsl:template match="/*/*[position() > 1]" />

尝试这个XSLT

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

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

    <xsl:template match="/*/*[1]">
        <xsl:variable name="second" select="local-name(following-sibling::*[1])" />
        <xsl:element name="{local-name()}And{$second}">
            <xsl:apply-templates select="node()" />
            <xsl:text> </xsl:text>
            <xsl:apply-templates select="following-sibling::*[1]/node()"/>
        </xsl:element>
    </xsl:template>

    <xsl:template match="/*/*[position() > 1]" />
</xsl:stylesheet>

注意,这并不是第一个字母的首字母。为此(在XSLT 1.0中),您需要使用 substring 的组合来提取第一个字母,并使用翻译将其转换为大写。

答案 1 :(得分:1)

这个解决方案怎么样?

<root>
    <first>The first</first>
    <second>and the second</second>
</root>
<xsl:template match="root">
    <xsl:variable name="first_name" select="name(*[position() = 1])"/>
    <xsl:variable name="second_name" select="name(*[position() = 2])"/>
    <xsl:variable name="combined_names" select="concat($first_name,'And',$second_name)"/>
    <xsl:element name="{$combined_names}">
        <xsl:value-of select="concat(*[position() = 1],' and ',*[position() = 2])"/>
    </xsl:element>
</xsl:template>