Merge Xml Files in PHP

Merge XML files in PHP

Since you've put an effort in, I've coded something that should work.

Note that this is untested code, but you get the idea.

It's up to you to make it into pretty functions. Make sure you understand what's going on; being able to work with the DOM will probably help you out in a lot of future scenarios. The cool thing about the DOM standard is that you have pretty much the same operations in many different programming languages/platforms.

    $doc1 = new DOMDocument();
$doc1->load('1.xml');

$doc2 = new DOMDocument();
$doc2->load('2.xml');

// get 'res' element of document 1
$res1 = $doc1->getElementsByTagName('res')->item(0);

// iterate over 'item' elements of document 2
$items2 = $doc2->getElementsByTagName('item');
for ($i = 0; $i < $items2->length; $i ++) {
$item2 = $items2->item($i);

// import/copy item from document 2 to document 1
$item1 = $doc1->importNode($item2, true);

// append imported item to document 1 'res' element
$res1->appendChild($item1);

}

Combining XML files in php

Merging several files can be done something like...

function mergeFile ( DOMDocument $target, $fileName )    {
$source = new DOMDocument();
$source->load($fileName);

foreach ( $source->getElementsByTagName("row") as $row ) {
$import = $target->importNode($row, true);
$target->documentElement->appendChild($import);
}
}

$target = new DOMDocument();
$target->loadXML('<?xml version="1.0" encoding="utf-8"?><sales></sales>');
mergeFile($target, "NewFile.xml");
mergeFile($target, "NewFile1.xml");
mergeFile($target, "NewFile2.xml");

$target->save("out2.xml");

This allows you to keep on adding all of the files together and then saving them at the end.

Combine multiple XML files with PHP and wrap in new root element

Actually your source only has some minor mistakes. You create a root document element in the target document, not the files element in you example. Additionally your copy of the nodes in the source documents is a level to deep, you just need to import their document elements.

I modified your code a little to make it self contained and fixed the mistakes.

$files= array(
'file1.xml' =>
'<root information="file1">
<items>
<item>FOO</item>
<item>BAR</item>
</items>
</root>',
'file2.xml' =>
'<root information="file2">
<items>
<item>BAR</item>
<item>FOO</item>
</items>
</root>'
);

// create a target document with a files root
$target = new DOMDocument();
$target->appendChild($target->createElement('files'));

// iterate the source files array
foreach ($files as $name => $content) {
// load each source
$source = new DOMDocument();
$source->loadXml($content);
// if it has a document element
if ($source->documentElement) {
// copy it to the target document
$target->documentElement->appendChild(
$target->importNode($source->documentElement, TRUE)
);
}
}

$target->formatOutput = TRUE;
echo $target->saveXml();

PHP - best way to combine multiple XML files into one, then show as a webpage with XML formatting?

Using DOMDocument rather than SimpleXML allows you to do it very easily...

function mergeFile ( DOMDocument $target, $fileName )    {
$source = new DOMDocument();
$target->preserveWhiteSpace = false;
$source->load($fileName);

$import = $target->importNode($source->documentElement, true);
$target->documentElement->appendChild($import);
}

$target = new DOMDocument();
$target->formatOutput = true;
$target->preserveWhiteSpace = true;
$target->loadXML('<?xml version="1.0" encoding="utf-8"?><animals></animals>');
mergeFile($target, "dog.xml");
mergeFile($target, "cat.xml");
mergeFile($target, "rabbit.xml");

$target->loadXML($target->saveXML());
$target->save("animals.xml");

There are a few fiddles in there to ensure the format is correct, at the end it re-loads the document to create the proper layout. Also when loading the sub-documents, the spacing isn't preserved to allow the main document to sort this out.

The output file is...

<?xml version="1.0" encoding="utf-8"?>
<animals>
<animal>
<species>dog</species>
<weight>10</weight>
<length>2</length>
</animal>
<animal>
<species>rabbit</species>
<weight>0.6</weight>
<length>0.3</length>
</animal>
<animal>
<species>cat</species>
<weight>2.5</weight>
<length>1</length>
</animal>
</animals>

Combine XML Files using PHP

Since you need to merge attributes from the rain nodes in both XML, consider XSLT, the special-purpose XML transformation language. With XSLT's document() function, you can parse from an external saved file in a current or subdirectory relative to the xsl script.

