2012-09-14 89 views
1

请我想知道如何我可以将两个xml文件合并成一个xml文件使用xslt。 我有这两个xml文件,我想要合并到一个xml文件中,如预期输出中所示。我想包括从第二个文件到文件1中相同编号的相应块的每个节点Hn我怎样才能合并这两个xml文件使用xslt

file1的:

<Test> 
    <R1> 
    <Th1> 
     here are some instruction. 
    </Th1> 
    </R1> 

    <R2> 
    <Th2> 
     here are some instruction. 
    </Th2> 
    </R2> 

    <R3> 
    <Th3> 
     here are some instruction. 
    </Th3> 
    </R3> 
</Test> 

文件2:

<test1> 
    <H1> 
    here are some instruction. 
    </H1> 

    <H2> 
    here are some instruction. 
    </H2> 

    <H3> 
    here are some instruction. 
    </H3> 
</test1>  

,这里是所期望的输出:

<test2> 
    <R1> 
    <H1> 
     here are some instruction. 
    </H1> 
    <Th1> 
     here are some instruction. 
    </Th1> 
    </R1> 

    <R2> 
    <H2> 
     here are some instruction. 
    </H2> 
    <Th2> 
     here are some instruction. 
    </Th2> 
    </R2> 

    <R3> 
    <H3> 
     here are some instruction. 
    </H3> 
    <Th3> 
     here are some instruction. 
    </Th3> 
    </R3> 

</test2> 

感谢您的帮助。

+0

你好永邦,你必须使用的文件( )功能。尝试设置一个XSLT,看看你有多远。谢谢你,彼得 – Peter

+0

你好,彼得,我不熟悉xslt。我刚开始使用xslt,并且我不知道更多关于它的事情。但是我会对谷歌做关于这个功能的一些研究。感谢已经给了一个技巧。 –

回答

2

I.这XSLT 1.0转化

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output omit-xml-declaration="yes"/> 

<xsl:variable name="vDigits" select="''"/> 
<xsl:variable name="vDoc2" select="document('file:///c:/temp/delete/file2.xml')"/> 

<xsl:template match="/*"> 
    <test2><xsl:apply-templates/></test2> 
</xsl:template> 

<xsl:template match="/*/*"> 
    <xsl:copy> 
    <xsl:text>&#xA;</xsl:text> 
    <xsl:copy-of select= 
    "$vDoc2/*/* 
     [translate(name(),translate(name(),$vDigits,''),'') 
     = 
     translate(name(current()),translate(name(current()),$vDigits,''),'') 
     ]"/> 
    <xsl:copy-of select="node()"/> 
    </xsl:copy> 
</xsl:template> 
</xsl:stylesheet> 

当施加在第一个XML文档(file1.xml):

<Test> 
    <R1> 
    <Th1> 
     here are some instruction. 
    </Th1> 
    </R1> 

    <R2> 
    <Th2> 
     here are some instruction. 
    </Th2> 
    </R2> 

    <R3> 
    <Th3> 
     here are some instruction. 
    </Th3> 
    </R3> 
</Test> 

和具有第二XML文档驻留at c:\temp\delete\file2.xml

<test1> 
    <H1> 
    here are some instruction. 
    </H1> 

    <H2> 
    here are some instruction. 
    </H2> 

    <H3> 
    here are some instruction. 
    </H3> 
</test1> 

产生想要的,正确的结果:

<test2> 
    <R1> 
<H1> 
    here are some instruction. 
    </H1> 
    <Th1> 
     here are some instruction. 
    </Th1> 
    </R1> 

    <R2> 
<H2> 
    here are some instruction. 
    </H2> 
    <Th2> 
     here are some instruction. 
    </Th2> 
    </R2> 

    <R3> 
<H3> 
    here are some instruction. 
    </H3> 
    <Th3> 
     here are some instruction. 
    </Th3> 
    </R3> 
</test2> 

说明

正确使用的 “双转换” 方法首先由迈克尔·凯全世界展示。


二, XSLT 2.0解决方案

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output omit-xml-declaration="yes"/> 

<xsl:variable name="vDigits" select="''"/> 
<xsl:variable name="vDoc2" select="document('file:///c:/temp/delete/file2.xml')"/> 

<xsl:template match="/*"> 
    <test2><xsl:apply-templates/></test2> 
</xsl:template> 

<xsl:template match="/*/*"> 
    <xsl:if test="not(matches(name(), '^.+\d+$'))"> 
    <xsl:message terminate="yes"> 
    Element Name doesn't end with number: <xsl:sequence select="name()"/> 
    </xsl:message> 
    </xsl:if> 
    <xsl:copy> 
    <xsl:text>&#xA;</xsl:text> 
    <xsl:copy-of select= 
    "$vDoc2/*/* 
     [replace(name(),'^.+(\d+)$', '$1') 
     = 
     replace(name(current()),'^.+(\d+)$', '$1') 
     ]"/> 
    <xsl:copy-of select="node()"/> 
    </xsl:copy> 
</xsl:template> 
</xsl:stylesheet> 

说明

正确使用标准的XPath 2.0功能matches()replace()

+0

你好Dimitre,感谢这个解决方案。它走得很好。但是我想知道变量名称vDigits的用途和用法。是否有可能自动获取file2.xml的路径,以便我不需要总是将此文件存储在c:\ temp \ delete \ ...中?谢谢 –

+0

@FrankyN。,是的,您可以为此指定一个全局/外部(xsl:stylesheet的子项)'xsl:param'。这样的参数可以从XSLT转换的调用者的外部进行设置 - 因为这是依赖于实现的,所以您需要阅读您正在使用的特定XSLT处理器的文档。 –

+0

@FrankyN的'$ vDigits'的作用 - 它用来查找元素名称中使用的所有数字。首先我们找到所有非数字(在'translate()'的内部),然后我们去除名字中的所有非数字 - 在外部翻译中。剩下的只是该名称包含的所有数字。 –