使用 XSLT 转换在 XML 中创建 xmlns 属性
Posted
技术标签:
【中文标题】使用 XSLT 转换在 XML 中创建 xmlns 属性【英文标题】:Create xmlns attribute in the XML using XSLT Transformation 【发布时间】:2012-08-24 03:23:44 【问题描述】:我正在尝试使用 JDK Transformer(Oracle XML v2 Parser 或 JAXP)在 XSLT 转换期间通过参数传递的值将 xmlns 属性添加到生成的 XML,但它始终默认为 http://www.w3.org/2000/xmlns/
我的源 XML
<test/>
我的 XSLT
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns="http://example.com">
<xsl:param name="myNameSpace" select="'http://neilghosh.com'"/>
<xsl:template match="/">
<process>
<xsl:attribute name="xmlns:neil">
<xsl:value-of select="$myNameSpace"/>
</xsl:attribute>
</process>
</xsl:template>
</xsl:stylesheet>
我的结果
<?xml version="1.0"?>
<process xmlns="http://www.w3.org/2000/xmlns/" xmlns:neil="neilghosh.com">
</process>
我想要的结果
<?xml version="1.0"?>
<process xmlns="http://example.com" xmlns:neil="neilghosh.com">
</process>
【问题讨论】:
您应该为命名空间使用有效的 URI,例如http://example.com/
,不是http://example.com
。如果您将浏览器输入到位置栏中,浏览器会将后者更正为前者,但这是在纠正输入时的明显错误。不能有没有路径部分的 HTTP URI。
【参考方案1】:
首先,在 XSLT 数据模型中,您不想创建属性节点,而是要创建命名空间节点。
命名空间节点通常是自动创建的:如果您在特定命名空间中创建元素或属性,处理器会自动添加必要的命名空间节点(因此,在序列化时,命名空间声明)会自动添加。
如果您想创建一个不必要的名称空间节点(因为它没有用于任何元素或属性的名称中),那么在 XSLT 2.0 中您可以使用 xsl:namespace。如果您坚持使用 XSLT 1.0,那么有一个解决方法,即在相关命名空间中创建一个元素,然后复制其命名空间节点:
<xsl:variable name="ns">
<xsl:element name="neil:dummy" namespace="$param"/>
</xsl:variable>
<process>
<xsl:copy-of select="$ns/*/namespace::neil"/>
</process>
【讨论】:
当$ns
变量持有RTF 而不是节点集时,这是否有效?我本来预计需要一个 exslt:node-set()
电话或类似电话来首先转换它。
感谢模板下的以下代码不起作用 xxx:node-set()
扩展功能?
是的,我认为它需要 xx:node-set()。抱歉,我只为人们指明正确的方向,我不会牵着他们的手走到那里——尤其是涉及 XSLT 1.0 时,因为那总是一段不愉快的旅程。【参考方案2】:
Michael Kay 为您提供了正确答案,但根据您的 cmets,您不确定如何在转换中使用它。
这是一个完整的转换:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:ext="http://exslt.org/common" exclude-result-prefixes="ext">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:param name="pNamespace" select="'neilghosh.com'"/>
<xsl:variable name="vDummy">
<xsl:element name="neil:x" namespace="$pNamespace"/>
</xsl:variable>
<xsl:template match="/*">
<xsl:element name="process" namespace="http://example.com">
<xsl:copy-of select="namespace::*"/>
<xsl:copy-of select="ext:node-set($vDummy)/*/namespace::*[.=$pNamespace]"/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
当此转换应用于提供的 XML 文档时:
<test/>
产生了想要的正确结果:
<process xmlns="http://example.com" xmlns:neil="neilghosh.com" />
【讨论】:
感谢您的回答。我收到以下错误 a.xsl: XML-23049: (Error) FOTY0021: invalid node type 这是因为我的 JDeveloper 的 oracle.xml.parser.v2.XSLProcessor 吗?有更好的 v2 解析器方法吗? 删除了 Oracle v2 解析器库并运行了上述代码,但输出为XML 中的命名空间声明不是属性,即使它们看起来像属性。在 XSLT 2.0 中,您可以使用 <xsl:namespace name="neil" select="$myNameSpace" />
将命名空间声明动态添加到结果树,但该功能在 XSLT 1.0 中不可用。
【讨论】:
我添加了不要尝试自己创建“xmlns”属性。在 XSLT 中创建名称空间,它们将自动完成。 这个 XSLT 工作(用 Saxon 9.4 测试):
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:neil="neilghosh.com"
xpath-default-namespace="http://example.com"
xmlns="http://example.com" version="2.0">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:param name="myDynamicNamespace" select="'http://neilghosh.com'"/>
<xsl:template match="/">
<xsl:element name="process">
<xsl:namespace name="neil" select="$myDynamicNamespace"/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
并给出以下输出:
<?xml version="1.0" encoding="UTF-8"?>
<process xmlns="http://example.com" xmlns:neil="http://neilghosh.com"/>
【讨论】:
问题的关键在于 xmlns 的值应该来自参数 [sent by transformer.setParameter("myNameSpace", "example.com") ] "myNameSpace" ok - 所以元素“process”应该在来自参数的命名空间中。我将尝试在终于找到了一个适用于我的 XSLT 处理器(Oracle XML V2 解析器)的解决方法
我必须 transform it to a DOM Document 然后将该 DOM 持久化到文件系统,而不是直接输出到 StreamResult
我在transform method 中使用了DOMResult
以下 XSLT 片段有效,但有一个额外的 xmlns:xmlns="http://www.w3.org/2000/xmlns/" 可能已被 Document 吸收,当我没有出现在最终输出中时持久化到文件系统。
<process>
<xsl:attribute name="xmlns">
<xsl:value-of select="'http://example.com'"/>
</xsl:attribute>
<process>
我知道这不是最好的方法,但考虑到解析约束,这是我现在唯一的选择。
【讨论】:
以上是关于使用 XSLT 转换在 XML 中创建 xmlns 属性的主要内容,如果未能解决你的问题,请参考以下文章
无法使用 Ant 在 Javascript 或 Jython 中创建 XSLT 扩展