使用 xslt 3.0 基于元素属性合并(左连接)2 XML 个文件

Merge (Left Join) 2 XML files based on an Element attribute using xslt 3.0

我是 xslt 的新手,我试图合并 2 个 xml 文件 - 期待类似 Left join 的东西,但它没有按预期工作。如果你们能帮助我,我将不胜感激。

第二个文件中匹配的 ID 应将其数据合并到第一个文件中,并忽略其余不匹配的 ID。

<xsl:stylesheet version="3.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:fn="http://www.w3.org/2005/xpath-functions"
    xmlns:math="http://www.w3.org/2005/xpath-functions/math"
    xmlns:array="http://www.w3.org/2005/xpath-functions/array"
    xmlns:map="http://www.w3.org/2005/xpath-functions/map" exclude-result-prefixes="array fn map math xs">
    <xsl:mode on-no-match="shallow-copy"/>
    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
    <xsl:param name="doc1">
        <RECORDS>
            <RECORD>
                <PROP NAME="A">
                    <PVAL>text A</PVAL>
                </PROP>
                <PROP NAME="B">
                    <PVAL>text B</PVAL>
                </PROP>
                <PROP NAME="C">
                    <PVAL>10</PVAL>
                </PROP>
                <PROP NAME="Id">
                    <PVAL>1</PVAL>
                </PROP>
            </RECORD>
            <RECORD>
                <PROP NAME="D">
                    <PVAL>text D</PVAL>
                </PROP>
                <PROP NAME="E">
                    <PVAL>text E</PVAL>
                </PROP>
                <PROP NAME="F">
                    <PVAL>10</PVAL>
                </PROP>
                <PROP NAME="Id">
                    <PVAL>2</PVAL>
                </PROP>
            </RECORD>
            <RECORD>
                <PROP NAME="G">
                    <PVAL>text G</PVAL>
                </PROP>
                <PROP NAME="H">
                    <PVAL>text H</PVAL>
                </PROP>
                <PROP NAME="I">
                    <PVAL>10</PVAL>
                </PROP>
                <PROP NAME="Id">
                    <PVAL>3</PVAL>
                </PROP>
            </RECORD>
        </RECORDS>
    </xsl:param>
    <xsl:param name="doc2">
        <RECORDS>
            <RECORD>
                <PROP NAME="J">
                    <PVAL>text J</PVAL>
                </PROP>
                <PROP NAME="K">
                    <PVAL>text K</PVAL>
                </PROP>
                <PROP NAME="L">
                    <PVAL>10</PVAL>
                </PROP>
                <PROP NAME="Id">
                    <PVAL>1</PVAL>
                </PROP>
            </RECORD>
            <RECORD>
                <PROP NAME="M">
                    <PVAL>text M</PVAL>
                </PROP>
                <PROP NAME="N">
                    <PVAL>text N</PVAL>
                </PROP>
                <PROP NAME="O">
                    <PVAL>10</PVAL>
                </PROP>
                <PROP NAME="Id">
                    <PVAL>4</PVAL>
                </PROP>
            </RECORD>
        </RECORDS>
    </xsl:param>
    <xsl:template match="/" name="xsl:initial-template">
            <xsl:merge>
                <xsl:merge-source select="$doc1/RECORDS/RECORD">
                    <xsl:merge-key select="PROP/@Id"></xsl:merge-key>
                </xsl:merge-source>
                <xsl:merge-source select="$doc2/RECORDS/RECORD">
                    <xsl:merge-key select="PROP/@Id"></xsl:merge-key>
                </xsl:merge-source>
                <xsl:merge-action>
                    <xsl:copy>
                        <xsl:apply-templates select="current-merge-group()[1]/*, fn:current-merge-group()[2]/*"/>
                    </xsl:copy>
                </xsl:merge-action>
            </xsl:merge>
    </xsl:template>
</xsl:stylesheet>

预期结果:

<?xml version="1.0" encoding="UTF-8"?>
<RECORDS>
   <RECORD>
      <PROP NAME="Id">
         <PVAL>1</PVAL>
      </PROP>
      <PROP NAME="A">
         <PVAL>text A</PVAL>
      </PROP>
      <PROP NAME="B">
         <PVAL>text B</PVAL>
      </PROP>
      <PROP NAME="C">
         <PVAL>10</PVAL>
      </PROP>
      <PROP NAME="J">
         <PVAL>text J</PVAL>
      </PROP>
      <PROP NAME="K">
         <PVAL>text K</PVAL>
      </PROP>
      <PROP NAME="L">
         <PVAL>10</PVAL>
      </PROP>
   </RECORD>
   <RECORD>
      <PROP NAME="Id">
         <PVAL>2</PVAL>
      </PROP>
      <PROP NAME="D">
         <PVAL>text D</PVAL>
      </PROP>
      <PROP NAME="E">
         <PVAL>text E</PVAL>
      </PROP>
      <PROP NAME="F">
         <PVAL>10</PVAL>
      </PROP>
   </RECORD>
   <RECORD>
      <PROP NAME="Id">
         <PVAL>3</PVAL>
      </PROP>
      <PROP NAME="G">
         <PVAL>text G</PVAL>
      </PROP>
      <PROP NAME="H">
         <PVAL>text H</PVAL>
      </PROP>
      <PROP NAME="I">
         <PVAL>10</PVAL>
      </PROP>
   </RECORD>
</RECORDS>

您的路径与输入结构不匹配,并且您没有检查第一个合并源中是否存在匹配项,因此以下更改应该有效:

<xsl:template match="/" name="xsl:initial-template">
        <xsl:merge>
            <xsl:merge-source name="doc1" select="$doc1/RECORDS/RECORD">
                <xsl:merge-key select="PROP[@NAME = 'Id']/PVAL"></xsl:merge-key>
            </xsl:merge-source>
            <xsl:merge-source name="doc2" select="$doc2/RECORDS/RECORD">
                <xsl:merge-key select="PROP[@NAME = 'Id']/PVAL"></xsl:merge-key>
            </xsl:merge-source>
            <xsl:merge-action>
                <xsl:if test="current-merge-group('doc1')">
                    <xsl:copy>
                        <xsl:apply-templates select="*, current-merge-group('doc2')/*"/>
                    </xsl:copy>
                </xsl:if>
            </xsl:merge-action>
        </xsl:merge>
</xsl:template>

https://xsltfiddle.liberty-development.net/6q1SDkj