I know there are few xml/xslt merge related questions here however none seems to solve the problem I have.
What I am looking is an XSLT (as generic as possible - not tight with the structure of the input XML files) which can
Merge a.xml with b.xml and generate c.xml such a way that
- c.xml will contain the common nodes between a.xml and b.xml (with the node values taken from a.xml)
- in addition c.xml will contain the nodes(and values) which are present in b.xml and not in a.xml
For example: merging a.xml:
<root_node>
<settings>
<setting1>a1</setting1>
<setting2>a2</setting2>
<setting3>
<setting31>a3</setting31>
</setting3>
<setting4>a4</setting4>
</settings>
</root_node>
with b.xml:
<root_node>
<settings>
<setting1>b1</setting1>
<setting2>b2</setting2>
<setting3>
<setting31>b3</setting31>
</setting3>
<setting5 id="77">b5</setting5>
</settings>
</root_node>
will generate c.xml:
<root_node>
<settings>
<setting1>a1</setting1>
<setting2>a2</setting2>
<setting3>
<setting31>a3</setting31>
</setting3>
<setting5 id="77">b5</setting5>
</settings>
Additional Information
I will try to explain what I understand by a "common node". This might not be an accurate xml/xslt definition since I am not an expert in any.
a/root_node/settings/setting1 is a "common node" with b/root_node/settings/setting1 since the 2 nodes are reached using the same path. The same for setting2 and setting3.
The 2 "non-common nodes" are a/root_node/settings/setting4 which is found only in a.xml (it should not come in the output) and b/root_node/settings/setting5 which is found only in b.xml (it should come into the output).
By "generic solution" I don't mean something that will work whatever format the input XMLs will have. What I mean by that is that the xslt should not contain hard-code xpaths while you might add restrictions like "this will work only if the nodes in a.xml are unique" or whatever other restriction you might think it will be suitable.
the basic technique to operate on multiple files is through the document() function. The document function looks like this:
Once you have the two documents, you can use their contents like they are available in the same document.
The following XSLT 1.0 program does what you want.
Apply it to
b.xml
and pass in the path toa.xml
as a parameter.Here is how it works.
B
, as that contains the new nodes that you want to keep as well as the common elements betweenA
andB
.ancestor-or-self
axis.So in your sample
B
,<setting31>
would have a simple path ofroot_node/settings/setting3/setting31/
.calculatePath
.nodeValueByPath
is called that tries to retrieve the text value of the corresponding simple path from the other document.B
. This satisfies your second bullet point.As a result, the new document matches
B
's structure and contains:B
that have no corresponding node inA
.A
when a corresponding node inB
exists.Here's the XSLT: