如何使用XSLT合并两个结构相似的XML文件?
如何使用XSLT合并两个结构相似的XML文件?
看起来你想要合并两个结构相近的XML文件,核心需求是:对于reference相同的<common-indicator>条目,要把它们的<reports>内容合并到一起,而不是重复生成相同reference的条目。你原来的XSLT只是简单把两个文件的所有条目拼接,所以会出现重复的REF10,我来帮你调整代码实现正确的合并逻辑:
首先看你的主输入文件01.xml:
<?xml version="1.0" encoding="utf-8" standalone="yes"?> <common-indicators> <common-indicator> <reference>REF01</reference> <name>name1</name> <reports> <report> <id>15</id> <name>name15</name> </report> <report> <id>16</id> <name>name16</name> </report> </reports> </common-indicator> <common-indicator> <reference>REF10</reference> <name>name10</name> <reports> <report> <id>30</id> <name>name30</name> </report> <report> <id>32</id> <name>name32</name> </report> <report> <id>34</id> <name>name34</name> </report> </reports> </common-indicator> </common-indicators>
接下来是修改后的XSLT代码,它会处理主文件和参数传入的第二个XML,合并同reference的reports:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="#all" version="3.0"> <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes" /> <!-- 要合并的第二个XML文件,作为参数传入 --> <xsl:param name="param1"> <common-indicators> <common-indicator> <reference>REF02</reference> <name>name2</name> <reports> <report> <id>17</id> <name>name17</name> </report> <report> <id>18</id> <name>name18</name> </report> </reports> </common-indicator> <common-indicator> <reference>REF10</reference> <name>name10</name> <reports> <report> <id>36</id> <name>name36</name> </report> <report> <id>38</id> <name>name38</name> </report> <report> <id>40</id> <name>name40</name> </report> </reports> </common-indicator> </common-indicators> </xsl:param> <!-- 定义key,按reference字段分组主文件和参数文件的条目 --> <xsl:key name="indicator-by-ref" match="common-indicator" use="reference"/> <xsl:template match="@*|node()"> <xsl:copy> <xsl:apply-templates select="@*|node()"/> </xsl:copy> </xsl:template> <xsl:template match="common-indicators"> <xsl:copy> <!-- 处理主文件中的所有common-indicator --> <xsl:apply-templates select="common-indicator"/> <!-- 添加参数文件中主文件没有的common-indicator --> <xsl:apply-templates select="$param1/common-indicators/common-indicator[not(key('indicator-by-ref', reference, ..))]"/> </xsl:copy> </xsl:template> <!-- 处理common-indicator时,合并同reference的reports --> <xsl:template match="common-indicator"> <xsl:copy> <xsl:apply-templates select="@*|node()[not(self::reports)]"/> <reports> <!-- 保留当前条目的reports --> <xsl:apply-templates select="reports/report"/> <!-- 添加参数文件中同reference条目的reports --> <xsl:apply-templates select="key('indicator-by-ref', reference, $param1/common-indicators)/reports/report"/> </reports> </xsl:copy> </xsl:template> </xsl:stylesheet>
关键逻辑说明:
- 用
<xsl:key>定义了按reference分组的规则,方便快速找到同reference的条目 - 处理主文件的
<common-indicator>时,会把自身的reports和参数文件中同reference条目的reports合并在一起 - 最后只添加参数文件中主文件没有的新
common-indicator,避免重复
运行这个XSLT后,就能得到你想要的合并结果:
<?xml version="1.0" encoding="UTF-8"?> <common-indicators> <common-indicator> <reference>REF01</reference> <name>name1</name> <reports> <report> <id>15</id> <name>name15</name> </report> <report> <id>16</id> <name>name16</name> </report> </reports> </common-indicator> <common-indicator> <reference>REF10</reference> <name>name10</name> <reports> <report> <id>30</id> <name>name30</name> </report> <report> <id>32</id> <name>name32</name> </report> <report> <id>34</id> <name>name34</name> </report> <report> <id>36</id> <name>name36</name> </report> <report> <id>38</id> <name>name38</name> </report> <report> <id>40</id> <name>name40</name> </report> </reports> </common-indicator> <common-indicator> <reference>REF02</reference> <name>name2</name> <reports> <report> <id>17</id> <name>name17</name> </report> <report> <id>18</id> <name>name18</name> </report> </reports> </common-indicator> </common-indicators>
备注:内容来源于stack exchange,提问作者mancubus
相关产品推荐
相关产品推荐

