tags:

views:

1076

answers:

2

Is it possible to merge elements using XSLT.

If I have the following XML

<data>
<item column="left" value="1" />
<item column="left" value="2" />
<item column="right" value="3" />
<item column="left" value="4" />
<item column="right" value="5" />
<item column="right" value="6" />
<item column="right" value="7" />
<item column="left" value="8" />
<item column="right" value="9" />
<item column="right" value="10" />
</data>

I want the following output:

<data>
<item left="1" right="3 />
<item left="2" right="5" />
<item left="4" right="6" />
<item left="8" right="7" />
<item left="" right="9" />
<item left="" right="10" />
</data>

But I have absolutely no idea if this is possible using XSLT

A: 

You would use the element and attribute tags...

<xsl:element name="item">
    <xsl:attribute name="left"><xsl:value-of select="$theLeft"/></xsl:attribute>
    <xsl:attribute name="right"><xsl:value-of select="$theRight"/></xsl:attribute>
</xsl:element>

...as for the algorithm to determine what $theLeft and $theRight should be, I leave that to you.

dacracot
+3  A: 

This transformation:

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

    <xsl:template match="data">
      <xsl:variable name="vNumLeft" select="count(item[@column='left'])"/>

      <data>
        <xsl:apply-templates select="*[@column='left']"/>
        <xsl:apply-templates select=
                "*[@column='right'][position() > $vNumLeft]"/>
      </data>
    </xsl:template>

    <xsl:template match="item[@column='left']">
      <xsl:variable name="vPos" select="position()"/>

      <item left="{@value}" 
                    right="{../item[@column='right'][$vPos]/@value}"    />
    </xsl:template>

    <xsl:template match="item[@column='right']">
      <item left="" right="{@value}" />
    </xsl:template>
</xsl:stylesheet>

when applied on the provided XML document:

<data>
    <item column="left" value="1" />
    <item column="left" value="2" />
    <item column="right" value="3" />
    <item column="left" value="4" />
    <item column="right" value="5" />
    <item column="right" value="6" />
    <item column="right" value="7" />
    <item column="left" value="8" />
    <item column="right" value="9" />
    <item column="right" value="10" />
</data>

produces the wanted result:

<data>
   <item left="1" right="3"/>
   <item left="2" right="5"/>
   <item left="4" right="6"/>
   <item left="8" right="7"/>
   <item left="" right="9"/>
   <item left="" right="10"/>
</data>
Dimitre Novatchev