You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

XSLT Schema-aware模式下最具体子类型模板匹配问题问询

XSD类型继承下的XSLT模板匹配问题

我的XSD中存在如下类型层级:RetentionContest 继承自 BallotMeasureContest 继承自 Contest。我编写了多个XSLT模板,例如:

<xsl:template name="cdf:BallotMeasureContest" match="element(*, cdf:BallotMeasureContest)">

以及:

<xsl:template name="cdf:RetentionContest" match="element(*, cdf:RetentionContest)">

当输入元素的@xsi:type = "cdf:RetentionContest"(原输入拼写有误,已修正为RetentionContest),且使用Schema-aware处理器时,哪个模板会被调用?如何确保最具体的子类型对应的模板被执行?(备注:我尝试过设置优先级但效果不佳,Altova和Saxon-EE似乎只会调用最后一个适用的模板。)


复现代码

repro_delete.xml

<?xml version="1.0" encoding="UTF-8"?>
<n1:ElectionReport xmlns:n1="http://itl.nist.gov/ns/voting/1500-100/v2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://itl.nist.gov/ns/voting/1500-100/v2 repro_delete.xsd">
    <n1:Election>
        <n1:Contest xsi:type="n1:RetentionContest" ObjectId="rc-123">
            <n1:CandidateId>rc-123</n1:CandidateId>
        </n1:Contest>
    </n1:Election>
</n1:ElectionReport>

repro_delete.xsl

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns="http://www.w3.org/2005/xpath-functions" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:cdf="http://itl.nist.gov/ns/voting/1500-100/v2" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:fn="http://www.w3.org/2005/xpath-functions" xmlns:math="http://www.w3.org/2005/xpath-functions/math" xmlns:array="http://www.w3.org/2005/xpath-functions/array" xmlns:map="http://www.w3.org/2005/xpath-functions/map" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:err="http://www.w3.org/2005/xqt-errors" exclude-result-prefixes="array cdf fn map math xhtml err xs xsi" version="3.0">
    <xsl:output method="text" version="1.0" encoding="UTF-8" indent="yes"/>
    <xsl:import-schema namespace="http://itl.nist.gov/ns/voting/1500-100/v2" schema-location="repro_delete.xsd"/>
    <xsl:template match="/" name="xsl:initial-template">
        <xsl:apply-templates/>
    </xsl:template>
        <xsl:template name="cdf:C" match="element(*, cdf:Contest)">
Contest
    </xsl:template>

    <xsl:template name="cdf:RC" match="element(*, cdf:RetentionContest)">
Retention
    </xsl:template>
    <xsl:template name="cdf:BMC" match="element(*, cdf:BallotMeasureContest)">
Ballot Measure Contest
    </xsl:template>
</xsl:stylesheet>

repro_delete.xsd

<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns="http://itl.nist.gov/ns/voting/1500-100/v2"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    targetNamespace="http://itl.nist.gov/ns/voting/1500-100/v2" elementFormDefault="qualified"
    version="2.0.3">
    <xsd:element name="ElectionReport" type="ElectionReport"/>
    <xsd:complexType name="BallotMeasureContest">
        <xsd:complexContent>
            <xsd:extension base="Contest">
                <xsd:sequence>
                    <xsd:element name="FullText" type="InternationalizedText" minOccurs="0"
                    > </xsd:element>
                </xsd:sequence>
            </xsd:extension>
        </xsd:complexContent>
    </xsd:complexType>
    <xsd:complexType name="Contest" abstract="true">
        <xsd:sequence>
            <xsd:element name="SubUnitsReported" type="xsd:integer" minOccurs="0"> </xsd:element>
            <xsd:element name="TotalSubUnits" type="xsd:integer" minOccurs="0"> </xsd:element>
        </xsd:sequence>
        <xsd:attribute name="ObjectId" type="xsd:ID" use="required"/>
    </xsd:complexType>
    <xsd:complexType name="Election">
        <xsd:sequence>
            <xsd:element name="Contest" type="Contest" minOccurs="0" maxOccurs="unbounded"
            > </xsd:element>
        </xsd:sequence>
    </xsd:complexType>
    <xsd:complexType name="ElectionReport">
        <xsd:sequence>
            <xsd:element name="Election" type="Election" minOccurs="0" maxOccurs="unbounded"
            > </xsd:element>
        </xsd:sequence>
    </xsd:complexType>
    <xsd:complexType name="InternationalizedText">
        <xsd:sequence>
            <xsd:element name="Text" type="xsd:string" maxOccurs="unbounded"> </xsd:element>
        </xsd:sequence>
        <xsd:attribute name="Label" type="xsd:string"> </xsd:attribute>
    </xsd:complexType>
    <xsd:complexType name="RetentionContest">
        <xsd:complexContent>
            <xsd:extension base="BallotMeasureContest">
                <xsd:sequence>
                    <xsd:element name="CandidateId" type="xsd:IDREF"> </xsd:element>
                </xsd:sequence>
            </xsd:extension>
        </xsd:complexContent>
    </xsd:complexType>
</xsd:schema>

问题解答

在Schema-aware的XSLT处理中,当元素通过xsi:type指定为子类型时,匹配父/子类型的模板都会成为候选。但XSLT默认优先级规则不会自动为element(*, type)模式根据类型继承关系赋予更高优先级,这就是你设置优先级无效、处理器选择最后声明模板的原因。

要确保最具体的子类型模板被调用,可采用以下两种可靠方法:

1. 显式设置递增的模板优先级

给匹配子类型的模板设置比父类型更高的priority值,比如:

<xsl:template name="cdf:C" match="element(*, cdf:Contest)" priority="1"/>
<xsl:template name="cdf:BMC" match="element(*, cdf:BallotMeasureContest)" priority="2"/>
<xsl:template name="cdf:RC" match="element(*, cdf:RetentionContest)" priority="3"/>

优先级数值越大,模板越优先被选择,需保证每个子类型的优先级都高于其父类型。

2. 结合xsl:next-match实现层次调用(可选)

如果需要同时执行子类型和父类型模板的逻辑,可在子类型模板中用xsl:next-match触发父类型模板的处理:

<xsl:template name="cdf:RC" match="element(*, cdf:RetentionContest)" priority="3">
  Retention
  <xsl:next-match/> <!-- 触发BallotMeasureContest模板的执行 -->
</xsl:template>

若只需执行最具体的模板,第一种方法更直接高效。

需要注意的是,不同处理器对element(*, type)模式的优先级计算可能存在差异,显式设置优先级是跨处理器兼容的最可靠方案,能确保在Altova和Saxon-EE中都正确生效。


内容的提问来源于stack exchange,提问作者J. Nicholas

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 22:47:03