子节点中的空命名空间

时间:2018-04-27 16:38:41

标签: xml xslt

使用固定命名空间时输出正确。

XSLT:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" >
    <xsl:output method="xml"/>
    <xsl:template match="/NewDataSet">
        <Foo namespace="http://MyLink/FixedVersion">
            <Bar>
                <SomeData/>
            </Bar>
        </Foo>
    </xsl:template>
</xsl:stylesheet>

输出:

<?xml version="1.0" encoding="utf-8"?>
<Foo namespace="http://MyLink/FixedVersion">
    <Bar>
        <SomeData />
    </Bar>
</Foo>

当使用动态命名空间时,子节点中的命名空间&#39;使用空值设置名称空间。

XSLT:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" >
    <xsl:output method="xml"/>
    <xsl:template match="/NewDataSet">
        <xsl:element name="Foo" namespace="http://MyLink/{Table/version}">
            <Bar>
                <SomeData/>
            </Bar>
        </xsl:element>
    </xsl:template>
</xsl:stylesheet>

输出:

<?xml version="1.0" encoding="utf-8"?>
<Foo xmlns="http://MyLink/v02_04_01">
    <Bar xmlns="">
        <SomeData />
    </Bar>
</Foo>

https://stackoverflow.com/a/49872085/2524586声明它们位于不同的命名空间中,但我不了解固定和动态值如何改变它。

我的预期结果是拥有第一个输出但具有动态version值。

2 个答案:

答案 0 :(得分:2)

您似乎必须在每个元素上显式创建名称空间。您在第一个示例中的错误是您根本没有创建命名空间:

<Foo namespace="http://MyLink/FixedVersion">
    <Bar>
        <SomeData />
    </Bar>
</Foo>

此处Foo没有分配名称空间:
看,它没有xmlns="..."名称空间属性(!),而是一个(相当任意的)namespace="..."属性。

因此,实现所需结果的唯一方法是在每个namespace="..."上添加xsl:element属性:

<xsl:template match="/NewDataSet">
    <xsl:element name="Foo" namespace="http://MyLink/{Table/version}">
        <xsl:element name="Bar" namespace="http://MyLink/{Table/version}">
            <xsl:element name="SomeData" namespace="http://MyLink/{Table/version}" />
        </xsl:element>
    </xsl:element>
</xsl:template>

输出为:

<?xml version="1.0"?>
<Foo xmlns="http://MyLink/v02_04_01">
    <Bar>
        <SomeData/>
    </Bar>
</Foo>

答案 1 :(得分:2)

元素的扩展名称(即(名称空间,本地名称)对)完全由创建元素的指令决定;它并不以任何方式依赖于结果树中元素的父元素。您永远不能依赖于与其父级相同的命名空间的元素。

对于文字结果元素(如<Foo><p:Bar>),结果树中元素的展开名称与样式表中元素的展开名称相同。也就是说,它由XML命名空间规则的规则决定:命名空间URI由样式表中的xmlns命名空间声明确定(它可以出现在文字结果元素本身或任何祖先元素上)。这意味着命名空间又是一个静态常量,它不能动态计算。

对于使用xsl:element构造的元素,有两种指定命名空间的方法。如果存在namespace属性,则其有效值(解释为AVT)将建立构造元素的名称空间URI。因为这是一个AVT,所以命名空间可以动态计算。

如果没有namespace属性,name属性的值将被解释为词法QName,并且命名空间的确定方式与文字结果元素相同,使用命名空间样式表中xsl:element指令范围内的声明。使用此机制,您可以在一组固定的静态名称空间之间动态选择,但您无法完全动态地计算命名空间:

<xsl:stylesheet xmlns:a="http://one-uri/" xmlns:b="http://another-uri/">
....
   <xsl:element name="{if (x) then 'a' else 'b'}:foo">