xslt copy-of到结果文档中的不同命名空间

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了xslt copy-of到结果文档中的不同命名空间相关的知识,希望对你有一定的参考价值。

在我的xslt代码中,我可以使用copy-of来复制元素及其后代节点,但问题是生成的模式虽然具有相同的结构但具有不同的命名空间。有什么方法我仍然可以使用副本并完成此操作?我正在使用XSLT 2.0

以下是源和目标XML的示例,可以使用XSL中的copy-of复制cd元素,但它们具有不同的名称空间。

所以r XML

<catalog xmlns="namespace1">
  <cd>
    <title>Empire Burlesque</title>
    <artist>Bob Dylan</artist>
    <country>USA</country>
    <company>Columbia</company>
    <price>10.90</price>
    <year>1985</year>
  </cd>
  <cd>
    <title>Hide your heart</title>
    <artist>Bonnie Tyler</artist>
    <country>UK</country>
    <company>CBS Records</company>
    <price>9.90</price>
    <year>1988</year>
  </cd>
</catalog>

目标XML

<books xmlns="namespace2">
  <cd>
    <title>Empire Burlesque</title>
    <artist>Bob Dylan</artist>
    <country>USA</country>
    <company>Columbia</company>
    <price>10.90</price>
    <year>1985</year>
  </cd>
  <cd>
    <title>Hide your heart</title>
    <artist>Bonnie Tyler</artist>
    <country>UK</country>
    <company>CBS Records</company>
    <price>9.90</price>
    <year>1988</year>
  </cd>
</books>

使用了Martin Honnen的想法并创造了这个

<xsl:template name="changeNamespace">
<xsl:param name="nodes"/>
<xsl:for-each select="$nodes">
  <xsl:choose>
    <xsl:when test="count(child::*)>0">
      <xsl:element name="newnamespace:{local-name()}">
        <xsl:call-template name="changeNamespace">
          <xsl:with-param name="nodes" select="./child::*"/>
        </xsl:call-template>
      </xsl:element>
    </xsl:when>
    <xsl:otherwise>
      <xsl:element name="newnamespace:{local-name()}">
        <xsl:value-of select="."/>
      </xsl:element>
    </xsl:otherwise>
  </xsl:choose>
</xsl:for-each>

答案

您不能使用xsl:copyxsl:copy-of来更改节点的命名空间,您需要使用例如

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

然后假定你有例如<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:ns1="source-namespace" xmlns:ns2="target-namespace" version="1.0">在范围内,或者您当然也可以将目标命名空间放入xsl:element

<xsl:template match="ns1:*">
  <xsl:element name="ns2:{local-name()}" namespace="target-namespace">
    <xsl:apply-templates select="@* | node()"/>
  </xsl:element>
</xsl:template>

如果您有需要更改命名空间的属性,则需要为属性节点设置类似的模板。

使用XSLT 2.0,您可以简化样式表结构,例如

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xpath-default-namespace="namespace1" xmlns="namespace2" version="2.0">

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

以上是关于xslt copy-of到结果文档中的不同命名空间的主要内容,如果未能解决你的问题,请参考以下文章

名称空间作为使用 XSLT 处理的文档的变量

没有 xsl:copy-of 的 XSLT 复制

将命名空间从 java 传递给 xslt,并使用 java 中的参数作为 xslt 中的节点

在 XSLT 2.0 中定义变量时使用 xsl:copy-of

XSL:避免将命名空间定义导出到生成的 XML 文档

XSLT 将命名空间前缀添加到元素最佳实践