user1933888
user1933888

Reputation: 3017

Merge 2 contiguous elements into 1 using xslt

I am new to xslt and am trying different options since few days. Am kind of out of ideas stuck with below scenario (more because of my lack of knowledge on xslt)

Input xml is something like:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<MAIN>
    <ProcessResponse>
        <ORDERNO>workorder123</ORDERNO>
        <NAME>BD-OC 102</NAME>
        <FID>124</FID>
        <FNO>57</FNO>       
        <AID>126</AID>
        <BID>125</BID>

    </ProcessResponse>
    <ProcessResponse>
        <ORDERNO>workorder123</ORDERNO>
        <NAME>BD-OC 102</NAME>
        <FID>125</FID>
        <FNO>58</FNO>
        <AID>127</AID>
        <BID>128</BID>

    </ProcessResponse>
    <ProcessResponse>
        <ORDERNO>workorder124</ORDERNO>
        <NAME>BD-OC 102</NAME>
        <FID>130</FID>
        <FNO>59</FNO>       
        <AID>132</AID>
        <BID>131</BID>

    </ProcessResponse>
    <ProcessResponse>
        <ORDERNO>workorder124</ORDERNO>
        <NAME>BD-OC 102</NAME>
        <FID>132</FID>
        <FNO>60</FNO>
        <AID>133</AID>
        <BID>134</BID>

    </ProcessResponse>

</MAIN>

And the output I am expecting is something like (Basically I want every 2 consecutive elements to be merged into 1, merging the part that is not common). In procedural lang it should e simple but I tried recursive in xslt but did not get desired result.

Output after transformation:

<Response>
    <Process>
        <ORDERNO>workorder123</ORDERNO>
        <NAME>BD-OC 102</NAME>

        <F1>
            <FID>124</FID>
            <FNO>57</FNO>       
            <AID>126</AID>
            <BID>125</BID>
        </F1>

        <F2>
            <FID>125</FID>
            <FNO>58</FNO>
            <AID>127</AID>
            <BID>128</BID>
        </F2>

    </Process>

    <Process>
        <ORDERNO>workorder124</ORDERNO>
        <NAME>BD-OC 102</NAME>
        <F1>
            <FID>130</FID>
            <FNO>59</FNO>       
            <AID>132</AID>
            <BID>131</BID>
        </F1>
        <F2>
            <FID>132</FID>
            <FNO>60</FNO>
            <AID>133</AID>
            <BID>134</BID>
        </F2>

    </Process>


</Response>

Note: The actual files are much more complex than this but the basic Idea is the same, merge every 2 consecutive blocks into one (the common part).

Any help/Direction/Pointers appreciated.

Upvotes: 0

Views: 401

Answers (2)

hr_117
hr_117

Reputation: 9627

To "merge the 2 consecutive rows" try this:

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

    <xsl:key name="kOrderno" match="ProcessResponse" use="ORDERNO" />
    <xsl:template match="@* | node()">
        <xsl:copy>
            <xsl:apply-templates select="@* | node()" >
                <xsl:with-param name="ch" select="h1" />
            </xsl:apply-templates>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="ProcessResponse/ORDERNO"/>
    <xsl:template match="ProcessResponse/NAME"/>
    <xsl:template match="ProcessResponse/text()"/>

    <xsl:template match="/*">
        <Response>
            <xsl:for-each select="ProcessResponse">
                <xsl:if test="position() mod 2 = 1">
                <Process>
                    <xsl:copy-of  select="ORDERNO"/>
                    <xsl:copy-of  select="NAME"/>
                    <xsl:variable name="on" select="ORDERNO" />
                    <xsl:element name="F1">
                        <xsl:apply-templates />
                    </xsl:element>
                    <xsl:element name="F2">
                        <xsl:apply-templates select="following-sibling::ProcessResponse[1]/*" />
                    </xsl:element>
                </Process>
                </xsl:if>
            </xsl:for-each>
        </Response>
    </xsl:template>
</xsl:stylesheet>

Upvotes: 0

hr_117
hr_117

Reputation: 9627

Try this key based solution Using Keys to Group: The Muenchian Method:

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

    <xsl:key name="kOrderno" match="ProcessResponse" use="ORDERNO" />
    <xsl:template match="@* | node()">
        <xsl:copy>
            <xsl:apply-templates select="@* | node()" >
                <xsl:with-param name="ch" select="h1" />
            </xsl:apply-templates>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="ProcessResponse/ORDERNO"/>
    <xsl:template match="ProcessResponse/NAME"/>

    <xsl:template match="/*">
        <Response>
            <xsl:for-each select="ProcessResponse[count(. | key('kOrderno', ORDERNO)[1] ) =1] ">
                <Process>
                    <xsl:copy-of  select="ORDERNO"/>
                    <xsl:copy-of  select="NAME"/>
                    <xsl:variable name="on" select="ORDERNO" />
                    <xsl:for-each select=" key('kOrderno', $on)" >
                        <xsl:element name="F{position()}">
                            <xsl:apply-templates ></xsl:apply-templates>
                        </xsl:element>
                    </xsl:for-each>
                </Process>
            </xsl:for-each>
        </Response>
    </xsl:template>
</xsl:stylesheet>

Which will generate the following output:

<?xml version="1.0"?>
<Response>
  <Process>
    <ORDERNO>workorder123</ORDERNO>
    <NAME>BD-OC 102</NAME>
    <F1>


                <FID>124</FID>
                <FNO>57</FNO>
                <AID>126</AID>
                <BID>125</BID>

        </F1>
    <F2>


                <FID>125</FID>
                <FNO>58</FNO>
                <AID>127</AID>
                <BID>128</BID>

        </F2>
  </Process>
  <Process>
    <ORDERNO>workorder124</ORDERNO>
    <NAME>BD-OC 102</NAME>
    <F1>


                <FID>130</FID>
                <FNO>59</FNO>
                <AID>132</AID>
                <BID>131</BID>

        </F1>
    <F2>


                <FID>132</FID>
                <FNO>60</FNO>
                <AID>133</AID>
                <BID>134</BID>
        </F2>
  </Process>
</Response>

Upvotes: 1

Related Questions