我有以下源XML文档:
<UserDefinedFields>
<UserDefinedField>
<Name>ABC</Name>
<Value>123</Value>
</UserDefinedField>
<UserDefinedField>
<Name>XYZ</Name>
<Value>645q3245</Value>
</UserDefinedField>
</UserDefinedFields>
如果存在匹配的<Name>
值,我想覆盖输入XML中的匹配节点。换句话说,合并它的最终结果是:
<UserDefinedField>
<Name>XYZ</Name>
<Value>NEWVALUE!</Value>
</UserDefinedField>
......将是:
<UserDefinedFields>
<UserDefinedField>
<Name>ABC</Name>
<Value>123</Value>
</UserDefinedField>
<UserDefinedField>
<Name>XYZ</Name>
<Value>NEWVALUE!</Value>
</UserDefinedField>
</UserDefinedFields>
实现这一目标的适当XSLT转换是什么?
XSLT 2.0或1.0答案很好......但是首选2.0。
答案 0 :(得分:1)
您可以使用分组执行此操作:
<xsl:for-each-group
select="$doc1//UserDefinedField, $doc2//UserDefinedField"
group-by="Name">
<xsl:copy-of select="current-group()[last()]"/>
</xsl:for-each-group>
答案 1 :(得分:0)
假设您指示处理器处理“初始”XML文档,并提供“覆盖”文档的路径作为参数,您可以这样做:
XSLT 2.0
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:param name="path-to-update">update.xml</xsl:param>
<xsl:key name="fld" match="UserDefinedField" use="Name" />
<!-- identity transform -->
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="Value">
<xsl:variable name="update" select="key('fld', ../Name, document($path-to-update))" />
<xsl:copy>
<xsl:value-of select="if ($update) then $update/Value else ."/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
答案 2 :(得分:0)
只需使用此模板覆盖身份规则:
<xsl:template match="UserDefinedField[key('kFieldByName', Name, $vDoc2)]/Value/text()">
<xsl:value-of select="key('kFieldByName', ../../Name, $vDoc2)[1]"/>
</xsl:template>
这里我假设第二个文档有一个文档元素(顶部元素),并且可以包含不同深度的许多UserDefinedField
个元素。仅为方便起见,第二个文档在转换中内联 - 在实际情况下,可以使用doc()
函数。我还声明<xsl:key>
使用第二个文档中Name
孩子的UserDefinedField
值来有效地找到新值。
以下是完整转型:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:key name="kFieldByName" match="Value" use="../Name"/>
<xsl:variable name="vDoc2">
<patterns>
<UserDefinedField>
<Name>XYZ</Name>
<Value>NEWVALUE!</Value>
</UserDefinedField>
</patterns>
</xsl:variable>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="UserDefinedField[key('kFieldByName', Name, $vDoc2)]/Value/text()">
<xsl:value-of select="key('kFieldByName', ../../Name, $vDoc2)[1]"/>
</xsl:template>
</xsl:stylesheet>
在提供的XML文档上应用此转换时:
<UserDefinedFields>
<UserDefinedField>
<Name>ABC</Name>
<Value>123</Value>
</UserDefinedField>
<UserDefinedField>
<Name>XYZ</Name>
<Value>645q3245</Value>
</UserDefinedField>
</UserDefinedFields>
产生了想要的正确结果:
<UserDefinedFields>
<UserDefinedField>
<Name>ABC</Name>
<Value>123</Value>
</UserDefinedField>
<UserDefinedField>
<Name>XYZ</Name>
<Value>NEWVALUE!</Value>
</UserDefinedField>
</UserDefinedFields>