2

I have an xml file as below propNode.xml

<NODES>
  <NODE>
<NODELINE CLASS="Item" TYPE="Item" >
  <ATTR_NODES>
    <ATTR_NODE NAME="myName" />
    <ATTR_NODE NAME="myDesc />
  </ATTR_NODES>
</NODELINE>
<NODELINE CLASS="Item1" TYPE="Item1" >
  <ATTR_NODES>
    <ATTR_NODE NAME="myName1" />
    <ATTR_NODE NAME="myDesc1" />
  </ATTR_NODES>
</NODELINE>
<NODELINE CLASS="Item2" TYPE="Item2" >
  <ATTR_NODES>
    <ATTR_NODE NAME="myName2" />
    <ATTR_NODE NAME="myDesc2" />
  </ATTR_NODES>
</NODELINE>
</NODE>
</NODES>

I want to read this xml and using it, I need to merge the following two xml files source.xml

<NODES>
  <NODE>
<NODELINE CLASS="Item" TYPE="Item" >
  <ATTR_NODES>
    <ATTR_NODE NAME="myName" VALUE="myNameValue" />
    <ATTR_NODE NAME="myDesc" VALUE="test-myDescValue" />
<ATTR_NODE NAME="myId" VALUE="test-myIdValue" />
  </ATTR_NODES>
</NODELINE>
<NODELINE CLASS="Item1" TYPE="Item1" >
  <ATTR_NODES>
    <ATTR_NODE NAME="myName1" VALUE="myNameValue1" />
    <ATTR_NODE NAME="myDesc1" VALUE="myDescValue1"/>
<ATTR_NODE NAME="myId1" VALUE="myIdValue1" />
  </ATTR_NODES>
</NODELINE>
<NODELINE CLASS="Item2" TYPE="Item2" >
  <ATTR_NODES>
    <ATTR_NODE NAME="myName2" VALUE="test-myNameValue2" />
    <ATTR_NODE NAME="myDesc2" VALUE="myDescValue2"/>
<ATTR_NODE NAME="myId2" VALUE="test-myIdValue2" />
  </ATTR_NODES>
</NODELINE>
  </NODE>
</NODES>

And target.xml

<NODES>
  <NODE>
<NODELINE CLASS="Item" TYPE="Item" >
  <ATTR_NODES>
    <ATTR_NODE NAME="myName" VALUE="myNameValue" />
    <ATTR_NODE NAME="myDesc" VALUE="myDescValue" />
<ATTR_NODE NAME="myId" VALUE="myIdValue" />
  </ATTR_NODES>
</NODELINE>
<NODELINE CLASS="Item1" TYPE="Item1" >
  <ATTR_NODES>
    <ATTR_NODE NAME="myName1" VALUE="myNameValue1" />
    <ATTR_NODE NAME="myDesc1" VALUE="myDescValue1"/>
<ATTR_NODE NAME="myId1" VALUE="myIdValue1" />
  </ATTR_NODES>
</NODELINE>
<NODELINE CLASS="Item2" TYPE="Item2" >
  <ATTR_NODES>
    <ATTR_NODE NAME="myName2" VALUE="myNameValue2" />
    <ATTR_NODE NAME="myDesc2" VALUE="myDescValue2"/>
<ATTR_NODE NAME="myId2" VALUE="myIdValue2" />
  </ATTR_NODES>
</NODELINE>
  </NODE>
</NODES>

The condition is reading the propNode.xml, if the value of @NAME matches in the source.xml and target.xml, then the values of @VALUE in the source.xml and target.xml needs to be compared and an output xml should be created as below:

desiredOutput.xml

<NODES>
  <NODE>
<NODELINE CLASS="Item" TYPE="Item" >
  <ATTR_NODES>
    <ATTR_NODE NAME="myName" SRCVALUE="myNameValue" TGTVALUE="myNameValue" ISDIFF="false" />
    <ATTR_NODE NAME="myDesc" SRCVALUE="test-myDescValue" TGTVALUE="myDescValue" ISDIFF="true" />
  </ATTR_NODES>
</NODELINE>
<NODELINE CLASS="Item1" TYPE="Item1" >
  <ATTR_NODES>
    <ATTR_NODE NAME="myName1" SRCVALUE="myNameValue1" TGTVALUE="myNameValue1" ISDIFF="false" />
    <ATTR_NODE NAME="myDesc1" SRCVALUE="myDescValue1" TGTVALUE="myDescValue1" ISDIFF="false" />
  </ATTR_NODES>
