xml使用xsl合并两个文件?
我需要合并两个类似的xml文件,但只合并与公共标记匹配的记录,例如下面示例中的xml使用xsl合并两个文件?,xml,xslt,msxsl,Xml,Xslt,Msxsl,我需要合并两个类似的xml文件,但只合并与公共标记匹配的记录,例如下面示例中的: file1.xml是 <node> <type>a</type> <name>joe</name> </node> <node> <type>b</type> <name>sam</name> </node> A. 乔 B 山姆 fil
:
file1.xml是
<node>
<type>a</type>
<name>joe</name>
</node>
<node>
<type>b</type>
<name>sam</name>
</node>
A.
乔
B
山姆
file2.xml是
<node>
<type>a</type>
<name>jill</name>
</node>
A.
吉尔
所以我有一个
<node>
<type>a</type>
<name>jill</name>
<name>joe</name>
</node>
<node>
<type>b</type>
<name>sam</name>
</node>
A.
吉尔
乔
B
山姆
在xsl中,这样做的基础是什么?
非常感谢。此样式表:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:key name="kElementByType" match="*[not(self::type)]" use="../type"/>
<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="type">
<xsl:variable name="vCurrent" select="."/>
<xsl:call-template name="identity"/>
<xsl:for-each select="$vSource2">
<xsl:apply-templates select="key('kElementByType',$vCurrent)"/>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
使用此输入(格式正确):
A.
乔
B
山姆
输出:
<root>
<node>
<type>a</type>
<name>jill</name>
<name>joe</name>
</node>
<node>
<type>b</type>
<name>sam</name>
</node>
</root>
A.
吉尔
乔
B
山姆
一种方法是将第二个xml作为参数传递
第二种更简单的方法是将一个根元素下的两个XML连接到
<root>
<node>
<type>a</type>
<name>joe</name>
</node>
<node>
<type>b</type>
<name>sam</name>
</node>
<node>
<type>a</type>
<name>jill</name>
</node>
</root>
A.
乔
B
山姆
A.
吉尔
然后使用2合并它
<xsl:template match="/root">
<xsl:for-each select="node">
<xsl:variable name="type" select="type"/>
<node>
<type><xsl:value-of select="$type"/></type>
<xsl:for-each select="../node[type=$type]">
<name><xsl:value-of select"name"/></name>
</xsl:for-each>
</node>
</xsl:for-each>
</xsl:template>
我认为值得在做这件事的同时添加一些我学到的额外信息,以防对其他初学者有用。我已经更改了测试代码名,以便它们不会与xsl中使用的某些术语混淆。我不知道这是做事情的最好或最有效的方式,但它是有效的(有一些警告!) 我想保留“info”节点,但原始代码丢失了它。编码单独的匹配模板将其保留在输出中。另外,按照我的编码方式,只有在输入文件(x1)中才保留该节点。如果它在(x2)文件中,那么它不会被保留。这必须与我编写迭代的方式一致。理想情况下,我希望从任何一个输入文件中保留它,但还没有解决如何做到这一点。另外,我希望可以选择通过msxsl将文件名x2作为参数传递,而不是硬编码。肯定有办法,但我还没找到 xsl文件:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:key name="kElementByType" match="*[not(self::keynode)]" use="../keynode"/>
<xsl:param name="pSource2" select="'x2.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="info">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="keynode">
<xsl:variable name="vCurrent" select="."/>
<xsl:call-template name="identity"/>
<xsl:for-each select="$vSource2">
<xsl:apply-templates select="key('kElementByType',$vCurrent)"/>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
使用以下数据给出以下结果:
文件x1.xml:
<root>
<info>
<id>147</id>
</info>
<nodetype>
<keynode>annajon</keynode>
<note>
<source>source1</source>
<name>Anna Jones</name>
</note>
</nodetype>
<nodetype>
<keynode>brucejon</keynode>
<note>
<source>source1</source>
<name>Bruce Jones</name>
</note>
</nodetype>
</root>
147
安纳洪
资料来源1
安娜·琼斯
布鲁塞戎
资料来源1
布鲁斯·琼斯
文件x2.xml:
<root>
<nodetype>
<keynode>annajon</keynode>
<note>
<source>source2</source>
<name>Anna Jones</name>
</note>
</nodetype>
<nodetype>
<keynode>iangore</keynode>
<note>
<source>source2</source>
<name>Ian Gore</name>
</note>
</nodetype>
</root>
安纳洪
资料来源2
安娜·琼斯
伊恩戈尔
资料来源2
伊恩·戈尔
out.xml:
<?xml version="1.0" encoding="UTF-16"?><root>
<info>
<id>147</id>
</info>
<nodetype>
<keynode>annajon</keynode><note>
<source>source2</source>
<name>Anna Jones</name>
</note>
<note>
<source>source1</source>
<name>Anna Jones</name>
</note>
</nodetype>
<nodetype>
<keynode>brucejon</keynode>
<note>
<source>source1</source>
<name>Bruce Jones</name>
</note>
</nodetype>
</root>
147
安纳洪
资料来源2
安娜·琼斯
资料来源1
安娜·琼斯
布鲁塞戎
资料来源1
布鲁斯·琼斯
Chernyshow:您仍然需要迭代uniques类型。感谢Max的建议。我曾经考虑过剪切和粘贴这两个文件,然后进行排序/合并,但也无法理解:我对xsl非常陌生,但确实喜欢它!对不起,我不能发布任何一个答案,因为我没有atm机的声誉。我知道在匹配模板上同时使用name和match,但没有意识到利用这一事实的真实模式。非常感谢你的回答,非常感谢你的回答。非常感谢,这非常有效,就像在测试系统上一样。现在我需要尝试将它应用到我的实际系统中,这是一个更复杂的问题,因为我简化了它。不过,我现在有一些具体的工作要做,可以从文档中了解到功能等在做什么。有一件事我想澄清一下,因为我还没有找到它(毫无疑问,它是基本的,因为我已经看到它被大量使用!),但是“@”字符在做什么,比如“node()|@*”@debs:You's wellcome。关于你的问题:@*
是属性::*
的缩写,意思是任何属性。在对代码进行了更多的研究之后,我开始意识到我不知道[match=“node()|@*”]语句在做什么。我以为它是在测试名为“node”的节点,但怀疑它是某种保留字,好像我将实际的节点名称更改为(比如)tnode,xsl不会更改,但如果用tnode替换节点,xsl就会中断。我可以用一本基本的入门书来解释这一切,因此如果任何人有任何可以推荐的链接(或书籍),我将不胜感激。这本书非常清楚地解释了身份等的一些基本知识。对我来说:当你知道如何做时,参数传递很容易:[msxsl.exe x2.xml test.xsl-o out.xml pSource2=“x1.xml”]在xsl文件中用x1.xml替换x2.xml。如果未设置任何参数,“select”语句将设置默认值。
<root>
<nodetype>
<keynode>annajon</keynode>
<note>
<source>source2</source>
<name>Anna Jones</name>
</note>
</nodetype>
<nodetype>
<keynode>iangore</keynode>
<note>
<source>source2</source>
<name>Ian Gore</name>
</note>
</nodetype>
</root>
<?xml version="1.0" encoding="UTF-16"?><root>
<info>
<id>147</id>
</info>
<nodetype>
<keynode>annajon</keynode><note>
<source>source2</source>
<name>Anna Jones</name>
</note>
<note>
<source>source1</source>
<name>Anna Jones</name>
</note>
</nodetype>
<nodetype>
<keynode>brucejon</keynode>
<note>
<source>source1</source>
<name>Bruce Jones</name>
</note>
</nodetype>
</root>