Reputation: 707
I have a large XML file which takes forever to load on external FTP editor so I would like to split it into several files.
I use simplexml_load_file
but couldn't make it load multiple files into same array.
XML files has the same structure, here's a sample of each file:
a.xml:
<?xml version="1.0"?>
<queries>
<query>
<admin_user_type>user</admin_user_type>
<show_in_menu>True</show_in_menu>
<title>Dashboard</title>
<vertical_report>True</vertical_report>
</query>
</queries>
b.xml:
<?xml version="1.0"?>
<queries>
<query>
<admin_user_type>admin</admin_user_type>
<show_in_menu>false</show_in_menu>
<title>Profile Element</title>
<input_name>Id</input_name>
<input_type>hidden</input_type>
</query>
</queries>
There are about 200 queries in 7,000 lines between the two files.
The code fails on the foreach below:
$xml = read_xml_files();
foreach($xml->children() as $xml) {
...
...
}
Below is what I've taken from Nigel's suggestion:
function read_xml_files() {
$target = new DOMDocument();
$target->loadXML('<base />');
mergeFile($target, XML_FILES_FOLDER."a.xml");
mergeFile($target, XML_FILES_FOLDER."b.xml");
$xml = simplexml_import_dom($target);
return $xml->asXML();
}
function mergeFile ( DOMDocument $target, $fileName ) {
$source = new DOMDocument();
$source->load($fileName);
foreach ( $source->childNodes as $row ) {
$import = $target->importNode($row, true);
$target->documentElement->appendChild($import);
}
}
Thanks for any suggestion!
Upvotes: 3
Views: 815
Reputation: 57131
If you use DOMDocument to do the main merging part...
function mergeFile ( DOMDocument $target, $fileName ) {
$source = new DOMDocument();
$source->load($fileName);
foreach ( $source->childNodes as $row ) {
$import = $target->importNode($row, true);
$target->documentElement->appendChild($import);
}
}
$target = new DOMDocument();
$target->loadXML('<base />');
mergeFile($target, "file1.xml");
mergeFile($target, "file2.xml");
$xml = simplexml_import_dom($target);
echo $xml->asXML();
At the end $xml contains the merged files.
Note that this adds another level to the document (unless I know the type of contents it's difficult to do anything else). So in this case you will get something like...
file1.xml
<?xml version="1.0" encoding="UTF-8"?>
<A>A</A>
file2.xml
<?xml version="1.0" encoding="UTF-8"?>
<B>B</B>
Result will be
<?xml version="1.0"?>
<base>
<A>A</A>
<B>B</B>
</base>
Update:
You could also try...
function read_xml_files() {
$target = new DOMDocument();
$target->loadXML('<queries />');
mergeFile($target, "NewFile.xml");
mergeFile($target, "NewFile1.xml");
$xml = simplexml_import_dom($target);
return $xml->asXML();
}
function mergeFile ( DOMDocument $target, $fileName ) {
$source = new DOMDocument();
$source->load($fileName);
foreach ( $source->getElementsByTagName("query") as $row ) {
$import = $target->importNode($row, true);
$target->documentElement->appendChild($import);
}
}
This merges the file so that the result is
<?xml version="1.0"?>
<queries>
<query>
<admin_user_type>user</admin_user_type>
<show_in_menu>True</show_in_menu>
<title>Dashboard</title>
<vertical_report>True</vertical_report>
</query>
<query>
<admin_user_type>admin</admin_user_type>
<show_in_menu>false</show_in_menu>
<title>Profile Element</title>
<input_name>Id</input_name>
<input_type>hidden</input_type>
</query>
</queries>
Upvotes: 3