2011-08-06 103 views
0

我需要将我的XML转换为另一个数据结构。 我收到的XML象下面这样:使用XSLT合并XML节点

<results> 
    <resultset> 
    <result> 
     <name>BMW Cars</name> 
     <code>BMW Pkw</code> 
     <model.model>730d Saloon</model.model> 
     <model.name>KM21</model.name> 
    </result> 
    <result> 
     <name>BMW Cars</name> 
     <code>BMW Pkw</code> 
     <model.model>120i 3 doors</model.model> 
     <model.name>UA51</model.name> 
    </result> 
    <result> 
     <name>BMW Cars</name> 
     <code>BMW Pkw</code> 
     <model.model>Z4 sDrive23i</model.model> 
     <model.name>LM31</model.name> 
    </result> 
    <result> 
     <name>Audi</name> 
     <code>AUDI</code> 
     <model.model>A4 SAL.3.0 Q SPT TIP 5SPD</model.model> 
     <model.name>8E2SFZ04</model.name> 
    </result> 
    <result> 
     <name>Audi</name> 
     <code>AUDI</code> 
     <model.model>A6 SAL. 2.5TDI SPORT MAN.6SP.</model.model> 
     <model.name>4B2BBC04</model.name> 
    </result> 
    <result> 
     <name>AUdi</name> 
     <code>AUDI</code> 
     <model.model>A8 4.2 QUATTRO 6-SPD TIP</model.model> 
     <model.name>4E201L04</model.name> 
    </result> 
    </resultset> 
</results> 

,我需要它是这样的:

<results> 
    <resultset> 
    <result> 
     <name>BMW Cars</name> 
     <code>BMW Pkw</code> 
     <model.model>730d Saloon</model.model> 
     <model.name>KM21</model.name> 
     <model.model>120i 3 doors</model.model> 
     <model.name>UA51</model.name> 
     <model.model>Z4 sDrive23i</model.model> 
     <model.name>LM31</model.name> 
    </result> 
    <result> 
     <name>Audi</name> 
     <code>AUDI</code> 
     <model.model>A4 SAL.3.0 Q SPT TIP 5SPD</model.model> 
     <model.name>8E2SFZ04</model.name> 
     <model.model>A6 SAL. 2.5TDI SPORT MAN.6SP.</model.model> 
     <model.name>4B2BBC04</model.name> 
     <model.model>A8 4.2 QUATTRO 6-SPD TIP</model.model> 
     <model.name>4E201L04</model.name> 
    </result> 
    </resultset> 
</results> 

我花了很多时间来解决这个问题,但至今没有运气。 有谁知道如何解决这个问题?

+0

您使用的是XSLT 1.0还是2.0? –

回答

1
<?xml version="1.0" encoding="utf-8"?> 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output method="xml" version="1.0" encoding="utf-8" indent="yes" /> 

<xsl:key name="groupName" match="//results/resultset/result" use="concat(name, code)" /> 

<xsl:template match="/"> 

    <results> 
    <resultset> 
    <xsl:for-each select="//results/resultset/result[generate-id() = generate-id(key('groupName', concat(name, code)) [1]) ]" > 


     <xsl:call-template name="group"> 
     <xsl:with-param name="k1" select="name" /> 
     <xsl:with-param name="k2" select="code" /> 
     </xsl:call-template> 

    </xsl:for-each> 

    </resultset> 
    </results> 
</xsl:template> 

<xsl:template name="group"> 
<xsl:param name="k1" /> 
<xsl:param name="k2" /> 

    <result> 
     <xsl:copy-of select="name" />  
     <xsl:copy-of select="code" />  

     <xsl:for-each select="//results/resultset/result[name = $k1][code = $k2]"> 

     <xsl:copy-of select="model.model" />  
     <xsl:copy-of select="model.name" />  

     </xsl:for-each> 
    </result> 

</xsl:template> 
</xsl:stylesheet> 
+0

非常感谢。 你的代码工作正常。 – Grigory

0

我知道这是一个老问题,但我想提供一个答案,不同的是公认的答案,更短,更简单的,利用了通用的面向推设计模式,不需要与模板参数,并且不会对树进行多次完整遍历。

当这个XSLT:

<?xml version="1.0" encoding="UTF-8"?> 
<results> 
    <resultset> 
    <result> 
     <name>BMW Cars</name> 
     <code>BMW Pkw</code> 
     <model.model>730d Saloon</model.model> 
     <model.name>KM21</model.name> 
    </result> 
    <result> 
     <name>BMW Cars</name> 
     <code>BMW Pkw</code> 
     <model.model>120i 3 doors</model.model> 
     <model.name>UA51</model.name> 
    </result> 
    <result> 
     <name>BMW Cars</name> 
     <code>BMW Pkw</code> 
     <model.model>Z4 sDrive23i</model.model> 
     <model.name>LM31</model.name> 
    </result> 
    <result> 
     <name>Audi</name> 
     <code>AUDI</code> 
     <model.model>A4 SAL.3.0 Q SPT TIP 5SPD</model.model> 
     <model.name>8E2SFZ04</model.name> 
    </result> 
    <result> 
     <name>Audi</name> 
     <code>AUDI</code> 
     <model.model>A6 SAL. 2.5TDI SPORT MAN.6SP.</model.model> 
     <model.name>4B2BBC04</model.name> 
    </result> 
    <result> 
     <name>Audi</name> 
     <code>AUDI</code> 
     <model.model>A8 4.2 QUATTRO 6-SPD TIP</model.model> 
     <model.name>4E201L04</model.name> 
    </result> 
    </resultset> 
</results> 

......想要的结果产生:

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> 
    <xsl:output omit-xml-declaration="no" indent="yes"/> 
    <xsl:strip-space elements="*"/> 

    <xsl:key name="kResultByNameCode" match="result" use="concat(name, '+', code)"/> 

    <xsl:template match="node()|@*"> 
    <xsl:copy> 
     <xsl:apply-templates select="node()|@*"/> 
    </xsl:copy> 
    </xsl:template> 

    <xsl:template match="result[generate-id() = generate-id(key('kResultByNameCode', concat(name, '+', code))[1])]"> 
    <xsl:copy> 
     <xsl:apply-templates select="name | code"/> 
     <xsl:apply-templates select="key('kResultByNameCode', concat(name, '+', code))/*[starts-with(name(), 'model')]"/> 
    </xsl:copy> 
    </xsl:template> 

    <xsl:template match="result"/> 

</xsl:stylesheet> 

......是对所提供的XML运行

<results> <resultset> <result> <name>BMW Cars</name> <code>BMW Pkw</code> <model.model>730d Saloon</model.model> <model.name>KM21</model.name> <model.model>120i 3 doors</model.model> <model.name>UA51</model.name> <model.model>Z4 sDrive23i</model.model> <model.name>LM31</model.name> </result> <result> <name>Audi</name> <code>AUDI</code> <model.model>A4 SAL.3.0 Q SPT TIP 5SPD</model.model> <model.name>8E2SFZ04</model.name> <model.model>A6 SAL. 2.5TDI SPORT MAN.6SP.</model.model> <model.name>4B2BBC04</model.name> <model.model>A8 4.2 QUATTRO 6-SPD TIP</model.model> <model.name>4E201L04</model.name> </result> </resultset> </results> 

再一次,@ Mike的答案并没有什么内在的错误,但这更加可维护,并且更充分地利用了XSLT解析器的本地功能。