XSLT使用来自另一个兄弟的信息

时间:2011-12-27 16:35:12

标签: xslt merge descendant ancestor

我必须转换具有以下结构的XML文档

<NODEA d="8" m="1" xxxxx="WWWWWWWWWWWWWW"/> 
<NODEA d="16" m="1" xxxxx="somethingelse"/> 

<NODEB d="1" m="1" yyyyy="xx"/> 
<NODEB d="2" m="1" yyyyy="xx"/> 
<NODEB d="3" m="1" yyyyy="yy"/> 
<NODEB d="4" m="1" yyyyy="zz"/> 
<NODEB d="5" m="1" yyyyy="aa"/> 
<NODEB d="6" m="1" yyyyy="ss"/> 
<NODEB d="7" m="1" yyyyy="33"/> 
<NODEB d="8" m="1" yyyyy="AAAAAAAAAAAAA"/> 
<NODEB d="9" m="1" yyyyy="qq"/>   etc

在xslt中我尝试合并两个节点,当属性&#34; d&#34;是平等的

<NewNode>
   <d>8</d>
   <m>1</m>
   <xxxxx>WWWWWWWWWWWWWW</xxxxx>
   <yyyyy>AAAAAAAAAAAAA</yyyyy>
</NewNode>

这样做

<xsl:template match="NODEB">
<xsl:element name="NewNode"> 
    <xsl:apply-templates select="@d" />
    <xsl:apply-templates select="@m" />
    <xsl:apply-templates select="@yyyyy" />

    <xsl:element name="xxxxx" >
        <xsl:for-each select="//NODEA">
            <xsl:if test=".@d eq @d">
                <xsl:value-of select=".@xxxxx" />
            </xsl:if>
        </xsl:for-each>          
    </xsl:element>
</xsl:element>

所以if语句显然不起作用,但我怎么能这样做呢?

2 个答案:

答案 0 :(得分:2)

此转化

<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:key name="kElemByD" match="*" use="@d"/>

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

 <xsl:template priority="1" match=
  "*[generate-id()
    =
     generate-id(key('kElemByD', @d)[2])
    ]
  ">
  <newNode>
   <xsl:copy-of select="key('kElemByD', @d)/@*"/>
  </newNode>
 </xsl:template>

 <xsl:template match=
  "*[count(key('kElemByD', @d)) > 1]"/>
</xsl:stylesheet>

应用于提供的XML (包装到顶部元素中以成为格式良好的XML文档):

<t>
    <NODEA d="8" m="1" xxxxx="WWWWWWWWWWWWWW"/>
    <NODEA d="16" m="1" xxxxx="somethingelse"/>

    <NODEB d="1" m="1" yyyyy="xx"/>
    <NODEB d="2" m="1" yyyyy="xx"/>
    <NODEB d="3" m="1" yyyyy="yy"/>
    <NODEB d="4" m="1" yyyyy="zz"/>
    <NODEB d="5" m="1" yyyyy="aa"/>
    <NODEB d="6" m="1" yyyyy="ss"/>
    <NODEB d="7" m="1" yyyyy="33"/>
    <NODEB d="8" m="1" yyyyy="AAAAAAAAAAAAA"/>
    <NODEB d="9" m="1" yyyyy="qq"/>
</t>

生成想要的正确结果

<t>
   <NODEA d="16" m="1" xxxxx="somethingelse"/>
   <NODEB d="1" m="1" yyyyy="xx"/>
   <NODEB d="2" m="1" yyyyy="xx"/>
   <NODEB d="3" m="1" yyyyy="yy"/>
   <NODEB d="4" m="1" yyyyy="zz"/>
   <NODEB d="5" m="1" yyyyy="aa"/>
   <NODEB d="6" m="1" yyyyy="ss"/>
   <NODEB d="7" m="1" yyyyy="33"/>
   <newNode d="8" m="1" xxxxx="WWWWWWWWWWWWWW" yyyyy="AAAAAAAAAAAAA"/>
   <NODEB d="9" m="1" yyyyy="qq"/>
</t>

解释 Muenchian method 进行分组。

答案 1 :(得分:0)

这是另一种方法,你可以使用两个for-each,比@Dimitre更不优雅:)

<强> EDITED

    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
        version="1.0">
        <xsl:template match="/">
            <xsl:for-each select="//NODEA">
                <xsl:variable name="nodea" select="."/>
                <xsl:variable name="d" select="./@d"/>

                <!-- The d should match only then create New Node -->
                <xsl:for-each select="//NODEB[@d = $d]">
                    <xsl:variable name="nodeb" select="." />
                    <NewNode>
                        <d><xsl:value-of select="$d"/></d>
                        <m><xsl:value-of select="$nodea/@m"/></m>
                        <xxxxx><xsl:value-of select="$nodea/@xxxxx"/></xxxxx>
                        <yyyyy><xsl:value-of select="$nodeb/@yyyyy"/></yyyyy>
                    </NewNode>
                    </xsl:for-each>
                </xsl:for-each>
        </xsl:template>
    </xsl:stylesheet>

产生必要的输出

        <NewNode>
            <d>8</d>
            <m>1</m>
            <xxxxx>WWWWWWWWWWWWWW</xxxxx>
            <yyyyy>AAAAAAAAAAAAA</yyyyy>
        </NewNode>