Let's say I have two XML files which has the same structure. I need to create new XML file with same structure which contain the selected nodes from initial two XML files.
I will try to explain again with bellow example.
input1.xml
:
<parent>
<item id="100">
...
</item>
<item id="101">
...
</item>
<item id="102">
...
</item>
<item id="103">
...
</item>
</parent>
input2.xml
:
<parent>
<item id="200">
...
</item>
<item id="201">
...
</item>
<item id="202">
...
</item>
<item id="203">
...
</item>
</parent>
Now I need select the nodes which have id 100,103
from input1.xml
and 202,203
from input2.xml
. Also it should be in the order of 203,100,103,202
and final result would be look like bellow.
result.xml
:
<parent>
<item id="203">
...
</item>
<item id="100">
...
</item>
<item id="103">
...
</item>
<item id="202">
...
</item>
</parent>
It is not necessary to create new file, if I can edit the input2.xml
in the way it looks like result.xml
, that would be the ideal solution.
What I have done so far :
My approach is first delete the nodes from the input2.xml
and then add the nodes to that from input1.xml
.
I have following function to delete nodes from input2.xml
file.
eg: call delete_record(200,'input2.xml','result.xml')
can delete the node 200 and I can repeat it in the similar manner.
function delete_record($id, $input, $output){
$xml = new DOMDocument();
$xml->load($input);
$deals = $xml->getElementsByTagName('item');
foreach ($deals as $deal) {
$deal_id = $deal->getElementsByTagName('id')->item(0)->nodeValue;
if ($deal_id == $id) {
$id_matched = true;
$deal->parentNode->removeChild($deal);
break;
}
}
if ($id_matched == true) {
if ($xml->save($output)) {
return true;
}
}
}
But still I am struggling to find a way how to add nodes to the same result.xml
file and how to make the order.
Any kind of help would be highly appreciated.
There is no need to mess with deletion, just do what you need to. Pick nodes by id from both files, and put it in order:
// merge all nodes by Id
function getNodesById($id, ...$xpaths) {
$result = [];
foreach($xpaths as $xpath) {
foreach($xpath->query("//item[@id='$id']") as $node) {
$result[] = $node;
}
}
return $result;
}
// load source documents
$xml1 = new DOMDocument();
$xml1->load(....);
$xpath1 = new DomXpath($xml1);
$xml2 = new DOMDocument();
$xml2->load(....);
$xpath2 = new DomXpath($xml2);
// create result document
$result = new DOMDocument();
$parent = $result->createElement("parent");
$result->appendChild($parent);
// populate result document with nodes:
foreach([203, 100, 103, 202] as $id) {
$nodesToInsert = getNodesById($id, xpath1, xpath2);
if (count($nodesToInsert) !== 1) {
// resolve conflicts, if any
throw new Exception("Id $id is not found or not unique.");
}
$parent->appendChild($result->importNode($nodesToInsert[0], true));
}
// or save it to a file
echo $result->saveXml();