且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

使用 XSLT 从 XSLT 样式表中删除命名空间声明

更新时间:2023-10-01 23:01:34

我会补充

 exclude-result-prefixes="foo"

到你的

 <xsl:stylesheet>

元素.然后,如果可能,将省略 foo 的命名空间声明,即如果该命名空间中没有要输出的元素或属性.

element. Then the namespace declaration for foo will be omitted if possible, i.e. if there no elements or attributes in that namespace to output.

仅供参考,这行的原因

<xsl:template match="xsl:stylesheet/@xmlns:foo" />`

抛出错误是因为输入文档中的xmlns:foo不是属性;这是一个伪属性.您的匹配模式要求匹配的是名为 foo 的属性,该属性位于与命名空间前缀 xmlns 相对应的命名空间中.由于您尚未在样式表中声明命名空间前缀 xmlns,您会收到错误前缀 xmlns 未定义".

throws an error is because xmlns:foo in the input document is not an attribute; it's a pseudoattribute. What your match pattern is asking to match is an attribute named foo that is in a namespace corresponding to a namespace prefix xmlns. Since you have not declared a namespace prefix xmlns in your stylesheet, you get the error "prefix xmlns is not defined."

我从您发布的输出(以及我自己的测试)中看到 exclude-result-prefixes 在删除命名空间声明方面没有效果.

I see from your posted output (and my own testing) that exclude-result-prefixes hasn't been effective in removing the namespace declaration.

1) 首先我会问为什么这很重要.它不会更改输出 XSLT 中任何内容的名称空间.您只是出于审美原因试图将其删除吗?

1) First I would ask why it matters. It doesn't change the namespace of anything in your output XSLT. Are you just trying to remove it for aesthetic reasons?

2) 查看 XSLT 1.0 规范,在我看来 <xsl:copy> 不注意exclude-result-prefixes:

2) Looking at the XSLT 1.0 spec, it appears to me that <xsl:copy> pays no attention to exclude-result-prefixes:

实例化 xsl:copy 元素会创建当前节点的副本.当前节点的命名空间节点被自动复制为嗯...

Instantiating the xsl:copy element creates a copy of the current node. The namespace nodes of the current node are automatically copied as well...

AFAICT,只有文字结果元素会省略基于 exclude-result-prefixes 的命名空间节点.

AFAICT, only literal result elements will omit namespace nodes based on exclude-result-prefixes.

在此基础上,我会尝试用 <xsl:element name="{name()}" 替换您的标识模板(对于元素)中的 <xsl:copy>> 或其一些变体.然后,您将需要一个用于非元素节点的单独标识模板.

On that basis, I would try replacing <xsl:copy> in your identity template (for elements) with <xsl:element name="{name()}"> or some variant thereof. You would then need a separate identity template for non-element nodes.

我用以下两个模板替换了您的身份模板:

I replaced your identity template with the following two templates:

<!-- Copy elements -->
<xsl:template match="*" priority="-1">
   <xsl:element name="{name()}">
      <xsl:apply-templates select="node()|@*"/>
   </xsl:element>
</xsl:template>

<!-- Copy all other nodes -->
<xsl:template match="node()|@*" priority="-2">
   <xsl:copy />      
</xsl:template>

这给出了我认为需要的输出,没有多余的 ns 声明:

and that gave what I believe is the desired output, with no extraneous ns declarations:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
   <xsl:output indent="yes" omit-xml-declaration="yes" />

   <xsl:template match="/">
      <xsl:variable name="processId" select="''" />
      <root>
         <xsl:apply-templates />
      </root>
   </xsl:template>

   <!-- Other stuff -->
</xsl:stylesheet>

(为了清晰起见,我已经调整了空格.)

(I have adjusted the whitespace for clarity.)