How to save changed SimpleXML object back to file?
Not sure I understand the issue. The asXML()
method accepts an optional filename as param that will save the current structure as XML to a file. So once you have updated your XML with the hints, just save it back to file.
// Load XML with SimpleXml from string
$root = simplexml_load_string('<root><a>foo</a></root>');
// Modify a node
$root->a = 'bar';
// Saving the whole modified XML to a new filename
$root->asXml('updated.xml');
// Save only the modified node
$root->a->asXml('only-a.xml');
Format output of $SimpleXML->asXML();
There's a variety of solutions in the comments on the PHP manual page for SimpleXMLElement. Not very efficient, but certainly terse, is a solution by Anonymous
$dom = dom_import_simplexml($simpleXml)->ownerDocument;
$dom->formatOutput = true;
echo $dom->saveXML();
The PHP manual page comments are often good sources for common needs, as long as you filter out the patently wrong stuff first.
Prettifying/Formatting output in SimpleXML
AFAIK simpleXML can't do it on its own.
However, DOMDocument can.
$dom = dom_import_simplexml($sxe)->ownerDocument;
$dom->formatOutput = TRUE;
$formatted = $dom->saveXML();
How to save a neatly formatted XML file using Simple XML?
If the proper format of Xml is important for you instead of SimpleXml use the DOM (also included and much more complex) extension that has a property for this:
$xml->formatOutput = true;
SimpleXMLElement won't save readable well-formatted file
Found better solution using DOMDocument. Heres rewrited example of code inside the loop:
$node_ad = $xml->CreateElement('ad');
$node_ads->appendChild($node_ad);
//$node_ads->addChild('title', htmlentities(htmlspecialchars(substr($resources['titles'][$i], 0, 70))));
$title = $xml->CreateElement('title', htmlentities(htmlspecialchars(substr($resources['titles'][$i], 0, 70))));
$node_ad->appendChild($title);
$text = $xml->CreateElement('text', 'Текст текст');
$node_ad->appendChild($text);
$images_node = $xml->CreateElement('images');
$node_ad->appendChild($images_node);
$images = $xml->CreateElement('image', $this->_mainUrl.'/uploads/'.$resources['images'][$i]);
$images_node->appendChild($images);
xml formatting- simple xml does not do pretty formatting (indent formatting)
First of all you were successful in finding out that DOMDocument supports formatted XML while SimpleXMLElement does not. And that is totally correct.
So as you want to use SimpleXMLElement to actually create the XML document but you also want to benefit from the formatting options from DOMDocument you might want to learn about the fact that both libraries are sister-libraries that work very well with each other. You already sort of seem to know about that as you make use of simplexml_import_dom
to convert a DOMNode object into it's SimpleXMLElement object.
You however seem to miss how near you already were. Please see the following example which I copied from your question - I just added a single line at the very end (and change the filename to standard output so it echoes out the documents):
$dom = new domDocument;
$dom->formatOutput = true;
$root = $dom->appendChild($dom->createElement( "user" ));
$sxe = simplexml_import_dom( $dom );
$sxe->addChild("firstname", "John");
$sxe->addChild("surname", "Brady");
$sxe->asXML('php://output');
$dom->save('php://output');
The SimpleXMLElement::saveXML()
method will use non-formatted output while the DOMDocument::save()
method will use the formatting as you set the parameters for:
<?xml version="1.0"?>
<user><firstname>John</firstname><surname>Brady</surname></user>
<?xml version="1.0"?>
<user>
<firstname>John</firstname>
<surname>Brady</surname>
</user>
And that's it already.
PHP XML how to output nice format
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]);
Format xml with DOM Document AND SimpleXML. Arrgghhh
//Get the wordpress postID
$postID = get_the_ID();
$postData = get_post($postID);
// echo $postID.'<br />'.$postData->post_title.'<br />'.$postData->post_date_gmt.'<br />';
$xmlFile = '/Applications/MAMP/htdocs/giraffetest/test.xml';
// load the document
$xml = simplexml_load_file($xmlFile);
// Check to see if the post id is already in the xml file - has it already been set?
$nodeExists = $xml->xpath("//post[@id=".$postID."]");
//Count the results
$countNodeExists = count($nodeExists);
if($countNodeExists > 0) { // If the ID is already in the file
// echo 'ID already here';
// get the correct node
$result = $xml->xpath("//post[@id=".$postID."]/postviews");
// heres the trick - the first result of xpath, and the node value (stored in [0])
$result[0][0] = $result[0][0]+1;
} else { // If the ID isn;'t there, add a new entry in the xml file for the post
//echo 'ID added';
$postNode = $xml->addChild('post'); // adding a new <post> to the top level node
$postNode->addAttribute('id', $postID); // adding a <postid> inside the new <post>
$postNode->addChild('postviews', 1); // adding a postviews inside the new <post>
}
// save the updated document
//$xml->asXML($xmlFile);
$dom = new DOMDocument('1.0');
$dom->preserveWhiteSpace = false;
$dom->formatOutput = true;
$dom->loadXML($xml->asXML());
$dom->save($xmlFile);
Related Topics
How to Have a 64-Bit Integer in PHP
Get the Client Ip Address Using PHP
Preserve Line Breaks from Textarea
PHP Code to Convert a MySQL Query to Csv
Upgrading My Encryption Library from Mcrypt to Openssl
Are Arrays in PHP Copied as Value or as Reference to New Variables, and When Passed to Functions
List of Big-O For PHP Functions
Preparing For Removal of Mcrypt in PHP 7.2
"Connect Failed: Access Denied For User 'Root'@'Localhost' (Using Password: Yes)" from PHP Function
Why Does MySQLi Num_Rows Always Return 0
Get the Last Inserted Id Using Laravel Eloquent
Get First Key in a (Possibly) Associative Array
Performance of Foreach, Array_Map With Lambda and Array_Map With Static Function