xsltproc合并XML文件异常:丢失新文件节点求助
解决XML合并时丢失新文件节点的问题
你的问题出在当前的XSLT逻辑上:当匹配Item节点时,只有找到abc.xml中对应measurement的匹配项才会输出,完全忽略了xyz.xml中没有匹配的Item,同时也没有把abc.xml中独有的Item添加进去。
我们需要调整XSLT逻辑,实现三个核心目标:
- 保留xyz.xml中所有的Item:如果在abc.xml找到相同measurement的Item,就用abc的替换;否则保留原xyz的Item
- 把abc.xml中xyz.xml没有的Item补充到结果里
- 保持原有的节点复制逻辑(identity template)
以下是修改后的logic.xslt:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="xml" version="1.0" encoding="UTF-8" standalone="no" indent="yes"/> <!-- 定义key,方便快速查找abc.xml中按measurement匹配的Item --> <xsl:key name="abc-item-by-measurement" match="/schedule/Item" use="measurements/measurement"/> <!-- 基础的identity模板,复制所有未被特殊处理的节点 --> <xsl:template match="@*|node()"> <xsl:copy> <xsl:apply-templates select="@*|node()" /> </xsl:copy> </xsl:template> <!-- 处理xyz.xml中的Item节点 --> <xsl:template match="Item"> <!-- 查找abc.xml中对应measurement的Item --> <xsl:variable name="matching-abc-item" select="key('abc-item-by-measurement', measurements/measurement, document('./abc.xml'))"/> <!-- 如果找到匹配项,输出abc的Item;否则保留当前xyz的Item --> <xsl:choose> <xsl:when test="$matching-abc-item"> <xsl:copy-of select="$matching-abc-item"/> </xsl:when> <xsl:otherwise> <xsl:copy> <xsl:apply-templates select="@*|node()"/> </xsl:copy> </xsl:otherwise> </xsl:choose> </xsl:template> <!-- 处理schedule节点,在复制完xyz的Item后,添加abc中独有的Item --> <xsl:template match="schedule"> <xsl:copy> <!-- 先处理xyz的所有Item(上面的模板会处理替换逻辑) --> <xsl:apply-templates select="Item"/> <!-- 再添加abc中xyz没有的Item --> <xsl:for-each select="document('./abc.xml')/schedule/Item"> <xsl:variable name="current-measurement" select="measurements/measurement"/> <!-- 如果xyz中没有这个measurement的Item,就输出 --> <xsl:if test="not(key('abc-item-by-measurement', $current-measurement))"> <xsl:copy-of select="."/> </xsl:if> </xsl:for-each> </xsl:copy> </xsl:template> </xsl:stylesheet>
逻辑解释:
<xsl:key>定义:创建一个基于measurement值的索引,快速查找abc.xml中的Item,比原有的document()+XPath匹配更高效。- 修改
Item模板:不再只输出匹配的abc Item,而是增加了<xsl:otherwise>分支,保留xyz中没有匹配的Item。 - 新增
schedule模板:先处理xyz的所有Item(完成替换),然后遍历abc的Item,把那些xyz中不存在的Item补充到结果里。
现在执行原命令:
xsltproc logic.xslt xyz.xml > output.xml
得到的输出会和你的预期完全一致:
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <schedule> <Item Id="2"> <measurements> <measurement>Alpha</measurement> </measurements> </Item> <Item Id="4"> <measurements> <measurement>Beta</measurement> </measurements> </Item> <Item Id="9"> <measurements> <measurement>Gamma</measurement> </measurements> </Item> </schedule>
内容的提问来源于stack exchange,提问作者Sambit Mishra
相关产品推荐
相关产品推荐

