如果给定 w3c DOM(具体来说是 Java 的默认实现),我该如何更改该 DOM 中每个元素/属性/节点的命名空间?高效,最好。
我认为没有一个有效的解决方案也很强大。您不能只重命名根元素上的某些内容。考虑这些文件:
文档1
<?xml version="1.0" encoding="UTF-8"?>
<root xmlns="urn:all" xmlns:f="urn:fleet" xmlns:m="urn:mission">
<f:starfleet>
<m:bold>
<f:ship name="Enterprise" />
</m:bold>
</f:starfleet>
</root>
文档2
<?xml version="1.0" encoding="UTF-8"?>
<root xmlns="urn:all">
<starfleet xmlns="urn:fleet">
<bold xmlns="urn:mission">
<ship xmlns="urn:fleet" name="Enterprise" />
</bold>
</starfleet>
</root>
文档3
<?xml version="1.0" encoding="UTF-8"?>
<r:root xmlns:r="urn:all">
<r:starfleet xmlns:r="urn:fleet">
<r:bold xmlns:r="urn:mission">
<r:ship xmlns:r="urn:fleet" name="Enterprise" />
</r:bold>
</r:starfleet>
</r:root>
这三个文档在命名空间感知 DOM 中是等价的。您可以对其中任何一个运行相同的 namespaced XPath queries。
由于 DOM 允许您准确指定节点应如何命名,因此没有包罗万象的一步调用来更改命名空间。您需要遍历 DOM,不仅要考虑前缀和 URI 值,还要考虑它们在任何给定时间的 scope。
此 XSLT 可与 Transformer 一起使用,以将命名为 urn:fleet 的元素更改为命名为 urn:new:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:f="urn:fleet" version="1.0">
<xsl:output method="xml" indent="yes" />
<xsl:template match="*">
<xsl:copy>
<xsl:copy-of select="@*" />
<xsl:apply-templates />
</xsl:copy>
</xsl:template>
<xsl:template match="f:*">
<xsl:variable name="var.foo" select="local-name()" />
<xsl:element namespace="urn:new" name="{$var.foo}">
<xsl:copy-of select="@*" />
<xsl:apply-templates />
</xsl:element>
</xsl:template>
</xsl:stylesheet>
注意事项:需要进一步调整来处理命名空间属性;悬空urn:fleet 声明可以被抛在后面,这很混乱,但在很大程度上是无关紧要的;可能还有其他我没有想到的东西。