XSLT转换重定位xmlns实例

时间:2013-05-08 06:10:41

标签: xml xslt

我有以下XML:

<root xmlns:myns="derf">
    <child>
        <grandchild>mikey</grandchild>
    </child>
</root>

我正在尝试将其转换为以下XML:

<root xmlns="theNamespace" xmlns:myns="derf">
    <child>
        <grandchild>mikey</grandchild>
    </child>
</root>

我认为以下XSLT会这样做:

<xsl:template match="/">
    <xsl:apply-templates select="/root"/>
</xsl:template>

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

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

虽然发出:

<root xmlns="theNamespace">
    <child xmlns="" xmlns:myns="derf">
        <grandchild>mikey</grandchild>
    </child>
</root>

有人可以帮助我理解 - 并且理想情况下修复 - 为什么xmlns:myns="derf"最终会在child节点而不是输出中的root节点上结束?

我基本上只是想用xmlns命名空间值来扩充原始XML。

提前致谢, 马特

1 个答案:

答案 0 :(得分:0)

这里有两个问题 - 首先,您只将root元素放在theNamespace命名空间中,因此子元素仍然在其原始(null)命名空间中。其次,<xsl:copy>完成复制元素命名空间的工作,但文字元素不会。这个XSLT应该按照你描述的方式运行:

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

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

  <xsl:template match="*[name() = local-name()]">
    <xsl:element name="{name()}" namespace="theNamespace">
      <xsl:copy-of select="namespace::*[name() != '']" />
      <xsl:apply-templates select="@* | node()" />
    </xsl:element>
  </xsl:template>
</xsl:stylesheet>

在样本输入上运行时,结果为:

<root xmlns="theNamespace" xmlns:myns="derf">
  <child>
    <grandchild>mikey</grandchild>
  </child>
</root>