【问题标题】:Changing the namespace with xslt 1使用 xslt 1 更改命名空间
【发布时间】:2012-12-20 14:36:17
【问题描述】:

我在这方面遇到了比我应该的更多的麻烦,并且无法找到似乎正确的解决方案:

我想简单地使用 xslt 1.0 更改 XML 文档的名称空间 - 用于 java 应用程序,使用 javax.xml.transform。

这是我的 xml 文档:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Root xmlns="http://namespace1.org" type="Document" version="V2_2">
    <Content>
        <Text>asdf</Text>
    </Content>
</Root>

这就是它在转换后的样子:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Root xmlns="http://namespace2.org" type="Document" version="V2_2">
    <Content>
        <Text>asdf</Text>
    </Content>
</Root>

这是我的 xslt 代码:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns="http://namespace2.org">

  <xsl:output omit-xml-declaration="yes" indent="yes"/>
  <xsl:strip-space elements="*"/>

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

</xsl:stylesheet>

这是我转换后得到的实际输出:

<?xml version="1.0" encoding="UTF-8"?>
<ns0:Root xmlns:ns0="http://namespace2.org">2012-11-02T15:39:46.05+01:00DocumentV2_2<ns1:Content xmlns:ns1="http://namespace2.org">
  <ns2:Text xmlns:ns2="http://namespace2.org">asdf</ns2:Text>
 </ns1:Content>
</ns0:Root>

添加了很多前缀,我不想要。

我已经能够通过使用以下 xlst 摆脱 ns+increment 前缀:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns="http://namespace2.org"
 xmlns:cmp="http://namespace2.org"
 exclude-result-prefixes="cmp">

  <xsl:output omit-xml-declaration="yes" indent="yes"/>
  <xsl:strip-space elements="*"/>

  <xsl:template match="*">
     <xsl:element name="cmp:{name()}" namespace="http://namespace2.org">
       <xsl:copy-of select="@*"/>
       <xsl:apply-templates/>
     </xsl:element>
 </xsl:template>

</xsl:stylesheet>

产生以下输出:

<?xml version="1.0" encoding="UTF-8"?>
<cmp:Root xmlns:cmp="http://namespace2.org" type="Document" version="V2_2">
 <cmp:Content>
  <cmp:Text>asdf</cmp:Text>
 </cmp:Content>
</cmp:Root>

但我一直无法摆脱“cmp”前缀。

有什么想法可以达到预期的输出吗?

【问题讨论】:

  • 我很好奇 - 如果您使用的是 Java,那么您到底为什么还在使用 XSLT 1.0?

标签: java xml xslt xslt-1.0


【解决方案1】:

此通用转换(适用于任何 XML 文档,新命名空间作为全局/外部参数传递):

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

 <xsl:param name="pNewNS" select="'http://namespace2.org'"/>

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

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

 <xsl:template match="@*">
  <xsl:attribute name="{name()}">
   <xsl:value-of select="."/>
  </xsl:attribute>
 </xsl:template>

 <xsl:template match="@*[namespace-uri()=namespace-uri(/*)]">
  <xsl:attribute name="{name()}" namespace="{$pNewNS}">
   <xsl:value-of select="."/>
  </xsl:attribute>
 </xsl:template>
</xsl:stylesheet>

应用于提供的 XML 文档时

<Root xmlns="http://namespace1.org" type="Document" version="V2_2">
    <Content>
        <Text>asdf</Text>
    </Content>
</Root>

产生想要的正确结果:

<Root xmlns="http://namespace2.org" type="Document" version="V2_2">
   <Content>
      <Text>asdf</Text>
   </Content>
</Root>

【讨论】:

  • 不幸的是,我无法验证这一点。这是我与您的 xslt 的输出: ; asdf; 可能这是 xslt 转换器的 java 实现的问题?
  • @codeySmurf,W3C XSLT 1.0 规范不会阻止 XSLT 处理器将生成的命名空间前缀添加到元素名称中。还有一些 XSLT 处理器,比如您正在使用的处理器,会在元素名称中添加前缀,并且不会生成默认名称空间。作为结果得到的文档和我得到的文档是完全相同的文档——它们只是在词汇表示上有所不同。我使用了 Saxon 6.5.4 并得到了我复制并粘贴在答案中的结果。我在计算机上安装的所有 12 个 XSLT 处理器都得到完全相同的结果。
  • @codeySmurf 我在计算机上安装的所有 12 个 XSLT 处理器得到完全相同的结果 MSXML 3/4/6、.Net XslCompiledTransform 和 XslTransform、Saxon 6.5.4、9.1.07、9.4 .06、.NET、Altova(XML-SPY XSLT 1.0 和 XSLT 2.0)、XQSharp。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-02-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多