Nino
Nino

Reputation: 707

How to append multiple XML files

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

Answers (1)

Nigel Ren
Nigel Ren

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

Related Questions