cdahms
cdahms

Reputation: 3760

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

Suppose I have 3 XML files, like so:

dog.xml:

<animal>
    <species>dog</species>
    <weight>10</weight>
    <length>2</length>
</animal>

cat.xml:

<animal>
    <species>cat</species>
    <weight>2.5</weight>
    <length>1</length>
</animal>

rabbit.xml:

<animal>
    <species>rabbit</species>
    <weight>0.6</weight>
    <length>0.3</length>
</animal>

I'm attempting to combine these 3 into one PHP file that can be served as a webpage in .xml format, like so:

http://www.some.web.address.com/animals.php

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

The following stipulations apply:
-there should be a single xml version tag at the top, but no other xml version tags should be added elsewhere in the file
-the .xml tag formatting must be showing
-proper xml indenting should be maintained throughout

So far, this is the best way I can come up with, which is not that great:

<?php

$dogXml = simplexml_load_file("/some/file/location/dog.xml");
$catXml = simplexml_load_file("/some/file/location/cat.xml");
$rabbitXml = simplexml_load_file("/some/file/location/rabbit.xml");

echo "<pre>";

echo htmlspecialchars('<?xml version="1.0"?>');
echo "<br>";
echo htmlspecialchars("<animals>");
echo "<br>";

echo htmlspecialchars(explode("\n", $dogXml->asXML(), 2)[1]);
echo htmlspecialchars(explode("\n", $catXml->asXML(), 2)[1]);
echo htmlspecialchars(explode("\n", $rabbitXml->asXML(), 2)[1]);

echo htmlspecialchars("</animals>");

echo "</pre>";

?>

This produces the following output:

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

Which is correct, except for not preserving the indenting properly (the 3 animals and their descriptions should all be indented one more tab over).

Additionally, the

explode("\n", $dogXml->asXML(), 2)[1]

trickery to suppress re-printing the xml version tag with each animal seems like it may not work in all cases.

Is there a better way to accomplish this? The best sources I could find on the subject are these posts:

remove xml version tag when a xml is created in php

Merge XML files in PHP

But each of the solutions in these posts either crashed with an error, did not preserve the xml tags, or added other content (ex. repeating the xml version tag). The only content I could get to work from these posts was the explode() call above.

Suggestions?

Upvotes: 0

Views: 309

Answers (1)

Nigel Ren
Nigel Ren

Reputation: 57131

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>

Upvotes: 1

Related Questions