[英]Create xmlns attribute in the XML using XSLT Transformation
I am trying to add the xmlns attribute to the resulting XML with a value passed by parameter during XSLT transformation using JDK Transformer (Oracle XML v2 Parser or JAXP) but it always defaults to http://www.w3.org/2000/xmlns/ 我正在尝试使用JDK Transformer(Oracle XML v2 Parser或JAXP)在XSLT转换期间使用参数传递的值将xmlns属性添加到生成的XML中,但它始终默认为http://www.w3.org/2000/xmlns /
My source XML 我的源XML
<test/>
My XSLT 我的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>
My Result 我的结果
<?xml version="1.0"?>
<process xmlns="http://www.w3.org/2000/xmlns/" xmlns:neil="neilghosh.com">
</process>
My Desired Result 我想要的结果
<?xml version="1.0"?>
<process xmlns="http://example.com" xmlns:neil="neilghosh.com">
</process>
Firstly, in the XSLT data model, you don't want to create an attribute node, you want to create a namespace node. 首先,在XSLT数据模型中,您不希望创建属性节点,而是要创建命名空间节点。
Namespace nodes are usually created automatically: if you create an element or attribute in a particular namespace, the requisite namespace node (and hence, when serialized, the namespace declaration) are added automatically by the processor. 命名空间节点通常是自动创建的:如果在特定命名空间中创建元素或属性,则处理器会自动添加必需的命名空间节点(因此,在序列化时,命名空间声明)。
If you want to create a namespace node that isn't necessary (because it's not used in the name of any element or attribute) then in XSLT 2.0 you can use xsl:namespace. 如果要创建不必要的命名空间节点(因为它未在任何元素或属性的名称中使用),那么在XSLT 2.0中,您可以使用xsl:namespace。 If you're stuck with XSLT 1.0 then there's a workaround, that involves creating an element in the relevant namespace and then copying its namespace node:
如果您坚持使用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>
Michael Kay provided you with the correct answer, but based on your comments, you aren't sure how to use it in your transformation. Michael Kay为您提供了正确的答案,但根据您的意见,您不确定如何在转换中使用它。
Here is a complete transformation : 这是一个完整的转变 :
<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>
When this transformation is applied on the provided XML document: 在提供的XML文档上应用此转换时:
<test/>
the wanted, correct result is produced: 产生了想要的正确结果:
<process xmlns="http://example.com" xmlns:neil="neilghosh.com" />
Namespace declarations in XML are not attributes even though they look like attributes. XML中的命名空间声明不是属性,即使它们看起来像属性。 In XSLT 2.0 you can use
<xsl:namespace name="neil" select="$myNameSpace" />
to add a namespace declaration to the result tree dynamically but that feature is not available in XSLT 1.0. 在XSLT 2.0中,您可以使用
<xsl:namespace name="neil" select="$myNameSpace" />
动态地向结果树添加名称空间声明,但该功能在XSLT 1.0中不可用。
Don't try to create "xmlns" attributes yourself. 不要尝试自己创建“xmlns”属性。 Create the namespaces in the XSLT and they will be done automatically.
在XSLT中创建名称空间,它们将自动完成。 This XSLT works (tested with Saxon 9.4):
这个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>
And gives the following output: 并给出以下输出:
<?xml version="1.0" encoding="UTF-8"?>
<process xmlns="http://example.com" xmlns:neil="http://neilghosh.com"/>
Finally got an workaround which worked with my XSLT Processor (Oracle XML V2 Parser) 最后找到了一个适用于我的XSLT处理器(Oracle XML V2 Parser)的解决方法
I had to transform it to a DOM Document and then persist that DOM to filesystem instead of outputting directly to StreamResult 我不得不将其转换为DOM Document ,然后将DOM保存到文件系统,而不是直接输出到StreamResult
I used DOMResult in the transform method 我在transform方法中使用了DOMResult
Following XSLT fragment worked but there was an extra xmlns:xmlns="http://www.w3.org/2000/xmlns/" which was probably absorbed by Document and did not appear in the final output when I persisted to file system. 以下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>
I know this is not the best way to do but given the parse constraint this is the only choice I have now. 我知道这不是最好的方法,但鉴于解析约束,这是我现在唯一的选择。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.