Format XML output in PHP

When defined before saving the xml file, the options

$dom->formatOutput = true;
$dom->preserveWhiteSpace = false; 

should result in a formatted XML output, i.e. where each node is on one line and is indented. But this doesn’t seem to format the XML for me.

Here is the PHP code.

<?php

$dom = new DOMDocument();
$dom->load('communities.xml');

$dom->formatOutput = true;
$dom->preserveWhiteSpace = false;

// get document element

$root   = $dom->documentElement;

$xname     = $dom->createElement("NAME");
$xnameText = $dom->createTextNode("Hobbies");
$xname->appendChild($xnameText);

$xtop     = $dom->createElement("TOP");
$xtopText = $dom->createTextNode("60");
$xtop->appendChild($xtopText);

$xleft     = $dom->createElement("LEFT");
$xleftText = $dom->createTextNode("460");
$xleft->appendChild($xleftText);

$xwidth     = $dom->createElement("WIDTH");
$xwidthText = $dom->createTextNode("200");
$xwidth->appendChild($xwidthText);

$xheight     = $dom->createElement("HEIGHT");
$xheightText = $dom->createTextNode("400");
$xheight->appendChild($xheightText);

$xurls = $dom->createElement("URLS");

$xunames = array ("Bing.com", "Aol.com");
$xuurls = array ("http://www.bing.com", "http://www.aol.com");

$nurls = sizeof($xunames);

echo $xunames;
echo $xuurls;
echo "nurls: ".$nurls;

for ( $i=0; $i < $nurls; $i++ ) {
   $xurl = $dom->createElement("URL");
   $xuid = $i+1;
   $xurl->setAttribute("ID", "u00".$xuid);
   $xuname = $dom->createElement("NAME");
   $xunameText = $dom->createTextNode(mysql_escape_mimic($xunames[$i]));
   $xuname->appendChild($xunameText);
   $xuurl = $dom->createElement("URL");
   $xuurlText = $dom->createTextNode(mysql_escape_mimic($xuurls[$i]));
   $xuurl->appendChild($xuurlText);
   $xurl->appendChild($xuname);
   $xurl->appendChild($xuurl);
   $xurls->appendChild($xurl);
}

$community = $dom->createElement('COMMUNITY');
$community->setAttribute("ID", "c008");
$community->appendChild($xname);
$community->appendChild($xtop);
$community->appendChild($xleft);
$community->appendChild($xwidth);
$community->appendChild($xheight);
$community->appendChild($xurls);
$root->appendChild($community);

$dom->save('communities.xml');

?>

The xml file is saved without carriage returns. What could be the problem?

Have you tried it with

$dom->preserveWhiteSpace = true;

Yes I did.

I have this PHP code that adds a set of nodes to an XML file. It does most of what it should do, it finds where to make the additions, but then it doesn’t make the update.

I have an xml file of this structure.

<COMMUNITIES>
   <COMMUNITY ID="c001">
        <URLS>
            <URL ID="u001">
               <NAME>Google.com</NAME>
               <URL>http://www.google.com</URL>
            </URL>
        </URLS>
   </COMMUNITY>
</COMMUNITIES>

The updates are being made to the URLS node. The user clicks an “Add URL” link and I add the new URL to this node like this.

       <URL ID="u002">
           <NAME>Yahoo.com</NAME>
           <URL>http://www.yahoo.com</URL>
       </URL>

If the URLS node exists, I append the new url node. If the URLS node does not exist, I create it, then append the new url node.

There are no errors, everything seems to work, but the URLS node is empty. Here is the PHP script.

function add_url( $nodeid, $urlid, $urlname, $urllink ) {

$dom = new DOMDocument();
$dom->load('communities.xml');

$dom->formatOutput = true;
$dom->preserveWhiteSpace = true;

// get document element

$xpath = new DOMXPath($dom);
$nodes = $xpath->query("//COMMUNITY[@ID='$nodeid']");

if ($nodes->length) {
   $node = $nodes->item(0);

   $xurl = $dom->createElement("URL");
   $xurl->setAttribute("ID", $urlid);

   $xuname     = $dom->createElement("NAME");
   $xunameText = $dom->createTextNode(mysql_escape_mimic($urlname));
   $xuname->appendChild($xunameText);

   $xulink     = $dom->createElement("URL");
   $xulinkText = $dom->createTextNode(mysql_escape_mimic($urllink));
   $xulink->appendChild($xulinkText);

   $xurl->appendChild($xuname);
   $xurl->appendChild($xulink);

   $xurls = $xpath->query("//COMMUNITY[@ID='$nodeid']/URLS");

   if ($xurls->length) {
   }
   else {
      $xurls = $dom->createElement("URLS");
   }

   $xurls->appendChild($xurl);

   $node->appendChild($xurls);

}

/* $dom->asXML('communities.xml'); */
$dom->save('communities.xml');
}

I’ve played with the code for a while and I’m stumped for now.
The doc example

<?php
$doc = new DOMDocument('1.0');
// we want a nice output
$doc->formatOutput = true;

$root = $doc->createElement('book');
$root = $doc->appendChild($root);

$title = $doc->createElement('title');
$title = $root->appendChild($title);

$text = $doc->createTextNode('This is the title');
$text = $title->appendChild($text);

$doc->save("example.xml");
?> 

creates

<?xml version="1.0"?>
<book>
  <title>This is the title</title>
</book>

nice as can be. Newlines and even indentation.

I made a few changes to your code but still didn’t have any luck trying quite a few things.

I thought the reuse of node names might have something to do with it. So I changed one of the <NAME>s to UNAME and one of the <URL>s to URI.
I moved the “format” and “preserve” before the “load”.
I tried “asXML” (I see you did too).
I simplified the “creates”

//$xname     = $dom->createElement("NAME");
//$xnameText = $dom->createTextNode("Hobbies");
//$xname->appendChild($xnameText);
$xname     = $dom->createElement("NAME", "Hobbies");

I tried making the “appends” more like the doc example.

  • but still no go. :frowning:

Thanks for looking at this.

Hi,

Since you were kind enough to look into this for me. I thought I´d tell you that I found a workaround. There are two functions I found that do the formatting and they are more reliable than formatoutput.

http://gdatatips.blogspot.com/2008/11/xml-php-pretty-printer.html

I put the first one (formatXmlString) in my code and changed the newline from "
" to "\r
".

 $result .= $line . "\\r\

";

From my PHP script I call that function.

$formatted = formatXmlString($nodes->asXML());

$file = fopen (‘linkcards.xml’, “w”);
fwrite($file, $formatted);
fclose ($file);

This creates a formatted XML output.

Thanks for getting back. I’ll try it as soon as I get a chance. I know it doesn’t make much difference to a machine, but I like to be able to easily read code.