在 XSL 翻译中更改 XML 文件的命名空间

Posted

技术标签:

【中文标题】在 XSL 翻译中更改 XML 文件的命名空间【英文标题】:Changing namespace for XML file in XSL Translation 【发布时间】:2011-03-28 16:41:57 【问题描述】:

所以我有一个输入文件,它在默认命名空间 (xmlns="companyURL") 中使用我公司的命名空间,但我希望我的输出文件使用默认命名空间 (xmlns:cmp="companyURL") 以外的东西。所以我使用cmp 命名空间构造我的文件,但是我想复制一些内部元素:

<xsl:element name="cmp:container">
  <xsl:for-each select="foo">
    <xsl:copy-of select="." />
  </xsl:for-each>
</xsl:element>

不幸的是,这样做是为每个内部元素定义默认命名空间,使文件变得非常冗长和丑陋。简化示例:

来源

<foo xmlns="companyURL">
  <num1>asdf</num1>
  <num2>ghjkl</num2>
</foo>

变成:

<cmp:container xmlns:cmp="companyURL">
  <num1 xmlns="companyURL">asdf</num1>
  <num2 xmlns="companyURL">ghjkl</num2>
</cmp:container>

当然,companyURL 又大又长又丑,而且在两个地方都一样,所以我更希望上面的结果如下:

<cmp:container xmlns:cmp="companyURL">
  <cmp:num1>asdf</cmp:num1>
  <cmp:num2>ghjkl</cmp:num2>
</cmp:container>

有没有一种简单的方法可以做到这一点,或者我应该将cmp 命名空间下的所有内容都转换为默认命名空间?如果可能,我更愿意使用显式命名空间命名,这有助于根据我的经验理解 XSLT。

【问题讨论】:

好问题 (+1)。请参阅我的答案以获得简短的解决方案,:) "希望我的输出文件使用默认命名空间以外的其他内容" >> 按照您的示例,更改前缀(或从默认到前缀)并不意味着更改命名空间。从 XML+NS 的角度来看,元素将保持相等(本地名称 + 命名空间不变),即使前缀不同。 我指的是标签名称前面的可见标识符。 【参考方案1】:

这种转变

 <xsl:template match="*">
     <xsl:element name="cmp:name()" namespace="CompanyURL">
       <xsl:copy-of select="@*"/>
       <xsl:apply-templates/>
     </xsl:element>
 </xsl:template>
 <xsl:template match="/*">
     <cmp:container xmlns:cmp="CompanyURL">
       <xsl:copy-of select="@*"/>
       <xsl:apply-templates/>
     </cmp:container>
 </xsl:template>
</xsl:stylesheet>

在提供的 XML 文档上执行时

<foo xmlns="companyURL">
  <num1>asdf</num1>
  <num2>ghjkl</num2>
</foo>

产生想要的正确结果

<cmp:container xmlns:cmp="CompanyURL">
   <cmp:num1>asdf</cmp:num1>
   <cmp:num2>ghjkl</cmp:num2>
</cmp:container>

【讨论】:

为什么你的 XSLT 中有 &lt;xsl:copy-of select="@*"/&gt; @adam_0:这会复制元素的所有属性。在您的具体示例中没有属性,但如果我们想将此代码用作通用转换器,它必须能够正确转换所有文档 - 包括其中包含具有属性的元素的文档。 如果你 100% 确定你可以删除它,但离开它不会有任何伤害——根本不会复制任何属性。拥有更多通用代码总是更好。想象一下,明天模式会发生变化,并且会有属性。然后你需要添加属性的复制。如果您从一开始就使用更通用的代码,那么架构中的这种更改根本不会影响您。 我刚刚想到的后续行动:我可以通过将 &lt;xsl:element name="cmp:name()" namespace="CompanyURL"&gt; 的顶部模板行更改为 &lt;xsl:element name="cmp:local-name()" namespace="CompanyURL"&gt; 来使任何命名空间前缀都可以使用(有效地修剪掉任何命名空间前缀并添加我自己的)? @adam_0:是的,这是进行前缀重命名的方法。

以上是关于在 XSL 翻译中更改 XML 文件的命名空间的主要内容,如果未能解决你的问题,请参考以下文章

XML 和 XSL 中的前缀命名空间处理由 XML 解析器返回错误

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

XSL:删除命名空间前缀

使用 XSL 根据 XML 的条件添加命名空间

如何从输出 xml 中删除命名空间?

XML 元素名称中包含的 XSLT 命名空间 URI