PHP XML how to output nice format

145,314

Solution 1

You can try to do this:

...
// get completed xml document
$doc->preserveWhiteSpace = false;
$doc->formatOutput = true;
$xml_string = $doc->saveXML();
echo $xml_string;

You can make set these parameter right after you've created the DOMDocument as well:

$doc = new DomDocument('1.0');
$doc->preserveWhiteSpace = false;
$doc->formatOutput = true;

That's probably more concise. Output in both cases is (Demo):

<?xml version="1.0"?>
<root>
  <error>
    <a>eee</a>
    <b>sd</b>
    <c>df</c>
  </error>
  <error>
    <a>eee</a>
    <b>sd</b>
    <c>df</c>
  </error>
  <error>
    <a>eee</a>
    <b>sd</b>
    <c>df</c>
  </error>
</root>

I'm not aware how to change the indentation character(s) with DOMDocument. You could post-process the XML with a line-by-line regular-expression based replacing (e.g. with preg_replace):

$xml_string = preg_replace('/(?:^|\G)  /um', "\t", $xml_string);

Alternatively, there is the tidy extension with tidy_repair_string which can pretty print XML data as well. It's possible to specify indentation levels with it, however tidy will never output tabs.

tidy_repair_string($xml_string, ['input-xml'=> 1, 'indent' => 1, 'wrap' => 0]);

Solution 2

With a SimpleXml object, you can simply

$domxml = new DOMDocument('1.0');
$domxml->preserveWhiteSpace = false;
$domxml->formatOutput = true;
/* @var $xml SimpleXMLElement */
$domxml->loadXML($xml->asXML());
$domxml->save($newfile);

$xml is your simplexml object

So then you simpleXml can be saved as a new file specified by $newfile

Solution 3

<?php

$xml = $argv[1];

$dom = new DOMDocument();

// Initial block (must before load xml string)
$dom->preserveWhiteSpace = false;
$dom->formatOutput = true;
// End initial block

$dom->loadXML($xml);
$out = $dom->saveXML();

print_R($out);

Solution 4

Tried all the answers but none worked. Maybe it's because I'm appending and removing childs before saving the XML. After a lot of googling found this comment in the php documentation. I only had to reload the resulting XML to make it work.

$outXML = $xml->saveXML(); 
$xml = new DOMDocument(); 
$xml->preserveWhiteSpace = false; 
$xml->formatOutput = true; 
$xml->loadXML($outXML); 
$outXML = $xml->saveXML(); 

Solution 5

// ##### IN SUMMARY #####

$xmlFilepath = 'test.xml';
echoFormattedXML($xmlFilepath);

/*
 * echo xml in source format
 */
function echoFormattedXML($xmlFilepath) {
    header('Content-Type: text/xml'); // to show source, not execute the xml
    echo formatXML($xmlFilepath); // format the xml to make it readable
} // echoFormattedXML

/*
 * format xml so it can be easily read but will use more disk space
 */
function formatXML($xmlFilepath) {
    $loadxml = simplexml_load_file($xmlFilepath);

    $dom = new DOMDocument('1.0');
    $dom->preserveWhiteSpace = false;
    $dom->formatOutput = true;
    $dom->loadXML($loadxml->asXML());
    $formatxml = new SimpleXMLElement($dom->saveXML());
    //$formatxml->saveXML("testF.xml"); // save as file

    return $formatxml->saveXML();
} // formatXML
Share:
145,314

Related videos on Youtube

Dakadaka
Author by

Dakadaka

Updated on March 25, 2022

Comments

  • Dakadaka
    Dakadaka about 2 years

    Here are the codes:

    $doc = new DomDocument('1.0');
    // create root node
    $root = $doc->createElement('root');
    $root = $doc->appendChild($root);
    $signed_values = array('a' => 'eee', 'b' => 'sd', 'c' => 'df');
    // process one row at a time
    foreach ($signed_values as $key => $val) {
        // add node for each row
        $occ = $doc->createElement('error');
        $occ = $root->appendChild($occ);
        // add a child node for each field
        foreach ($signed_values as $fieldname => $fieldvalue) {
            $child = $doc->createElement($fieldname);
            $child = $occ->appendChild($child);
            $value = $doc->createTextNode($fieldvalue);
            $value = $child->appendChild($value);
        }
    }
    // get completed xml document
    $xml_string = $doc->saveXML() ;
    echo $xml_string;
    

    If I print it in the browser I don't get nice XML structure like

    <xml> \n tab <child> etc.
    

    I just get

    <xml><child>ee</child></xml>
    

    And I want to be utf-8 How is this all possible to do?

    • Thielicious
      Thielicious almost 8 years
      About your utf-8 issue, just add it to the object as a second parameter like $doc = new DOMDocument("1.0", "UTF-8");
  • hakre
    hakre over 12 years
    preserveWhiteSpace = TRUE can get in your way when you do pretty printing with DOMDocument - just FYI, not with the example given in question, but if you load from existing files that have actually whitespace textnodes.
  • hakre
    hakre over 12 years
    Related: Debug a DOMDocument Object in PHP for a more controlled form of XML printing.
  • hakre
    hakre over 11 years
  • Yang
    Yang over 9 years
    @hakre Why preserveWhiteSpace = TRUE works fine with XML, but doesn't work with HTML?
  • Álvaro González
    Álvaro González about 9 years
    @quickshiftin - Input data is an instance of SimpleXMLElement. I'll edit the answer to make it more obvious. Whatever, I agree that what you feed DOMDocument with is actually irrelevant.
  • Den
    Den almost 9 years
    To let the browser format it, a proper MIME type has to be set. For example whit: header('Content-type: text/xml');
  • Robert
    Robert over 8 years
    could you also add an explanation?
  • Jeff Puckett
    Jeff Puckett almost 8 years
    I've discovered that "You can make set these parameter right after you've created the DOMDocument as well" is not a great idea if you use saveXML while processing/comparing it with another document because it can lead to unexpected results. Best to format output right before you need to output.
  • baris1892
    baris1892 about 6 years
    upvoted, because this answer contains a complete example!
  • Ivan Prihhodko
    Ivan Prihhodko over 5 years
    Great answer, this was the only option that fully worked in my circumstance (working with RSS XML).
  • user1742529
    user1742529 over 5 years
    additionally, you can use ` $domxml->encoding = "UTF-8"` after loadXML before save.
  • gog
    gog almost 5 years
    I actually neeeded to see the whitespaces, so this was the correct answer for me