Dhaval Bharadva
Dhaval Bharadva

Reputation: 3083

combine multiple xml into one

Hi i am parsing one xml feed into an array and its working fine for me but till now i have only one xml feed but now i am bit of stuck at one point because i need to combine multiple xml into one and then parse whole xml into an array. here i am providing some example code what actual i want.

XML1

<JobRecords>
    <JobRecord>
        <Brand>Corporate1</Brand>
        <WorkTypes>
            <WorkTypeRecord>
                <Title>Permanent1</Title>
            </WorkTypeRecord>
        </WorkTypes>
    </JobRecord>
</JobRecords>  

XML2

<JobRecords>
    <JobRecord>
        <Brand>Corporate2</Brand>
        <WorkTypes>
            <WorkTypeRecord>
                <Title>Permanent2</Title>
            </WorkTypeRecord>
        </WorkTypes>
    </JobRecord>
</JobRecords>  

XML3

<JobRecords>
    <JobRecord>
        <Brand>Corporate3</Brand>
        <WorkTypes>
            <WorkTypeRecord>
                <Title>Permanent3</Title>
            </WorkTypeRecord>
        </WorkTypes>
    </JobRecord>
</JobRecords>  

Combine XML that i want as output

<JobRecords>
    <JobRecord>
        <Brand>Corporate1</Brand>
        <WorkTypes>
            <WorkTypeRecord>
                <Title>Permanent1</Title>
            </WorkTypeRecord>
        </WorkTypes>
    </JobRecord>
    <JobRecord>
        <Brand>Corporate2</Brand>
        <WorkTypes>
            <WorkTypeRecord>
                <Title>Permanent2</Title>
            </WorkTypeRecord>
        </WorkTypes>
    </JobRecord>
    <JobRecord>
        <Brand>Corporate3</Brand>
        <WorkTypes>
            <WorkTypeRecord>
                <Title>Permanent3</Title>
            </WorkTypeRecord>
        </WorkTypes>
    </JobRecord>
</JobRecords>  

So far i have tried below code and it's work for me but take too much time for generate combine output.xml. so is there any other way to achieve this with better solution.

function simplexml_merge(SimpleXMLElement &$xml1, SimpleXMLElement $xml2) {
        // convert SimpleXML objects into DOM ones
        $dom1 = new DomDocument('1.0', 'UTF-8');
        $dom2 = new DomDocument('1.0', 'UTF-8');

        $dom1->loadXML($xml1->asXML());
        $dom2->loadXML($xml2->asXML());
        // pull all child elements of second XML
        $xpath = new domXPath($dom2);
        $xpathQuery = $xpath->query('/*/*');
        for ($i = 0; $i < $xpathQuery->length; $i++) {
            // and pump them into first one
            $dom1->documentElement->appendChild(
                $dom1->importNode($xpathQuery->item($i), true));
        }
        $xml1 = simplexml_import_dom($dom1);
    }

    $xml1 = simplexml_load_file("xml1.xml", 'SimpleXMLElement', LIBXML_NOCDATA);
    $xml2 = simplexml_load_file("xml2.xml", 'SimpleXMLElement', LIBXML_NOCDATA);

    simplexml_merge($xml1, $xml2);
    $xml1->asXml('output.xml');

Please advise me what is the best way to achieve this.
Thanks in advance and much appreciated.

Upvotes: 4

Views: 4241

Answers (1)

ThW
ThW

Reputation: 19512

Just use DOM, not SimpleXML. I added the XML to an array, here. In real code that might be a list of filenames and DOMDocument::load() would be used, not DOMdocument::loadXml().

$addXml = array();
$addXml[] = '<JobRecords>
    <JobRecord>
        <Brand>Corporate1</Brand>
        <WorkTypes>
            <WorkTypeRecord>
                <Title>Permanent1</Title>
            </WorkTypeRecord>
        </WorkTypes>
    </JobRecord>
</JobRecords>';
$addXml[] = '<JobRecords>
    <JobRecord>
        <Brand>Corporate2</Brand>
        <WorkTypes>
            <WorkTypeRecord>
                <Title>Permanent2</Title>
            </WorkTypeRecord>
        </WorkTypes>
    </JobRecord>
</JobRecords>';

// create a new document
$dom = new DOMDocument();
// and add the root element
$dom->appendChild($dom->createElement('JobRecords'));

// for each document/xml to add
foreach ($addXml as $xml) {
  // create a dom
  $addDom = new DOMDocument();
  // load the xml
  $addDom->loadXml($xml);
  // if here is a root node in the loaded xml
  if ($addDom->documentElement) {
    // for each child of the loaded root node
    foreach ($addDom->documentElement->childNodes as $node) {
      // append to the result dom
      $dom->documentElement->appendChild(
        // after importing the child to the result dom
        $dom->importNode($node, TRUE)
      );
    }
  }
}

echo $dom->saveXml();

About the same using a list of filenames/urls:

$files= array(
  'xml1.xml',
  'xml2.xml'
);

$dom = new DOMDocument();
$dom->appendChild($dom->createElement('JobRecords'));

foreach ($files as $filename) {
  $addDom = new DOMDocument();
  $addDom->load($filename);
  if ($addDom->documentElement) {
    foreach ($addDom->documentElement->childNodes as $node) {
      $dom->documentElement->appendChild(
        $dom->importNode($node, TRUE)
      );
    }
  }
}

echo $dom->saveXml();

Upvotes: 3

Related Questions