Search code examples
xmlxsltxslt-1.0osb

Merge and update node values of two xmls using xslt


I am new bee in XSLT. But I belive below requirement can be achieved using XSLT :) Now I have a requirement where i need to merge 2 different xmls to one and there should be a check where the xslt should be capable of checking node name like if input1/nodeName matches to input2/nodeName then value need to be populated from input2.

For Example:

Input1 xml:

<Parent>
    <C1>123</C1>
    <C2>Incorrect data</C2>
    <C3>789</C3>
</Parent>

Input2 xml:

<NewParent>
  <C2>CorrectData</C2>
</NewParent>

Output: should be

<Parent>
    <C1>123</C1>
    <C2>CorrectData</C2>
    <C3>789</C3>
</Parent>

I tried below XSLT to merge both, but found no solution.

<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" indent="yes" />
    <xsl:param name="input1" select="input1.xml" />
    <xsl:param name="input2" select="input2.xml" />
    <xsl:template match="@* | node()">
        <xsl:copy>
            <xsl:apply-templates select="@* | node()" />
        </xsl:copy>
    </xsl:template>
    <xsl:template match="/">
        <xsl:copy>
            <xsl:for-each select="/*">
                <xsl:choose>
                    <xsl:when
                        test="$input1//node() = $input2//node()">
                        <xsl:value-of select="$input2/node()" />
                    </xsl:when>
                    <xsl:otherwise>
                        <xsl:apply-templates select="@* | node()" />
                    </xsl:otherwise>
                </xsl:choose>
            </xsl:for-each>
        </xsl:copy>
    </xsl:template>
</xsl:stylesheet>

and the stylesheet terminates with some node-set error.

Note : To get the result we shouln't specify any nodeName(like c1,c2) no where in the XSLT code. It should be generic.

Please let me know if any further information required. And also let me know if my question isn't clear.


Solution

  • Try This:

    <xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" indent="yes" />
    <xsl:variable name="input1" select="document('input1.xml')" />
    <xsl:variable name="input2" select="document('input2.xml')" />
    <xsl:template match="@* | node()">
        <xsl:copy>
            <xsl:apply-templates select="@* | node()" />
        </xsl:copy>
    </xsl:template>
    <xsl:template match="/">
        <xsl:copy>
            <xsl:for-each select="$input1/*">
                <xsl:copy>
                    <xsl:for-each select="*">
                        <xsl:choose>
                            <xsl:when test="name() = $input2//name()">
                                <xsl:copy-of select="$input2/*/node()" />
                            </xsl:when>
                            <xsl:otherwise>
                                <xsl:copy-of select="." />
                            </xsl:otherwise>
                        </xsl:choose>
                    </xsl:for-each>
                </xsl:copy>
            </xsl:for-each>
        </xsl:copy>
    </xsl:template>
    </xsl:stylesheet>
    

    Output:

    <Parent>
     <C1>123</C1>
     <C2>CorrectData</C2>
     <C3>789</C3>
    </Parent>