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

基于XSLT 2.0/1.0实现XML元素遍历与文档访问逻辑的问询

XSLT实现方案:处理summary元素并加载关联文档的name元素

先把你的核心需求再明确下,确保没理解错:

  • 遍历所有带@name='summary'的元素
  • 定位到该元素的父节点,收集父节点下所有后代<info>元素(要排除当前这个@name='summary'的元素本身)
  • 对这些<info>,根据@id对应的URI加载外部XML文档,输出文档里的<name>元素
  • 特殊规则:如果当前@name='summary'的元素带有@level='top',则跳过所有@duplicate='yes'的<info>元素

XSLT 2.0 实现

XSLT 2.0的语法更灵活,能写出更简洁的逻辑,代码如下:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" indent="yes"/>

    <!-- 匹配所有@name='summary'的元素 -->
    <xsl:template match="*[@name='summary']">
        <xsl:variable name="current-summary" select="."/>
        <!-- 获取父元素下的所有后代info,排除自身 -->
        <xsl:variable name="target-infos" select="$current-summary/ancestor::*[1]//info[not(. is $current-summary)]"/>
        
        <!-- 根据当前summary的level属性过滤info -->
        <xsl:variable name="filtered-infos" select="
            if ($current-summary/@level='top') then
                $target-infos[not(@duplicate='yes')]
            else
                $target-infos
        "/>

        <!-- 遍历过滤后的info,加载对应文档并输出name -->
        <xsl:for-each select="$filtered-infos">
            <xsl:variable name="doc-uri" select="@id"/>
            <!-- 加载外部文档,获取name元素 -->
            <xsl:copy-of select="document($doc-uri)//name"/>
        </xsl:for-each>
    </xsl:template>

    <!-- 匹配其他节点,避免默认输出原文档结构 -->
    <xsl:template match="text()|@*"/>
</xsl:stylesheet>

代码说明:

  1. 先匹配所有带@name='summary'的元素,用变量保存当前节点
  2. 通过ancestor::*[1]定位到父元素,然后选取其下所有后代<info>,用not(. is $current-summary)排除自身
  3. 根据当前summary是否有@level='top',决定是否过滤掉@duplicate='yes'的info元素
  4. 遍历过滤后的info,用document($doc-uri)加载对应URI的XML文档,然后输出里面的所有<name>元素

XSLT 1.0 实现

XSLT 1.0没有is运算符,也不支持简洁的条件表达式,得用节点集比较和xsl:if来处理,同时文档加载要注意URI的处理:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:exsl="http://exslt.org/common"
                extension-element-prefixes="exsl">
    <xsl:output method="xml" indent="yes"/>

    <xsl:template match="*[@name='summary']">
        <xsl:variable name="current-summary-id" select="generate-id(.)"/>
        <xsl:variable name="parent-node" select="parent::*"/>
        
        <!-- 收集父元素下的所有后代info,排除自身 -->
        <xsl:variable name="target-infos-raw">
            <xsl:for-each select="$parent-node//info">
                <xsl:if test="generate-id(.) != $current-summary-id">
                    <xsl:copy-of select="."/>
                </xsl:if>
            </xsl:for-each>
        </xsl:variable>
        <xsl:variable name="target-infos" select="exsl:node-set($target-infos-raw)/info"/>

        <!-- 过滤info:如果当前summary是top级别,跳过duplicate=yes的 -->
        <xsl:variable name="filtered-infos-raw">
            <xsl:for-each select="$target-infos">
                <xsl:if test="not($current-summary/@level='top' and @duplicate='yes')">
                    <xsl:copy-of select="."/>
                </xsl:if>
            </xsl:for-each>
        </xsl:variable>
        <xsl:variable name="filtered-infos" select="exsl:node-set($filtered-infos-raw)/info"/>

        <!-- 遍历加载文档并输出name -->
        <xsl:for-each select="$filtered-infos">
            <xsl:variable name="doc-uri" select="@id"/>
            <xsl:copy-of select="document($doc-uri)//name"/>
        </xsl:for-each>
    </xsl:template>

    <xsl:template match="text()|@*"/>
</xsl:stylesheet>

代码说明:

  1. 用generate-id()来区分当前summary元素和其他info元素——因为XSLT 1.0没有is运算符,这是常用的替代方案
  2. 借助exsl:node-set扩展函数(大部分XSLT 1.0处理器都支持)将临时生成的节点转换为可遍历的节点集
  3. 通过xsl:if实现条件过滤:当当前summary是@level='top'时,跳过所有@duplicate='yes'的info
  4. 同样用document()加载外部文档,输出<name>元素

针对你给出的XML示例测试

比如你的示例结构:

<map>
    <info id="a.xml" level="top" name="summary"/>
    <map id="b.xml">
        <info id="c.xml" name="summary">
            <info id="d.xml" duplicate="yes"/>
            <info id="e.xml"/>
        </info>
    </map>
</map>
  • 对于<info id="a.xml" level="top" name="summary"/>,会找其父元素<map>下的所有后代info,也就是<info id="d.xml" duplicate="yes"/>和<info id="e.xml"/>,但因为它是level='top',所以跳过duplicate='yes'的,只加载e.xml并输出其中的<name>
  • 对于<info id="c.xml" name="summary">,会找其父元素<map id="b.xml">下的后代info,也就是自身下的两个info,排除自身后,两个都处理,加载d.xml和e.xml并输出它们的<name>

内容的提问来源于stack exchange,提问作者DitaNewbie La

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 07:39:08