使用XSLT重命名XML节点的所有子节点

时间:2018-05-31 13:39:23

标签: xml xslt xpath

我有一个具有以下结构的XML文件。

<Telefon>
    <area>0123</area>
    <number>456</number>
    <extension>789</extension>
</Telefon>
<Fax>
    <area>3210</area>
    <number>654</number>
    <extension>1098</extension>
</Fax>

我想使用XSLT将其转换为以下

<telefon-area>0123</area>
<telefon-number>456</number>
<telefon-extension>789</extension>
<fax-area>3210</area>
<fax-number>654</number>
<fax-extension>1098</extension>

我到目前为止使用复制模板,虽然我可以编写模板来手动更改这些字段,但我想只写一个将telefon或fax-前缀添加到上一个Telefon和传真的每个子节点节点

这是我到目前为止提出的结构:

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

<!--The next template removes the telefon tag but I do not know how to modify the child nodes to extend them with the telefon- prefix.-->
<xsl:template match="Telefon">
    <xsl:apply-templates select="@*|node()"/> 
</xsl:template>

感谢您的帮助!

1 个答案:

答案 0 :(得分:3)

要匹配Telefon节点的子节点,您可以执行此操作...

<xsl:template match="Telefon/*">

你可以像这样扩展它,以处理Fax

 <xsl:template match="Telefon/*|Fax/*">

在此范围内,您可以将xsl:elementlocal-name()一起使用来创建新的元素名称。

试试这个XSLT

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

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

    <!--The next template removes the telefon tag but I do not know how to modify the child nodes to extend them with the telefon- prefix.-->
    <xsl:template match="Telefon|Fax">
        <xsl:apply-templates /> 
    </xsl:template>

    <xsl:template match="Telefon/*|Fax/*">
        <xsl:element name="{local-name(..)}-{local-name()}">
            <xsl:apply-templates select="@*|node()" />
        </xsl:element>
    </xsl:template>
</xsl:stylesheet>

注意,在匹配Telefon的模板中,您只需要执行<xsl:apply-templates />,因为您可能希望忽略Telefon上的任何属性(如果有的话)。

或者,您可以使用“模式”,如果您有其他元素,除TelefonFax之外您也想要更改

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

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

    <!--The next template removes the telefon tag but I do not know how to modify the child nodes to extend them with the telefon- prefix.-->
    <xsl:template match="Telefon|Fax">
        <xsl:apply-templates mode="child" /> 
    </xsl:template>

    <xsl:template match="*" mode="child">
        <xsl:element name="{local-name(..)}-{local-name()}">
            <xsl:apply-templates select="@*|node()" />
        </xsl:element>
    </xsl:template>
</xsl:stylesheet>

注意,这并不会使名称全部为小写。如果你想要它,那么它将取决于你是使用XSLT 2.0还是XSLT 1.0。

理想情况下,您可以使用XSLT 2.0,并执行此操作...

 <xsl:element name="{lower-case(local-name(..))}-{local-name()}">