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

如何在XSLT中引用含嵌套XML变量内的深层元素?

XSLT 1.0中访问变量内嵌套XML元素的解决方案

问题根源

XSLT 1.0中,通过<xsl:variable>直接嵌套XML定义的变量属于结果树片段(RTF),而非可直接用XPath路径访问的节点集。这就是你只能引用整个变量内容,却无法通过$descriptions/annotations/annotation这类路径选择子节点的核心原因。

解决方案:将结果树片段转为节点集

需要借助扩展函数将RTF转换为节点集,之后就能用常规XPath路径访问内部元素。不同XSLT处理器支持的扩展函数略有不同,以下是两种常见实现:

方案1:使用EXSLT扩展(兼容性更广)

在样式表根元素引入EXSLT命名空间,并用exsl:node-set()转换变量:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
                xmlns:xs="http://www.w3.org/2001/XMLSchema" 
                xmlns:exsl="http://exslt.org/common"
                extension-element-prefixes="exsl"
                version="1.0">

<xsl:variable name="descriptions">
    <annotations>
        <annotation element="Element1">Description for Element1</annotation>
        <annotation element="Element2">Description for Element2</annotation>
        <annotation element="Element3">Description for Element3</annotation>
    </annotations>
</xsl:variable>

<xsl:template match="xs:element">
    <xsl:copy>
        <xsl:apply-templates select="@*"/>
        <!-- 转换RTF为节点集,匹配当前元素对应的注释 -->
        <xsl:variable name="currentName" select="@name"/>
        <xsl:variable name="matchedDesc" select="exsl:node-set($descriptions)/annotations/annotation[@element = $currentName]"/>
        
        <!-- 示例:将注释添加到XSD的annotation节点中 -->
        <xs:annotation>
            <xs:documentation>
                <xsl:value-of select="$matchedDesc"/>
            </xs:documentation>
        </xs:annotation>
        
        <xsl:apply-templates select="node()"/>
    </xsl:copy>
</xsl:template>

<!-- 保留默认模板,确保所有节点正常复制 -->
<xsl:template match="@*|node()">
    <xsl:copy>
        <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
</xsl:template>

</xsl:stylesheet>

方案2:使用MSXML扩展(针对微软处理器)

如果你的XSLT处理器是MSXML(如IE、.NET旧版本),改用微软的扩展函数:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
                xmlns:xs="http://www.w3.org/2001/XMLSchema" 
                xmlns:msxsl="urn:schemas-microsoft-com:xslt"
                version="1.0">

<!-- 变量定义不变 -->
<xsl:variable name="descriptions">
    <annotations>
        <annotation element="Element1">Description for Element1</annotation>
        <annotation element="Element2">Description for Element2</annotation>
        <annotation element="Element3">Description for Element3</annotation>
    </annotations>
</xsl:variable>

<xsl:template match="xs:element">
    <xsl:copy>
        <xsl:apply-templates select="@*"/>
        <xsl:variable name="currentName" select="@name"/>
        <!-- 使用msxsl:node-set转换 -->
        <xsl:variable name="matchedDesc" select="msxsl:node-set($descriptions)/annotations/annotation[@element = $currentName]"/>
        
        <!-- 输出注释 -->
        <xs:annotation>
            <xs:documentation>
                <xsl:value-of select="$matchedDesc"/>
            </xs:documentation>
        </xs:annotation>
        
        <xsl:apply-templates select="node()"/>
    </xsl:copy>
</xsl:template>

<xsl:template match="@*|node()">
    <xsl:copy>
        <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
</xsl:template>

</xsl:stylesheet>

额外建议

如果可以升级到XSLT 2.0及以上版本(比如使用Saxon处理器),就不需要依赖扩展函数——XSLT 2.0已统一了结果树片段和节点集的概念,直接用$descriptions/annotations/annotation[@element = @name]这类路径就能访问变量内的元素。

内容的提问来源于stack exchange,提问作者Joost van de Ven

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 21:54:55