PHP can run XSLT 1.0 scripts with the php-xsl class which is enabled as an extension in .ini file. No for loops or if logic needed for this approach.

XSLT (save as .xsl file in same directory: alert.fcd.maricopa.gov/alert/Google/xml/) or embed as a PHP string)

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:strip-space elements="*"/>

<xsl:template match="/FCDMC">
<xsl:copy>
<xsl:copy-of select="rpt_info"/>
<xsl:apply-templates select="gage_rain"/>
</xsl:copy>
</xsl:template>

<xsl:template match="gage_rain">
<xsl:copy>
<xsl:variable name="curr_id" select="@id"/>
<xsl:copy-of select="@*"/>
<xsl:copy-of select="document('fcdmc_alert_return.xml')/FCDMC/return_rain[@id=$curr_id]/@*"/>
</xsl:copy>
</xsl:template>

</xsl:stylesheet>

PHP (load only the first XML as XSL handles the second XML)

// Load the XML source and XSLT file
$cd = dirname(__FILE__);
$doc = new DOMDocument();
$doc->load($cd.'/fcdmc_alert_rain_v3.xml');

$xsl = new DOMDocument;
$xsl->load($cd.'/XSLT_Script.xsl'); // OR $xsl->loadXML($xslstr);

// Configure the transformer
$proc = new XSLTProcessor;
$proc->importStyleSheet($xsl);

// Transform XML source
$newXml = $proc->transformToXML($doc);

// Save output to file
$xmlfile = $cd.'/merged.xml';
file_put_contents($xmlfile, $newXml);

Output

<?xml version="1.0"?>
<FCDMC>
<rpt_info created="07-06-2017 11:39"/>
<gage_rain id="770" last_rpt="2017-07-06T06:00:00" min_10="0.00" min_30="0.00" hour_1="0.00" hour_3="0.00" hour_6="0.00" day_1="0.00" day_3="0.00" day_7="0.00" cytd="1.77" rainscore="1" name="Tat Momolikot Dam [TM]" lat=" 32.65120" long="-111.92830" min10="0" min30="0" hour1="0" hour3="0" hour6="0" day1="0" day3="0" day7="0"/>
<gage_rain id="775" last_rpt="2017-07-06T06:00:00" min_10="0.00" min_30="0.00" hour_1="0.00" hour_3="0.00" hour_6="0.00" day_1="0.00" day_3="0.00" day_7="0.00" cytd="1.69" rainscore="1" name="Gila R. @ Maricopa Rd. [SP]" lat=" 33.17076" long="-112.00601" min10="0" min30="0" hour1="0" hour3="0" hour6="0" day1="0" day3="0" day7="0"/>
<gage_rain id="780" last_rpt="2017-07-06T06:00:00" min_10="0.00" min_30="0.00" hour_1="0.00" hour_3="0.00" hour_6="0.00" day_1="0.00" day_3="0.00" day_7="0.00" cytd="1.22" rainscore="1" name="Gila River at Olberg [SP]" lat=" 33.08706" long="-111.68700" min10="0" min30="0" hour1="0" hour3="0" hour6="0" day1="0" day3="0" day7="0"/>
<gage_rain id="785" last_rpt="2017-07-06T06:00:00" min_10="0.00" min_30="0.00" hour_1="0.00" hour_3="0.00" hour_6="0.00" day_1="0.00" day_3="0.00" day_7="0.00" cytd="2.13" rainscore="1" name="Santa Cruz R. @ SR 84 [SP]" lat=" 32.87952" long="-111.82895" min10="0" min30="0" hour1="0" hour3="0" hour6="0" day1="0" day3="0" day7="0"/>
<gage_rain id="795" last_rpt="2017-07-06T06:00:00" min_10="0.00" min_30="0.00" hour_1="0.00" hour_3="0.00" hour_6="0.00" day_1="0.00" day_3="0.00" day_7="0.00" cytd="0.43" rainscore="1" name="Greene Wash @ SR 84 [SP]" lat=" 32.87946" long="-111.93369" min10="0" min30="0" hour1="0" hour3="0" hour6="0" day1="0" day3="0" day7="0"/>
...


Related Topics



Leave a reply



Submit