4

我正在尝试使用 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>
4

5 回答 5

5

首先,在 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>
于 2012-08-29T14:11:07.293 回答
5

Michael Kay 为您提供了正确答案,但根据您的评论,您不确定如何在转换中使用它。

这是一个完整的转换

 <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" />
于 2012-08-29T16:26:51.260 回答
2

XML 中的命名空间声明不是属性,即使它们看起来像属性。在 XSLT 2.0 中,您可以使用<xsl:namespace name="neil" select="$myNameSpace" />动态地将名称空间声明添加到结果树中,但该功能在 XSLT 1.0 中不可用。

于 2012-08-29T13:58:26.880 回答
0

终于找到了一个与我的 XSLT 处理器 (Oracle XML V2 Parser) 一起使用的解决方法

我必须将其转换为 DOM 文档,然后将该 DOM 保存到文件系统,而不是直接输出到StreamResult

我在转换方法中使用了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>

我知道这不是最好的方法,但考虑到解析约束,这是我现在唯一的选择。

于 2012-08-30T14:22:01.293 回答
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"/>
于 2012-08-29T13:44:24.293 回答