</NODELINE>
<NODELINE CLASS="Item2" TYPE="Item2" >
  <ATTR_NODES>
    <ATTR_NODE NAME="myName2" SRCVALUE="test-myNameValue2" TGTVALUE="myNameValue2" ISDIFF="true" /> />
    <ATTR_NODE NAME="myDesc2" SRCVALUE="myDescValue2" TGTVALUE="myDescValue2" ISDIFF="false" />
  </ATTR_NODES>
</NODELINE>
  </NODE>
</NODES>

The desiredOutput.xml should contain both the values of @VALUE from the source and the target if the value of @NAME selected in the propNode.xml. If the values of @VALUE are different then @ISDIFF should have a value "true" or else "false".

Is this whole operation possible using xslt? Something like generating xsl using the propNode.xml and then applying it on the source.xml and the target.xml to generate the desired output? How would this xsl look like?

3
  • Can you confirm that propnode.xml should also have a <ATTR_NODE NAME="myDesc" /> element in the first ATTR_NODES, since this is present in both source, destination as well as desiredOutput? Commented Nov 27, 2012 at 12:40
  • @StuartLC yes, sorry my bad. I have edited it now. Thanks for pointing it out. Commented Nov 27, 2012 at 12:53
  • Updated my xslt - must be != of course ... Commented Nov 27, 2012 at 13:06

1 Answer 1

1

Assuming that only the nodes (ATTR_NODE) present in propNode.xml need to be tested, the following XSLT should do the job:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
     xmlns:my="some.uri" version="1.0">

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

    <xsl:template match="ATTR_NODE">
        <xsl:variable name="NodeLine" select="../../@CLASS" />
        <xsl:variable name="AttrName" select="@NAME" />
        <xsl:variable name="SrcValue" select="document('source.xml')//NODELINE[@CLASS=$NodeLine]//ATTR_NODE[@NAME=$AttrName]/@VALUE" />
        <xsl:variable name="TgtValue" select="document('target.xml')//NODELINE[@CLASS=$NodeLine]//ATTR_NODE[@NAME=$AttrName]/@VALUE" />
        <xsl:element name="ATTR_NODE">
            <xsl:attribute name="NAME">
                <xsl:value-of select="$AttrName"/>
            </xsl:attribute>
            <xsl:attribute name="SRCVALUE">
                <xsl:value-of select="$SrcValue" />
            </xsl:attribute>
            <xsl:attribute name="TGTVALUE">
                <xsl:value-of select="$TgtValue" />
            </xsl:attribute>
            <xsl:attribute name="ISDIFF">
                <xsl:value-of select="$SrcValue!=$TgtValue" />
            </xsl:attribute>
        </xsl:element>
    </xsl:template>
</xsl:stylesheet>

The identity template is used to traverse and copy propNode, with special processing for each ATTR_NODE checks VALUE in source and target, and then evaluated for equality. I've assumed that NODE_LINE/@CLASS is sufficient to establish the identity of the NODE_LINE - if it isn't, then you'll need to add additional checking e.g. @TYPE as well.

The xslt is run against propnode.xml, and source.xml and target.xml must be present in the same folder.

Output

<?xml version="1.0" encoding="utf-8"?>
<NODES>
    <NODE>
        <NODELINE CLASS="Item" TYPE="Item">
            <ATTR_NODES>
                <ATTR_NODE NAME="myName" SRCVALUE="myNameValue" TGTVALUE="myNameValue" ISDIFF="false" />
                <ATTR_NODE NAME="myDesc" SRCVALUE="test-myDescValue" TGTVALUE="myDescValue" ISDIFF="true" />"
            </ATTR_NODES>
        </NODELINE>
        <NODELINE CLASS="Item1" TYPE="Item1">
            <ATTR_NODES>
                <ATTR_NODE NAME="myName1" SRCVALUE="myNameValue1" TGTVALUE="myNameValue1" ISDIFF="false" />
                <ATTR_NODE NAME="myDesc1" SRCVALUE="myDescValue1" TGTVALUE="myDescValue1" ISDIFF="false" />
            </ATTR_NODES>
        </NODELINE>
        <NODELINE CLASS="Item2" TYPE="Item2">
            <ATTR_NODES>
                <ATTR_NODE NAME="myName2" SRCVALUE="test-myNameValue2" TGTVALUE="myNameValue2" ISDIFF="true" />
                <ATTR_NODE NAME="myDesc2" SRCVALUE="myDescValue2" TGTVALUE="myDescValue2" ISDIFF="false" />
            </ATTR_NODES>
        </NODELINE>
    </NODE>
</NODES>
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.