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

如何在XSLT中关联具有相同定义及映射关系的ID?

问题1:XSLT中关联相同定义的ID

当多个元素共享同一个ID值时,最直接的方式是用XSLT的<xsl:key>建立索引,通过key()函数快速查找所有匹配该ID的节点。

举个实际场景:假设你的XML结构如下:

<root>
  <product id="P001" name="Laptop"/>
  <order-item product-id="P001" quantity="2"/>
  <inventory product-id="P001" stock="15"/>
</root>

你可以在XSLT中定义key:

<xsl:key name="product-by-id" match="product" use="@id"/>

之后在处理order-item或inventory时,就能通过key('product-by-id', @product-id)获取对应的<product>节点,实现ID关联。如果有多个节点匹配同一个ID,key()会返回所有匹配的节点集合,你可以用for-each或者其他方式遍历处理。

问题2:处理链式ID映射场景

针对你给出的ID映射规则:

id=1 => id=2
id=2 => id=null
id=3 => id=2
id=4 => id=3

这种链式映射需要递归解析最终的目标ID(直到遇到null或循环),可以按以下步骤实现:

步骤1:定义映射数据

先在XSLT中嵌入映射规则,比如用一个内部的XML片段:

<xsl:variable name="id-mappings">
  <map from="1" to="2"/>
  <map from="2" to=""/> <!-- 对应null -->
  <map from="3" to="2"/>
  <map from="4" to="3"/>
</xsl:variable>
<!-- 将变量转为节点集(XSLT 1.0需要,XSLT 2.0+可省略) -->
<xsl:variable name="mapping-nodes" select="document('')//xsl:variable[@name='id-mappings']/*"/>

步骤2:建立映射索引

用<xsl:key>关联映射的from和to值:

<xsl:key name="id-map" match="map" use="@from"/>

步骤3:递归解析映射(XSLT 3.0+ 用函数)

如果用XSLT 3.0,写一个递归函数来解析最终ID:

<xsl:function name="my:resolve-final-id" as="xs:string?">
  <xsl:param name="current-id" as="xs:string"/>
  <!-- 获取当前ID的映射值 -->
  <xsl:variable name="mapped-id" select="key('id-map', $current-id, $mapping-nodes)/@to"/>
  
  <xsl:choose>
    <!-- 如果映射值存在且不是自身(避免循环),继续递归 -->
    <xsl:when test="$mapped-id and $mapped-id != $current-id">
      <xsl:sequence select="my:resolve-final-id($mapped-id)"/>
    </xsl:when>
    <!-- 否则返回最终结果(空值对应null) -->
    <xsl:otherwise>
      <xsl:sequence select="$mapped-id"/>
    </xsl:otherwise>
  </xsl:choose>
</xsl:function>

调用示例:my:resolve-final-id('4')会返回2,my:resolve-final-id('2')返回空字符串(对应你的null)。

步骤3(兼容XSLT 1.0:用递归模板)

如果需要兼容XSLT 1.0,改用递归模板:

<xsl:template name="resolve-final-id">
  <xsl:param name="current-id"/>
  <xsl:variable name="mapped-id" select="key('id-map', $current-id, $mapping-nodes)/@to"/>
  
  <xsl:if test="$mapped-id and $mapped-id != $current-id">
    <xsl:call-template name="resolve-final-id">
      <xsl:with-param name="current-id" select="$mapped-id"/>
    </xsl:call-template>
  </xsl:if>
  
  <xsl:if test="not($mapped-id) or $mapped-id = $current-id">
    <xsl:value-of select="$mapped-id"/>
  </xsl:if>
</xsl:template>

调用示例:

<xsl:call-template name="resolve-final-id">
  <xsl:with-param name="current-id" select="'1'"/>
</xsl:call-template>

返回结果为2。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 14:13:16