XSLT:在根元素中添加命名空间

7

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

输入文档:

<?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
好问题(+1)。请查看我的答案,其中包含完整的XSLT 1.0和2.0解决方案。 :) - Dimitre Novatchev
2个回答

阿里云服务器只需要99元/年,新老用户同享,点击查看详情
12

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 输出也很有用。 - Casey Watson

1
你应该真正使用“身份模板”,并且应该随时掌握它。创建一个带有该模板的XSLT,将其命名为“identity.xslt”,然后将其导入到当前XSLT中。假设您要替换的名称空间前缀为“bad”,要替换它的名称空间前缀为“good”,那么您只需要像这样编写一个模板(我在工作中,所以请原谅格式;我回家后会重新编辑):... 如果在XSLT 1.0中无法工作,请使用类似“*[namespace-uri() = 'urn:bad-namespace'”的匹配表达式,并按照Dimitre的说明动态创建新元素。在 中,您确实需要递归地应用模板...但是真的,请阅读有关身份模板的资料。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,