How to Append to a Xml File with PHP Preferably with Simplexml

How to append to a XML file with PHP preferably with SimpleXML

With SimpleXML, you can use the addChild() method.

$file = 'xml/config.xml';

$xml = simplexml_load_file($file);

$galleries = $xml->galleries;

$gallery = $galleries->addChild('gallery');
$gallery->addChild('name', 'a gallery');
$gallery->addChild('filepath', 'path/to/gallery');
$gallery->addChild('thumb', 'mythumb.jpg');

$xml->asXML($file);

Be aware that SimpleXML will not "format" the XML for you, however going from an unformatted SimpleXML representation to neatly indented XML is not a complicated step and is covered in lots of questions here.

Append Element to Xml file with Php

Since you are using DOMDocument, that's what you need:

$doc = new DOMDocument();
$doc->load($filename);
$firstchild = $doc->getElementsByTagName('firstchild')->item(0);
$newPage = $doc->createDocumentFragment();
$newPage->appendXML('<page name="second">
<inlude file="1.png"></inlude>
<inlude file="2.png"></inlude>
</page>');
$firstchild->appendChild($newPage);
$doc->save(filename);

trying to edit xml file using php simplexml

Second one is not possible as SimpleXMLElement can only take a well-formed XML string or the path or URL to an XML document. But you are passing an object of class SimpleXMLElement returned by simplexml_load_file. That is the reason it was throwing error String couldn't be parsed to XML...

In first one the asXML() method accepts an optional filename as parameter that will save the current structure as XML to a file.

If the filename isn't specified, this function returns a string on
success and FALSE on error. If the parameter is specified, it
returns TRUE if the file was written successfully and FALSE
otherwise.

So once you have updated your XML with the hints, just save it back to file.

$settings = simplexml_load_file("settings.xml");
....
if(isset($aInformation['cName']))
{
$settings->general->communityname = $aInformation['cName'];
// Saving the whole modified XML to a new filename
$settings->asXml('updated_settings.xml');
// Save only the modified node
$settings->general->communityname->asXml('settings.xml');
}

How do I update/append data to an XML file using PHP?

Instead of creating a new XML file each time, you'll want to load your existing XML file. To reuse as much of your code as possible, use SimpleXML's file-reading function:

// This file "test.xml" is pre-populated with your base XML:
// <?xml version="1.0" encoding="UTF-8"?><entrys></entrys>
$xml = simplexml_load_file('test.xml');

We need to make a change to your schema; <entrys> should be an array-like node of <entry> nodes. Correct? If so, replace your current addChild methods by creating a parent node to capture the first name, last name etc.:

$entry = $xml->addChild('entry');
$entry->addChild('fname', $fname);
$entry->addChild('lname', $lname);
$entry->addChild('location', $location);
$entry->addChild('report', $report);
$entry->addChild('description', $description);

Running this twice, we'll get something like:

<?xml version="1.0" encoding="UTF-8"?>
<entrys>
<entry>
<fname>abc</fname>
<lname>abc</lname>
<location>abc</location>
<report>abc</report>
<description>abc</description>
</entry>
<entry>
<fname>abc</fname>
<lname>abc</lname>
<location>abc</location>
<report>abc</report>
<description>abc</description>
</entry>
</entrys>

PHP SimpleXML: insert node at certain position

The following is a function to insert a new SimpleXMLElement after some other SimpleXMLElement. Since this isn't directly possible with SimpleXML, it uses some DOM classes/methods behind-the-scenes to get the job done.

function simplexml_insert_after(SimpleXMLElement $insert, SimpleXMLElement $target)
{
$target_dom = dom_import_simplexml($target);
$insert_dom = $target_dom->ownerDocument->importNode(dom_import_simplexml($insert), true);
if ($target_dom->nextSibling) {
return $target_dom->parentNode->insertBefore($insert_dom, $target_dom->nextSibling);
} else {
return $target_dom->parentNode->appendChild($insert_dom);
}
}

And an example of how it might be used (specific to your question):

$sxe = new SimpleXMLElement('<root><nodeA/><nodeA/><nodeA/><nodeC/><nodeC/><nodeC/></root>');
// New element to be inserted
$insert = new SimpleXMLElement("<nodeB/>");
// Get the last nodeA element
$target = current($sxe->xpath('//nodeA[last()]'));
// Insert the new element after the last nodeA
simplexml_insert_after($insert, $target);
// Peek at the new XML
echo $sxe->asXML();

If you want/need an explanation of how this works (the code is fairly simple but might include foreign concepts), just ask.

Extracting Data from xml file using SimpleXml

As the name of the element you want to display has a - in it, you will need to output the element using (I cast it to a string just to be pedantic)...

echo (string)$canal->{'display-name'};

Using

$canal->display-name

will be interpreted as $canal->display minus name.

XML Search and addChild

This is an addition to @Geekmans answer

Your code does not look too far of. However you can greatly improve it which is why add another answer here (I would have normally edited @Geekmans answer but it's already very large).

The point of improvement is in the program flow. If the email is not found, you don't need to create a new SimpleXMLElement, you only need to create a new <visitor> element. Then adding the <date> element as well as outputting the file is actually the same for both cases. This allows to remove the duplicate code:

// Specify the XML file we want to write to
$inFile = "data.xml";

// Set e-mail xml search and insert id
$search_id = 'jon.doe@aol.com';
$insert_id = preg_replace('/[^(\x20-\x7F)]*/', '', $search_id);

// Load the XML file we want to write to
$xmlFile = simplexml_load_file($inFile);
$results = $xmlFile->xpath("visitor[email='$search_id']");

// If we have a search result, email already exists in xml file
if ($results) {
$visitor = $results[0];
echo "Found Visitor: ", $visitor->email, "\n",
"First Date: ", $visitor->date, "\n";
} else {
echo "Adding new Visitor: ", $insert_id, "\n";
$visitor = $xmlFile->addChild("visitor");
$visitor->addChild("email", $insert_id);
}

echo "Adding new Date: ", $date = date('Y-m-d H:i:s'), "\n";
$visitor->addChild('date', $date);

echo "Changed XML: \n" . simplexml_pretty_print($xmlFile);
$xmlFile->asXML($inFile);

/**
* @param SimpleXMLElement $simplexml
* @link https://stackoverflow.com/a/798986/367456
*/
function simplexml_pretty_print(SimpleXMLElement $simplexml) {
$dom = new DOMDocument();
$dom->preserveWhiteSpace = false;
$dom->formatOutput = true;
$dom->loadXML($simplexml->asXML());
return $dom->saveXML();
}

As a bonus I added the simplexml_pretty_print function to have the output in a nicer way.

The output for jon.doe@aol.com:

Found Visitor: jon.doe@aol.com
First Date: 2012-11-01 11:00:00
Adding new Date: 2012-11-03 10:48:05
Changed XML:
<?xml version="1.0" encoding="utf-8"?>
<visitors>
<visitor>
<email>jon.doe@aol.com</email>
<date>2012-11-01 11:00:00</date>
<date>2012-11-02 14:00:00</date>
<date>2012-11-03 10:48:05</date>
</visitor>
</visitors>

The output for info@example.com:

Adding new Visitor: info@example.com
Adding new Date: 2012-11-03 10:52:09
Changed XML:
<?xml version="1.0" encoding="utf-8"?>
<visitors>
<visitor>
<email>jon.doe@aol.com</email>
<date>2012-11-01 11:00:00</date>
<date>2012-11-02 14:00:00</date>
</visitor>
<visitor>
<email>info@example.com</email>
<date>2012-11-03 10:52:09</date>
</visitor>
</visitors>

Tip: Whenever you spot duplicate code, there often is a way to write it in a much simpler form.



Related Topics



Leave a reply



Submit