我有两个文件,并希望根据节点树中的特定匹配值来组合/覆盖整个节点。
file1.xml
<record>
<key>key1</key>
<nodel>
<field1>source field1</field1>
<field2>source field2</field2>
<searchkey>myname</searchkey>
</nodel>
</record>
file2.xml
<record>
<key>key2</key>
<nodel>
<field1>match field1</field1>
<field2>match field2</field2>
<searchkey>myname</searchkey>
</nodel>
</record>
期望的输出:
<record>
<key>key1</key>
<nodel>
<field1>source field1</field1>
<field2>source field2</field2>
<searchkey>myname</searchkey>
</nodel>
<nodel>
<field1>match field1</field1>
<field2>match field2</field2>
<searchkey>myname</searchkey>
</nodel>
</record>
所以,我想在两个文件之间的searchkey中检查匹配,如果匹配,则将匹配的整个节点复制到输出文件,但保留原始密钥,而不是匹配密钥。然后,我将删除原始nodel,但我很乐意将其作为后续转换。
我确实询问了最近在<key>
节点上进行匹配的类似问题,但无法弄清楚如何修改它以实现所需的结果。
感谢。
答案 0 :(得分:1)
此转化:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:my="my:my">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<my:file2>
<record>
<key>key2</key>
<nodel>
<field1>match field1</field1>
<field2>match field2</field2>
<searchkey>myname</searchkey>
</nodel>
</record>
</my:file2>
<xsl:variable name="vFile2"
select="document('')/*/my:file2/*"/>
<xsl:template match="node()|@*" name="identity">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="/*/*[starts-with(name(),'node')]">
<xsl:call-template name="identity"/>
<xsl:apply-templates mode="copy" select=
"$vFile2/*[starts-with(name(),'node')]
[searchkey=current()/searchkey]
"/>
</xsl:template>
<xsl:template match="node()" mode="copy">
<xsl:call-template name="identity"/>
</xsl:template>
</xsl:stylesheet>
应用于提供的第一个XML文档:
<record>
<key>key1</key>
<nodel>
<field1>source field1</field1>
<field2>source field2</field2>
<searchkey>myname</searchkey>
</nodel>
</record>
会产生想要的正确结果:
<record>
<key>key1</key>
<nodel>
<field1>source field1</field1>
<field2>source field2</field2>
<searchkey>myname</searchkey>
</nodel>
<nodel>
<field1>match field1</field1>
<field2>match field2</field2>
<searchkey>myname</searchkey>
</nodel>
</record>
注意:第二个XML文档在样式表中以内联方式表示 - 这只是为了方便起见。实际上,它将驻留在自己的文件中,只有$vFile2
的定义将更改为:
<xsl:variable name="vFile2"
select="document('someFileURIHere')/*"/>
答案 1 :(得分:1)
带密钥的解决方案:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:key name="kNodeBySearchkey" match="*[searchkey]" use="searchkey"/>
<xsl:param name="pSource2" select="'file2.xml'"/>
<xsl:variable name="vSource2" select="document($pSource2,/)"/>
<xsl:template match="node()|@*" name="identity">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="*[searchkey]">
<xsl:variable name="vKey" select="searchkey"/>
<xsl:call-template name="identity"/>
<xsl:for-each select="$vSource2">
<xsl:for-each select="key('kNodeBySearchkey',$vKey)">
<xsl:call-template name="identity"/>
</xsl:for-each>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
输出:
<record>
<key>key1</key>
<nodel>
<field1>source field1</field1>
<field2>source field2</field2>
<searchkey>myname</searchkey>
</nodel>
<nodel>
<field1>source field1</field1>
<field2>source field2</field2>
<searchkey>myname</searchkey>
</nodel>
</record>
注意:我不想保留原始nodel
,只需删除第一条xsl:call-template
指令。
答案 2 :(得分:0)
尝试输入文件名:
XSL
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:param name="pSource2" select="'file2.xml'"/>
<xsl:variable name="vFile2" select="document($pSource2)/*"/>
<xsl:template match="node()|@*" name="identity">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="/*/*[starts-with(name(),'node')]">
<xsl:call-template name="identity"/>
<xsl:apply-templates select=
"$vFile2/*[starts-with(name(),'node')]
[searchkey=current()/searchkey]
"/>
</xsl:template>
</xsl:stylesheet>
给予
<record>
<key>key1</key>
<nodel>
<field1>source field1</field1>
<field2>source field2</field2>
<searchkey>myname</searchkey>
</nodel>
<nodel>
<field1>match field1</field1>
<field2>match field2</field2>
<searchkey>myname</searchkey>
</nodel>
重复第二个节点直到它放弃。