允许属性集设置属性所需的名称空间

Allowing an attribute-set to set a namespace required by an attribute

我知道 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> - 这有点符合我的预期。

所以 - 规则是属性集将添加任何所需的命名空间以限定该集合包含的任何属性,但不会添加任何其他命名空间?还是我误入歧途了?

您的理解基本上是正确的,因为如果有内容绑定到命名空间,并且您将其包含在输出中,那么命名空间就会随之而来。然而,您恰好在属性集上声明了它这一事实并不重要。它可以在样式表的其他地方声明,例如在 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 命名空间在未使用时从输出中删除。否则,范围内的命名空间可能会出现在输出中,即使它没有应用于任何内容。

是的,这会起作用:正如@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 命名空间。