允许属性集设置属性

时间:2018-04-17 19:55:34

标签: xslt saxon

我知道xsl:attribute-set的存在是为了允许一组XML属性在一个名称下分组,然后可以在以后轻松地将其应用于几个类似的元素。

我知道名称空间不是属性,不能使用它来设置。

然而在Saxon9.8EE中,我注意到这是有效的,我想知道这是否可以使用:

<xsl:attribute-set name="swbml.ir" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <xsl:attribute name="version">4-2</xsl:attribute>
    <xsl:attribute name="xsi:schemaLocation">http://www.fpml.org/2005/FpML-4-2 /path/to/swbml-ird-main-4-2.xsd</xsl:attribute>
</xsl:attribute-set>

通过将xsi名称空间添加到xsl:attribute-set本身,它将此名称空间应用于使用swbml.ir属性集的任何元素。

(当然必须因为其中一个属性位于xsi名称空间中)

所以这个:

<SWBML xmlns="http://www.fpml.org/2005/FpML-4-2" xsl:use-attribute-sets="swbml.ir">

结果:

<SWBML xmlns="http://www.fpml.org/2005/FpML-4-2"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       version="4-2"
       xsi:schemaLocation="http://www.fpml.org/2005/FpML-4-2 /path/to/swbml-ird-main-4-2.xsd">

这正是我想要的。但感觉我可能正在扩展属性集的预期用例?

具体来说,如果我尝试更进一步并像这样添加xmlns="http://www.fpml.org/2005/FpML-4-2"

<xsl:attribute-set name="swbml.ir" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.fpml.org/2005/FpML-4-2">

默认的xmlns不适用于<SWBML> - 这是我所期望的。

所以 - 规则是属性集将添加任何命名空间,以便限定集合包含的任何属性,但是不会添加任何其他命名空间?或者我误入了未定义的领域?

2 个答案:

答案 0 :(得分:2)

您的理解基本上是正确的,因为如果存在绑定到命名空间的内容,并且您将其包含在输出中,那么命名空间将随之而来。但是,您碰巧在属性集上声明了它并不重要。它可以在样式表的其他位置声明,例如在xsl:stylesheet元素上,在范围内并在属性集中引用。

根据您提出的示例,您可以将xsi命名空间前缀的声明从xsl:attribute-set移到xsl:stylesheet元素之外,它仍会显示在如果属性集应用于元素,则输出:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    exclude-result-prefixes="xsi">
    <xsl:output method="xml"/>
    <xsl:attribute-set name="swbml.ir">
        <xsl:attribute name="version">4-2</xsl:attribute>
        <xsl:attribute name="xsi:schemaLocation">http://www.fpml.org/2005/FpML-4-2 /path/to/swbml-ird-main-4-2.xsd</xsl:attribute>
    </xsl:attribute-set>
    <xsl:template match="/">
        <SWBML xmlns="http://www.fpml.org/2005/FpML-4-2" xsl:use-attribute-sets="swbml.ir"/>
    </xsl:template>
</xsl:stylesheet>

如果属性集未应用于内容,它将不会出现在输出中:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    exclude-result-prefixes="xsi">
    <xsl:output method="xml"/>
    <xsl:attribute-set name="swbml.ir">
        <xsl:attribute name="version">4-2</xsl:attribute>
        <xsl:attribute name="xsi:schemaLocation">http://www.fpml.org/2005/FpML-4-2 /path/to/swbml-ird-main-4-2.xsd</xsl:attribute>
    </xsl:attribute-set>
    <xsl:template match="/">
        <SWBML xmlns="http://www.fpml.org/2005/FpML-4-2" />
    </xsl:template>
</xsl:stylesheet>

请注意,我在两个示例中都使用了exclude-result-prefixes,以确保在未使用时从输出中删除xsi namepsace。否则,范围内的命名空间可能会出现在输出中,即使它没有应用于任何内容。

答案 1 :(得分:1)

是的,这将有效:正如@MadsHansen指出的那样,当你使用<xsl:attribute name="p:u"/>时,唯一真正重要的是p元素上的前缀xsl:attribute被声明的地方本身,或其祖先之一。如果在xsl:attribute-set本身的级别上声明它很方便,那就好了,做到这一点。

这里需要注意的是,这并不适用于QName值属性。如果你想做

<xsl:attribute name="xsi:type">xs:date</xsl:attribute>

然后你可以通过让它在xsi指令的范围内来获得结果文档中声明的前缀xsl:attribute,但对于xs前缀,你需要稍微工作一下更难(因为XSLT处理器不知道属性值xs:date是QName)。在这种情况下,您需要明确确保结果树中的某些包含元素声明xs命名空间。