比较两个 xml 树节点,并使用 xslt 查找具有值的节点是否存在于另一个节点中

Compare two xml tree nodes and find if a node with a value exists in another using xslt

我有一个 XML 输入,它是两个 xml 的合并格式:

<DATA>
<RECORDS1>
    <RECORD>
        <id>11</id>
        <value>123</value>
    </RECORD>
    <RECORD>
        <id>33</id>
        <value>321</value>
    </RECORD>
    <RECORD>
        <id>55</id>
        <value>121113</value>
    </RECORD>
    ...
</RECORDS1>
<RECORDS2>
    <RECORD>
        <id>11</id>
        <value>123</value>
    </RECORD>
    <RECORD>
        <id>33</id>
        <value>323</value>
    </RECORD>
    <RECORD>
        <id>44</id>
        <value>12333</value>
    </RECORD>
    ...
</RECORDS2>

我需要在输出中复制提供的 RECORDS1 中的记录:

  1. RECORDS1 中的记录在 RECORDS2 中不存在
  2. RECORDS1中的记录在RECORDS2中存在但值不同

此外,如果可以扩展输出,例如使用值为 NEW(当不存在时)作为 CHANGE(当存在但值不同时)的额外字段

输出

<DATA>
<RECORDS>
    <RECORD>
        <id>33</id>
        <value>321</value>
        <kind>Change</kind>
    </RECORD>
    <RECORD>
        <id>55</id>
        <value>121113</value>
        <kind>New</kind>
    </RECORD>
    ...
</RECORDS>

我已经应用了 FOR 循环,但由于无法重置 xslt 中的变量,因此它不起作用。

有什么想法吗?

也许

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    exclude-result-prefixes="#all"
    version="2.0">
    
  <xsl:output indent="yes"/>

  <xsl:key name="rec2-complete" match="RECORDS2/RECORD" use="concat(id, '|', value)"/>
  <xsl:key name="rec2-id" match="RECORDS2/RECORD" use="id"/>
  
  <xsl:template match="DATA">
      <xsl:apply-templates select="RECORDS1/RECORD[not(key('rec2-complete', concat(id, '|', value)))]"/>
  </xsl:template>
  
  <xsl:template match="RECORDS1/RECORD">
      <xsl:copy>
          <xsl:copy-of select="node()"/>
          <merged>
              <xsl:value-of select="if (key('rec2-id', id)/value != value) then 'changed' else 'new'"/>
          </merged>
      </xsl:copy>
  </xsl:template>
  
</xsl:stylesheet>

执行要求。

或者,要构建您现在显示的完整结果,请使用

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    exclude-result-prefixes="#all"
    version="2.0">
    
  <xsl:output indent="yes"/>

  <xsl:key name="rec2-complete" match="RECORDS2/RECORD" use="concat(id, '|', value)"/>
  <xsl:key name="rec2-id" match="RECORDS2/RECORD" use="id"/>
  
  <xsl:template match="DATA">
      <xsl:copy>
          <RECORDS>
              <xsl:apply-templates select="RECORDS1/RECORD[not(key('rec2-complete', concat(id, '|', value)))]"/>
          </RECORDS>
      </xsl:copy>
  </xsl:template>
  
  <xsl:template match="RECORDS1/RECORD">
      <xsl:copy>
          <xsl:copy-of select="node()"/>
          <kind>
              <xsl:value-of select="if (key('rec2-id', id)/value != value) then 'change' else 'new'"/>
          </kind>
      </xsl:copy>
  </xsl:template>
  
</xsl:stylesheet>