使用 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>
我是 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>