XSLT:将命名空间添加到根元素

Posted

技术标签:

【中文标题】XSLT:将命名空间添加到根元素【英文标题】:XSLT: Add namespace to root element 【发布时间】:2011-02-10 19:32:03 【问题描述】:

我需要更改根元素中的命名空间,如下所示:

输入文件:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<foo xsi:schemaLocation="urn:isbn:1-931666-22-9 http://www.loc.gov/ead/ead.xsd"
xmlns:ns2="http://www.w3.org/1999/xlink" xmlns="urn:isbn:1-931666-22-9"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

想要的输出:

<foo audience="external" xsi:schemaLocation="urn:isbn:1-931666-22-9
     http://www.loc.gov/ead/ead.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-
    instance" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="urn:isbn:1-931666-22-9">

我在复制整个文档时尝试这样做,然后再给出任何其他转换说明,但以下方法不起作用:

<xsl:template match="* | processing-instruction() | comment()">
    <xsl:copy copy-namespaces="no">
        <xsl:for-each select=".">
            <xsl:attribute name="audience" select="'external'"/>
            <xsl:namespace name="xlink" select="'http://www.w3.org/1999/xlink'"/>
        </xsl:for-each>
        <xsl:copy-of select="@*"/>
        <xsl:apply-templates/>
    </xsl:copy>
</xsl:template>

感谢您的建议!

【问题讨论】:

好问题 (+1)。有关完整的 XSLT 1.0 和 2.0 解决方案,请参阅我的答案。 :) 【参考方案1】:

XSLT 2.0 不是解决此问题所必需的。

这是一个 XSLT 1.0 解决方案,它与 XSLT 2.0 一样好用(只需将 version 属性更改为 2.0):

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

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

 <xsl:template match="/*">
   <xsl:element name="name()" namespace="namespace-uri()">

      <xsl:copy-of select=
        "namespace::*
           [not(name()='ns2')
          and
            not(name()='')
           ]"/>

      <xsl:copy-of select=
       "document('')/*/namespace::*[name()='xlink']"/>

      <xsl:copy-of select="@*"/>

      <xsl:attribute name="audience">external</xsl:attribute>
   </xsl:element>
 </xsl:template>
</xsl:stylesheet>

当上述转换应用于此 XML 文档时

<foo
xsi:schemaLocation="urn:isbn:1-931666-22-9 http://www.loc.gov/ead/ead.xsd"
xmlns:ns2="http://www.w3.org/1999/xlink"
xmlns="urn:isbn:1-931666-22-9"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"/>

产生想要的结果

<foo xmlns="urn:isbn:1-931666-22-9"
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xmlns:xlink="http://www.w3.org/1999/xlink"
     xsi:schemaLocation="urn:isbn:1-931666-22-9 http://www.loc.gov/ead/ead.xsd"
     audience="external"/>

【讨论】:

谢谢!非常有帮助! omit-xml-declaration="yes" 对于生成格式良好的 html5 输出也很有用。【参考方案2】:

您确实应该为此使用“身份模板”,并且您应该随时准备好它。使用该模板创建一个 XSLT,将其命名为“identity.xslt”,然后进入当前的 XSLT。假设要替换的命名空间的前缀为“bad”,而要替换的命名空间为“good”with,那么你只需要一个这样的模板(我在工作,所以请原谅格式;当我在家时,我会回到这个问题):...如果这在 XSLT 1.0 中不起作用,请使用匹配表达式,如 "*[namespace-uri() = 'urn :bad-namespace'",并按照 Dimitre 的说明以编程方式创建新元素。在 内,您确实需要递归地应用模板……但实际上,请阅读身份模板。

【讨论】:

以上是关于XSLT:将命名空间添加到根元素的主要内容,如果未能解决你的问题,请参考以下文章

在可视化映射器中将命名空间添加到根节点

jackson fasterxml 将命名空间添加到根元素

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

将命名空间前缀添加到根节点

如何使用 XSLT 替换命名空间中的元素?

xsd:any 元素的命名空间前缀并使用 XSLT 添加命名空间前缀