The below code is fetched from php.net (http://docs.php.net/manual/en/domdocument.savexml.php). My problem is - it doesn't work. My only output from this is: "Saving all the document: Saving only the title part:". What am I missing here?
$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);
echo "Saving all the document:\n";
echo $doc->saveXML() . "\n";
echo "Saving only the title part:\n";
echo $doc->saveXML($title);
PHP sends a Content-type http header. And by default it's text/html. I.e. the client is supposed to interpret the response document as html. But you're sending an xml document (and some text and another fragment, which invalidates the output).
If you want to send an xml document tell the client so, e.g. via header('Content-type: text/xml')
$doc = new DOMDocument('1.0');
$doc->formatOutput = true;
$root = $doc->appendChild($doc->createElement('book'));
$title = $root->appendChild($doc->createElement('title', 'This is the title'));
if (headers_sent() ) {
echo 'oh oh, something wnet wrong';
}
else {
header('Content-type: text/xml; charset=utf-8');
echo $doc->saveXML();
}
Related
I am using PHP to generate a XML and display on my browser. I have the following code:
<?php
header("content-type:application/xml; charset=ISO-8859-15");
$doc = new DOMDocument('1.0');
// we want a nice output
$doc->formatOutput = true;
$doc->preserveWhiteSpace = false;
$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);
//echo "Saving all the document:\n";
//echo $doc->saveXML()."\n";
echo "Saving only the title part:\n";
echo $doc->saveXML($title);
?>
If I comment out echo "Saving only the title part:\n";, it generates the XML to me in my browser without any problem, but if I try to add this echo "Saving only the title part:\n"; before echo $doc->saveXML($title);, it will give me the following error in my browser :
This page contains the following errors:
error on line 1 at column 1: Document is empty
Below is a rendering of the page up to the first error.
Does anybody knows why? Is there a way to display a string before printing out the XML in my browser?
This is because you have set your documents content type to application/xml, so the browser is expecting all content to be in the form of XML.
To get the above code to work, change the content type to text/plain
The following code works (tested on my machine):
header("content-type:text/plain; charset=ISO-8859-15");
$doc = new DOMDocument('1.0');
$doc->formatOutput = true;
$doc->preserveWhiteSpace = false;
$root = $doc->createElement('book');
$root = $doc->appendChild($root);
$title = $doc->createElement('title');
$title = $root->appendChild($title);
echo "Saving only the title part:\n";
echo $doc->saveXML($title);
I want to save space by saving the xml file in minified form
for example
<body>
<div>
<p>hello</p>
<div/>
</div>
</body>
it should be saved like this
<body><div><p>hello</p><div/></div></body>
I'm using DOMDocument to create xml file like this
$xml = new DOMDocument("1.0", "UTF-8");
$xml->preserveWhiteSpace = false;
$xml->formatOutput = false;
$feed = $xml->createElement("feed");
$feed = $xml->appendChild($feed);
/*add attribute*/
$feed_attribute = $xml->createAttribute('xmlns:xsi');
$feed_attribute->value = 'http://www.w3.org/2001/XMLSchema-instance';
$feed->appendChild($feed_attribute);
$aggregator = $xml->createElement("aggregator");
$aggregator = $feed->appendChild($aggregator);
$name = $xml->createElement('name', 'test.com');
$aggregator->appendChild($name);
...etc
$xml->save(public_path() .$string, LIBXML_NOEMPTYTAG);
You're already using the right options. DOMDocument::$formatOutput and DOMDocument::$preserveWhiteSpace:
Format Output
DOMDocument::$formatOutput adds indentation whitespace nodes to an XML DOM if saved. (It is disabled by default.)
$document = new DOMDocument();
$body = $document->appendChild($document->createElement('body'));
$div = $body->appendChild($document->createElement('div'));
$div
->appendChild($document->createElement('p'))
->appendChild($document->createTextNode('hello'));
echo "Not Formatted:\n", $document->saveXML();
$document->formatOutput = TRUE;
echo "\nFormatted:\n", $document->saveXML();
Output:
Not Formatted:
<?xml version="1.0"?>
<body><div><p>hello</p></div></body>
Formatted:
<?xml version="1.0"?>
<body>
<div>
<p>hello</p>
</div>
</body>
However it does not indent if here are text child nodes. It tries to avoid changes to the text output of an HTML/XML document. So it will usually not reformat a loaded document with existing indention whitespace nodes.
Preserve White Space
DOMDocument::$preserveWhiteSpace is an option for the parser. If disabled (It is enabled by default) the parser will ignore any text nodes that would consists of only whitespaces. Indentations are text nodes with a linebreak and some spaces or tabs. It can be used to remove indentations from an XML.
$xml = <<<'XML'
<?xml version="1.0"?>
<body>
<div>
<p>hello</p>
</div>
</body>
XML;
$document = new DOMDocument();
$document->preserveWhiteSpace = FALSE;
$document->loadXML($xml);
echo $document->saveXML();
Output:
<?xml version="1.0"?>
<body><div><p>hello</p></div></body>
Try this, you have to use saveXML() instead of save(),
<?php
$xml = new DOMDocument('1.0');
$xml->preserveWhiteSpace = false;
$xml->formatOutput = false;
$root = $xml->createElement('book');
$root = $xml->appendChild($root);
$title = $xml->createElement('title');
$title = $root->appendChild($title);
$text = $xml->createTextNode("This is the \n title");
$text = $title->appendChild($text);
echo "Saving all the document:\n";
$xml_content = $xml->saveXML();
echo $xml_content . "\n";
$xml_content = str_replace(array(">\n", ">\t"), '>', trim($xml_content, "\n"));
echo $xml_content . "\n";
// Write the contents back to the file
$filename = "/tmp/xml_minified.xml";
file_put_contents($filename, $xml_content);
?>
Hey there i'm trying to generate an XML file with php variables.
but echo or print don't seem to work watch my snippet below.
How could i achieve what i'm trying todo?
$xml = new DOMDocument();
$root = $xml->createElement('package');
$root = $xml->appendChild($root);
$title = $xml->createElement('id' , echo $_GET['bundleid']);
$title = $root->appendChild($title);
As luenib pointed out, you generally don't put "echo" before variables that you pass to functions as arguments. Below is a simple example of outputting XML to browser or writing to file.
$xml = new DOMDocument();
$root = $xml->createElement('package');
$root = $xml->appendChild($root);
$title = $xml->createElement('id' , $_GET['bundleid']); // no "echo" before variable
//$title = $xml->createElement('id' , $_POST['bundleid']);
//$title = $xml->createElement('id' , $bundleid);
//$title = $xml->createElement('id' , 'bundleid');
$title = $root->appendChild($title);
$xml->formatOutput = true;
$xml_string = $xml->saveXML();
// Store XML to file.
file_put_contents('path/myXmlFile.xml',$xml_string);
// Output XML to browser.
//header("Content-type: text/xml");
//echo $xml_string;
Im trying to create a XML file using php.
When I print my xml it prints it all in one line and not in proper format.
$xml = new DomDocument();
**$xml->preserveWhiteSpace = false;
$xml->FormatOutput = true;**
$parent = $xml->createElement("foo");
$parent->setAttribute("xmlns", "http://");
$parent->setAttribute("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance");
$parent->setAttribute("xsi:schemaLocation", "link");
$xml->appendChild($parent);
$child = $xml->createElement("foo1");
$parent->appendChild($child);
$subchile = $xml->createElement($foo);
$child->appendChild($subchile);
$s_c = $xml->createElement("foo3",$foo3);
$subchile->appendChild($s_c);
echo "<xmp>" . $xml->saveXML() . "<xml>";
$xml->save($file_name)
it prints everything without indentations etc.
I read other questions here and followed the answers but still nothing. Can you help?
changed $xml->FormatOutput = true; ---> $xml->formatOutput = true;
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?
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]);
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
<?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);
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();
// ##### 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
Two different issues here:
Set the formatOutput and preserveWhiteSpace attributes to TRUE to generate formatted XML:
$doc->formatOutput = TRUE;
$doc->preserveWhiteSpace = TRUE;
Many web browsers (namely Internet Explorer and Firefox) format XML when they display it. Use either the View Source feature or a regular text editor to inspect the output.
See also xmlEncoding and encoding.
This is a slight variation of the above theme but I'm putting here in case others hit this and cannot make sense of it ...as I did.
When using saveXML(), preserveWhiteSpace in the target DOMdocument does not apply to imported nodes (as at PHP 5.6).
Consider the following code:
$dom = new DOMDocument(); //create a document
$dom->preserveWhiteSpace = false; //disable whitespace preservation
$dom->formatOutput = true; //pretty print output
$documentElement = $dom->createElement("Entry"); //create a node
$dom->appendChild ($documentElement); //append it
$message = new DOMDocument(); //create another document
$message->loadXML($messageXMLtext); //populate the new document from XML text
$node=$dom->importNode($message->documentElement,true); //import the new document content to a new node in the original document
$documentElement->appendChild($node); //append the new node to the document Element
$dom->saveXML($dom->documentElement); //print the original document
In this context, the $dom->saveXML(); statement will NOT pretty print the content imported from $message, but content originally in $dom will be pretty printed.
In order to achieve pretty printing for the entire $dom document, the line:
$message->preserveWhiteSpace = false;
must be included after the $message = new DOMDocument(); line - ie. the document/s from which the nodes are imported must also have preserveWhiteSpace = false.
based on the answer by #heavenevil
This function pretty prints using the browser
function prettyPrintXmlToBrowser(SimpleXMLElement $xml)
{
$domXml = new DOMDocument('1.0');
$domXml->preserveWhiteSpace = false;
$domXml->formatOutput = true;
$domXml->loadXML($xml->asXML());
$xmlString = $domXml->saveXML();
echo nl2br(str_replace(' ', ' ', htmlspecialchars($xmlString)));
}