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

XSLT匹配:当值存在于列表/数组时提取指定XML节点

按指定ID列表提取XML中的节点

需求说明

有大量XML格式文档,需要根据一组ID值筛选<fig>节点:仅保留id属性值存在于目标ID列表中的<fig>节点,其余忽略。尝试过使用参数、变量及exsl:node-set但未成功。

输入XML

<?xml version="1.0" encoding="UTF-8"?>
<sec xmlns:xlink="http://www.w3.org/1999/xlink">
   <title>Section Title</title>
   <fig id="img01">
      <caption><title>Image 1</title></caption>
      <graphic xlink:href="img01.eps"/>
   </fig>

   <fig id="img02">
      <caption><title>Image 2</title></caption>
      <graphic xlink:href="img02.eps"/>
   </fig>
</sec>

目标ID列表

  • img02
  • img12
  • img23
  • img34
  • (更多ID)

期望输出XML

<?xml version="1.0" encoding="UTF-8"?>
<sec xmlns:xlink="http://www.w3.org/1999/xlink">
   <title>Section Title</title>
   <fig id="img02">
      <caption><title>Image 2</title></caption>
      <graphic xlink:href="img02.eps"/>
   </fig>
</sec>

尝试的XSLT代码

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:exsl="http://exslt.org/common" xmlns:xlink="http://www.w3.org/1999/xlink" exclude-result-prefixes="exsl" version="2">

    <xsl:param name="ListOfImages" as="element()">
        <item>img02</item>
        <item>hundreds-of-image-IDs</item>
    </xsl:param>

    <xsl:template match="/">
        <sec>
            <xsl:apply-templates/>
        </sec>

    </xsl:template>

    <xsl:template match="fig[exsl:node-set($ListOfImages)/item = exsl:node-set(@id)]">
        <p>Image Name: <xsl:value-of select="@id"/></p>
        <xsl:copy-of select="."/>
    </xsl:template>

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

</xsl:stylesheet>

问题分析与解决方案

你的代码存在几个关键问题:

  1. XSLT版本误用:已声明使用XSLT 2.0,却仍用了仅XSLT 1.0需要的exsl:node-set(),XSLT 2.0支持直接处理节点集参数,无需转换。
  2. 匹配条件错误:exsl:node-set(@id)是错误用法,@id是属性节点,不需要用node-set转换,直接比较即可。
  3. 模板逻辑问题:默认模板会忽略元素的属性和结构,导致输出的<sec>丢失命名空间,且不需要额外输出<p>标签。

正确的XSLT 2.0实现

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xlink="http://www.w3.org/1999/xlink" version="2.0">
    <!-- 定义目标ID列表参数,用元素节点存储 -->
    <xsl:param name="ListOfImages">
        <item>img02</item>
        <item>img12</item>
        <item>img23</item>
        <item>img34</item>
    </xsl:param>

    <!-- 复制整个文档结构,仅筛选指定fig节点 -->
    <xsl:template match="@* | node()">
        <xsl:copy>
            <xsl:apply-templates select="@* | node()"/>
        </xsl:copy>
    </xsl:template>

    <!-- 匹配id不在目标列表中的fig节点,不输出 -->
    <xsl:template match="fig[not(@id = $ListOfImages/item)]"/>
</xsl:stylesheet>

代码说明

  • 身份模板:match="@* | node()"的模板会复制所有原节点和属性,保证文档结构、命名空间等信息完整保留。
  • 筛选逻辑:专门匹配id不在目标列表中的<fig>节点,且模板为空,相当于删除这些节点;符合条件的<fig>会被身份模板正常复制。
  • 参数简化:XSLT 2.0中直接使用$ListOfImages/item即可获取所有目标ID值,无需额外转换。

若需兼容XSLT 1.0

如果你的处理器仅支持XSLT 1.0,可调整参数为字符串列表,用contains结合分隔符判断:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.0">
    <!-- 用逗号分隔的字符串作为ID列表参数 -->
    <xsl:param name="ListOfImages" select="'img02,img12,img23,img34'"/>

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

    <!-- 匹配id不在目标列表中的fig节点 -->
    <xsl:template match="fig[not(contains(concat(',', $ListOfImages, ','), concat(',', @id, ',')))]"/>
</xsl:stylesheet>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 14:29:56