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

基于CID节点对比XML Sibling节点差异并提取结果的XSLT求助

基于CID对比XML节点并提取差异的XSLT解决方案

核心思路

放弃使用accumulator,改用XSLT 3.0的xsl:key建立CID索引,快速关联两个数据源中同CID的节点,再逐个对比兄弟节点的值,只保留有差异的部分。这种方式比accumulator更适配“按ID关联+值对比”的场景。

输入示例

假设输入XML包含两个数据源:

<sources>
  <source1>
    <record>
      <CID>1001</CID>
      <Name>Alice</Name>
      <Age>30</Age>
      <City>New York</City>
    </record>
    <record>
      <CID>1002</CID>
      <Name>Bob</Name>
      <Age>25</Age>
      <City>London</City>
    </record>
  </source1>
  <source2>
    <record>
      <CID>1001</CID>
      <Name>Alice M.</Name>
      <Age>30</Age>
      <City>New York</City>
    </record>
    <record>
      <CID>1002</CID>
      <Name>Bob</Name>
      <Age>26</Age>
      <City>Paris</City>
    </record>
    <record>
      <CID>1003</CID>
      <Name>Charlie</Name>
      <Age>35</Age>
    </record>
  </source2>
</sources>

预期输出示例

仅保留同CID下值存在差异的节点,并标注来源:

<differences>
  <record CID="1001">
    <diff field="Name">
      <source1>Alice</source1>
      <source2>Alice M.</source2>
    </diff>
  </record>
  <record CID="1002">
    <diff field="Age">
      <source1>25</source1>
      <source2>26</source2>
    </diff>
    <diff field="City">
      <source1>London</source1>
      <source2>Paris</source2>
    </diff>
  </record>
</differences>

XSLT 3.0实现代码

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

  <!-- 为两个数据源的record建立CID索引 -->
  <xsl:key name="source1-cid-index" match="source1/record" use="CID"/>
  <xsl:key name="source2-cid-index" match="source2/record" use="CID"/>

  <xsl:template match="/">
    <differences>
      <!-- 遍历同时存在于两个数据源的CID对应的record -->
      <xsl:for-each select="sources/source1/record[key('source2-cid-index', CID)]">
        <xsl:variable name="current-cid" select="CID"/>
        <xsl:variable name="src1-node" select="."/>
        <xsl:variable name="src2-node" select="key('source2-cid-index', $current-cid)"/>

        <!-- 仅当当前CID下存在差异节点时生成record -->
        <xsl:if test="$src1-node/*[not(self::CID)] ne $src2-node/*[not(self::CID)]">
          <record CID="{$current-cid}">
            <!-- 对比除CID外的所有子节点 -->
            <xsl:for-each select="$src1-node/*[not(self::CID)]">
              <xsl:variable name="field" select="local-name()"/>
              <xsl:variable name="val1" select="."/>
              <xsl:variable name="val2" select="$src2-node/*[local-name() = $field]"/>

              <!-- 值不同则生成diff节点 -->
              <xsl:if test="$val1 ne $val2">
                <diff field="{$field}">
                  <source1><xsl:value-of select="$val1"/></source1>
                  <source2><xsl:value-of select="$val2"/></source2>
                </diff>
              </xsl:if>
            </xsl:for-each>
          </record>
        </xsl:if>
      </xsl:for-each>
    </differences>
  </xsl:template>
</xsl:stylesheet>

代码说明

  1. 索引建立:用xsl:key分别给两个数据源的record节点按CID建立索引,能快速定位同ID的节点,避免低效遍历。
  2. CID过滤:只处理同时出现在两个数据源中的CID,忽略单边存在的记录(比如示例中的CID1003)。
  3. 差异检查:遍历除CID外的所有子节点,用ne(非相等)运算符对比值,仅生成有差异的diff节点。
  4. 输出优化:只有当某个CID下存在至少一个差异节点时,才生成对应的<record>标签,减少冗余内容。

扩展说明

如果需要处理节点缺失/空值的场景(比如某个CID下source1有Age节点,source2没有),可以修改差异判断条件:

<xsl:if test="$val1 ne $val2 or not(exists($val2)) or not(exists($val1))">

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 15:33:13