我有一个源 xml,其中包含一个元素列表,这些元素可能存在于目标 xml 中,也可能不存在,并且目标 xml 有一些其他 xml 元素。要求是使用第一个 xml 中的元素处的规则 :loop 更新第二个 xml。如果目标 xml 中存在节点,则更新该值,否则将该节点添加到目标 xml 中。 对于下面的示例,我可以对字段名称 f1 、 f2 和 f3 进行硬编码。但我想知道是否可以使其通用,以便有一段转换代码真正说“在第一个 xml 中的元素处循环。如果目标 xml 中存在节点,则更新该值,否则添加一个新节点”无需对每个节点名称进行编码?
参数 XML
<root>
<f1>1<f1>
<f2>2<f2>
<f3>3<f3>
</root>
输入XML
<root>
<f1>a<f1>
<FY>Y<fY>
<fz>Z<fz>
</root>
输出XML
<root>
<f1>1<f1>
<f2>2<f2>
<f3>3<f3>
<FY>Y<fY>
<fz>Z<fz>
</root>
我正在使用 XSLT 版本 1.0
<xsl:param name="SourceData" />
<xsl:variable name="Source_xml" select="parse-xml($SourceData)" />
然后
<xsl:template match="f1">
<f1><xsl:value-of select="$Source_xml//f1"/></f1>
</xsl:template>
<xsl:template match="f2">
<f2><xsl:value-of select="$Source_xml//f2"/></f2>
</xsl:template>
<xsl:template match="f3">
<f3><xsl:value-of select="$Source_xml//f3"/></f3>
</xsl:template>
鉴于(如果
parse-xml()
有效)您正在使用 XSLT 3.0,您可以使用 xsl:merge 指令:
<root>
<xsl:merge>
<xsl:merge-source
for-each-source="'doc1.xml', 'doc2.xml'"
select="/*/*">
<xsl:merge-key select="name()" order="ascending"/>
</xsl:merge-source>
<xsl:merge-action>
<xsl:copy-of select="current-merge-group()[1]"/>
</xsl:merge-action>
</xsl:merge>
</root>
这假设两个输入均按名称排序。如果没有,可以选择
sort-before-merge
来强制执行此操作。