Delicious Bookmark this on Delicious Share on Facebook SlashdotSlashdot It! Digg! Digg



PHP : Function Reference : SimpleXML functions

SimpleXML functions

Introduction

The SimpleXML extension provides a very simple and easily usable toolset to convert XML to an object that can be processed with normal property selectors and array iterators.

Requirements

The SimpleXML extension requires PHP 5.

Installation

The SimpleXML extension is enabled by default. To disable it, use the --disable-simplexml configure option.

Examples

Many examples in this reference require an XML string. Instead of repeating this string in every example, we put it into a file which we include in each example. This included file is shown in the following example section. Alternatively, you could create an XML document and read it with simplexml_load_file().

Example 2237. Include file example.php with XML string

<?php
$xmlstr
= <<<XML
<?xml version='1.0' standalone='yes'?>
<movies>
<movie>
 <title>PHP: Behind the Parser</title>
 <characters>
  <character>
   <name>Ms. Coder</name>
   <actor>Onlivia Actora</actor>
  </character>
  <character>
   <name>Mr. Coder</name>
   <actor>El Act&#211;r</actor>
  </character>
 </characters>
 <plot>
  So, this language. It's like, a programming language. Or is it a
  scripting language? All is revealed in this thrilling horror spoof
  of a documentary.
 </plot>
 <great-lines>
  <line>PHP solves all my web problems</line>
 </great-lines>
 <rating type="thumbs">7</rating>
 <rating type="stars">5</rating>
</movie>
</movies>
XML;
?>


The simplicity of SimpleXML appears most clearly when one extracts a string or number from a basic XML document.

Example 2238. Getting <plot>

<?php
include 'example.php';

$xml = new SimpleXMLElement($xmlstr);

echo
$xml->movie[0]->plot; // "So this language. It's like..."
?>


Accessing elements within an XML document that contain characters not permitted under PHP's naming convention (e.g. the hyphen) can be accomplished by encapsulating the element name within braces and the apostrophe.

Example 2239. Getting <line>

<?php
include 'example.php';

$xml = new SimpleXMLElement($xmlstr);

echo
$xml->movie->{'great-lines'}->line; // "PHP solves all my web problems"
?>


Example 2240. Accessing non-unique elements in SimpleXML

When multiple instances of an element exist as children of a single parent element, normal iteration techniques apply.

<?php
include 'example.php';

$xml = new SimpleXMLElement($xmlstr);

/* For each <movie> node, we echo a separate <plot>. */
foreach ($xml->movie as $movie) {
  echo
$movie->plot, '<br />';
}

?>


Example 2241. Using attributes

So far, we have only covered the work of reading element names and their values. SimpleXML can also access element attributes. Access attributes of an element just as you would elements of an array.

<?php
include 'example.php';

$xml = new SimpleXMLElement($xmlstr);

/* Access the <rating> nodes of the first movie.
* Output the rating scale, too. */
foreach ($xml->movie[0]->rating as $rating) {
   switch((string)
$rating['type']) { // Get attributes as element indices
   
case 'thumbs':
       echo
$rating, ' thumbs up';
       break;
   case
'stars':
       echo
$rating, ' stars';
       break;
   }
}
?>


Example 2242. Comparing Elements and Attributes with Text

To compare an element or attribute with a string or pass it into a function that requires a string, you must cast it to a string using (string). Otherwise, PHP treats the element as an object.

<?php    
include 'example.php';

$xml = new SimpleXMLElement($xmlstr);

if ((string)
$xml->movie->title == 'PHP: Behind the Parser') {
   print
'My favorite movie.';
}

htmlentities((string) $xml->movie->title);
?>


Example 2243. Using XPath

SimpleXML includes built-in XPath support. To find all <character> elements:

<?php
include 'example.php';
$xml = new SimpleXMLElement($xmlstr);

foreach (
$xml->xpath('//character') as $character) {
   echo
$character->name, 'played by ', $character->actor, '<br />';
}
?>

'//' serves as a wildcard. To specify absolute paths, omit one of the slashes.


Example 2244. Setting values

Data in SimpleXML doesn't have to be constant. The object allows for manipulation of all of its elements.

<?php
include 'example.php';
$xml = new SimpleXMLElement($xmlstr);

$xml->movie[0]->characters->character[0]->name = 'Miss Coder';

echo
$xml->asXML();
?>

The above code will output a new XML document, just like the original, except that the new XML will change Ms. Coder to Miss Coder.


Example 2245. Adding elements and attributes

Since PHP 5.1.3, SimpleXML has had the ability to easily add children and attributes.

<?php
include 'example.php';
$xml = new SimpleXMLElement($xmlstr);

$character = $xml->movie[0]->characters->addChild('character');
$character->addChild('name', 'Mr. Parser');
$character->addChild('actor', 'John Doe');

$rating = $xml->movie[0]->addChild('rating', 'PG');
$rating->addAttribute('type', 'mpaa');

echo
$xml->asXML();
?>

The above code will output an XML document based on the original but having a new character and rating.


Example 2246. DOM Interoperability

PHP has a mechanism to convert XML nodes between SimpleXML and DOM formats. This example shows how one might change a DOM element to SimpleXML.

<?php
$dom
= new domDocument;
$dom->loadXML('<books><book><title>blah</title></book></books>');
if (!
$dom) {
    echo
'Error while parsing the document';
    exit;
}

$s = simplexml_import_dom($dom);

echo
$s->book[0]->title;
?>


Table of Contents

SimpleXMLElement->addAttribute() — Adds an attribute to the SimpleXML element
SimpleXMLElement->addChild() — Adds a child element to the XML node
SimpleXMLElement->asXML() — Return a well-formed XML string based on SimpleXML element
SimpleXMLElement->attributes() — Identifies an element's attributes
SimpleXMLElement->children() — Finds children of given node
SimpleXMLElement->__construct() — Creates a new SimpleXMLElement object
SimpleXMLElement->getDocNamespaces() — Returns namespaces declared in document
SimpleXMLElement->getName() — Gets the name of the XML element
SimpleXMLElement->getNamespaces() — Returns namespaces used in document
SimpleXMLElement->registerXPathNamespace() — Creates a prefix/ns context for the next XPath query
SimpleXMLElement->xpath() — Runs XPath query on XML data
simplexml_import_dom — Get a SimpleXMLElement object from a DOM node.
simplexml_load_file — Interprets an XML file into an object
simplexml_load_string — Interprets a string of XML into an object

Code Examples / Notes » ref.simplexml

darkstream777

You dont need a function named "fixCDATA".
Work with "htmlentities" and "html_entity_decode" is
better.
A short example:
$xml->addChild($key, "<![CDATA[".htmlentities($value)."]]>");
print_r((html_entity_decode($files_xml->asXML())));
Greetings S.P. aka darki777


josh sowin fireandknowledge.org

You can't use CDATA with SimpleXML, but there is a way around it. Wrap your child in CDATA like this:
<? $listing->addChild( 'description', '<![CDATA[' . $row['description'] . ']]>' ); ?>
And then when you display the XML, run it through this function:
<?
function fixCDATA($string) {
$find[] = '&lt;![CDATA[';
$replace[] = '<![CDATA[';

$find[] = ']]&gt;';
$replace[] = ']]>';
return $string = str_replace($find, $replace, $string);
}
$xml = fixCDATA( $xml->asXML() );
echo $xml;
?>


lists

While you can't add new elements to a SimpleXML object you can however add new attributes
<?php
$string = '<doc channel="chat"><test1>Hello</test1></doc>';
$xml = simplexml_load_string($string);
$xml->test1['sub'] = 'No';
echo $xml->asXML();
?>
Will return output
<doc channel="chat"><test1 sub="No">Hello</test1></doc>


jebner

When using Apache & PHP on windows and you try to do a direct typecast to string or integer of your SimpleXMLElement objects, your Apache MAY crash  (mine did :-( ).
would look like this:
$id = (int)$xml->id;
so try other things like firts converting it to a string  with strval() NOT direct typecast - this won't work neither.
seems like direct typecast doesnt work on objects (doesn' suprise me very much)


karsten dot bruch

When creating a new XML document and adding text with umlauts and such
$SimpleXMLElement->asXML();
will silently NOT output any content with umlauts.
Use htmlentities () while adding Umlauts & co to solve the "problem"


lukemoscrop

to eho when using name space you need to select the arry from it (xpath turns all of it in to array)
<?php
$logined = $xml->xpath('/root/login/@status');
echo $logined[0];
//to see the the array its self
//use print_r() function
//
print_r($logined);
?>


vaedan

This is one new stuff to get the root name (since PHP 5.1.3) :
<?php
$xml = simplexml_load_string( '<foo name="bar" />' );
echo $xml->getName(); // displays foo
?>


david

This function could be useful to somebody if you want to insert an XML into another when building an XML from many different files.
Note that you must specify a name for the node in which the child files content/node will be inserted :
foreach (xxx as $firstCondition){
$xml_parent = simplexml_load_file("$firstCondition.xml");
foreach (yyy as $secondCondition){
$xml_children = simplexml_load_file("secondCondition.xml");
SimpleXMLElementObj_into_xml($xml_parent , $xml_children , 'linkingNode'); //will insert every nodes of the files at the end of the parent_xml
} }
function SimpleXMLElementObj_into_xml($xml_parent, $xml_children, $linkingNode= "linkingNode" , $child_count = 0 , $xml = false ){
if(!$xml)    {
$xml = $xml_parent->addChild($linkingNode);
}else{
$xml = $xml_parent[$child_count];
}
$child_count = 0;
foreach($xml_children->children() as $k => $v)    {
if($xml->$k){
$child_count++;
}
if($v->children())        {
$xml->addChild($k);
SimpleXMLElementObj_into_xml($xml->$k, $v, '', $child_count, true);
}else{
$xml->addChild($k, $v);
}
}
return $xml;
}
Thanks to some contributor whom I've taken the structure of this function.


codje2

Sometimes it's nice to mix up data storage types. This is a very simple SQL to XML converter. Feed it a SQL query and it outputs the result in XML.
The first paramater should be a mysql_query result
(optional)The second is the xml name for each row (i.e the second depth of XML)
(optional)The third is the name of the XML document, the root name
<?php
$result=mysql_query("SELECT * FROM users");
sql_to_xml($result,"users","members");
function sql_to_xml($mysql_result,$row_name="row",$doc_name="root")
{

$xml= new SimpleXMLElement("<$doc_name></$doc_name>");
while($line=mysql_fetch_assoc($mysql_result))
{
$row=$xml->addChild($row_name);
foreach($line as $column => $value)
{
$row->$column="$value";
}
}
return $xml->asXML();
}
?>


greg dot steffensen

Simplexml's simplicity can be deceptive.  Simplexml elements behave either as objects or strings, depending on the context in which they're used (through overloading of the __toString() method, I assume).  Statements implying conversion to string treat them as strings, while assignment operations treat them as objects.  This can lead to unexpected behavior if, for example, you are trying to compare the values of two Simplexml elements.  The expected syntax will not work.  To force conversion to strings, just "typecast' whatever Simplexml element you're using.  For example:
<?php
$s = simplexml_load_string('<foo>43</foo> <bar>43</bar>');
// Evaluates to false by comparing object IDs instead of strings
($s->foo == $s->bar);
// Evaluates to true
((string)$s->foo == (string)$s->bar);
?>
[Ed. Note: Changed from quotes to casts because casts provide a quicker and more explicit conversion than do double quotes.]


roy dot walter

simplexml provides a neat way to do 'ini' files. Preferences for any number of users can be held in a single XML file having elements for each user name with user specific preferences as attributes of child elements. The separate <pref/>'s could of course be combined as multiple attributes of a single <pref/> element but this could get unwieldy.
In the sample code below the makeXML() function uses the simplexml_load_string function to generate some XML to play with and the readPrefs() function parses the requested users preferences into an array.
<?
function makeXML() {
$xmlString = <<<XML
<preferences>
<johndoe>
<pref color="#FFFFFF"/>
<pref size="14"/>
<pref font="Verdana"/>
</johndoe>
<janedoe>
<pref color="#000000"/>
<pref size="16"/>
<pref font="Georgia"/>
</janedoe>
</preferences>
XML;
return simplexml_load_string($xmlString);
}
function readPrefs($user, $xml) {

foreach($xml->$user as $arr);
$n = count($arr);

for($i=0;$i<$n;$i++) {
foreach($xml->$user->pref[$i]->attributes() as $a=>$b) {
$prefs[$a] = (string)$b;
}
}

print_r($prefs);
}
readPrefs('johndoe', makeXML());
?>


daniel dot oconnor

SimpleXML handles namespaces, but it's not documented very well here at all.
If you wanted to parse, say, an open office manifest file or a piece of RDF/XML, you have to get elements and attributes by the namespace url.
Example:
<?php
function display($in) {
   if (file_exists($in)) {
       $xml = simplexml_load_file($in);
   } else {
       throw new Exception($in . " does not exist");
   }
   $manifest = $xml->children('http://openoffice.org/2001/manifest');
   foreach ($manifest->xpath('//manifest:file-entry') as $file) {
       foreach ($file->attributes('http://openoffice.org/2001/manifest') as $key => $value) {
           print "Key:" . $key . "\n";
           print "Value:" . $value . "\n";
       }
   }
}
?>
File: manifest.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE manifest:manifest PUBLIC "-//OpenOffice.org//DTD Manifest 1.0//EN" "Manifest.dtd">
<manifest:manifest xmlns:manifest="http://openoffice.org/2001/manifest">
<manifest:file-entry manifest:media-type="application/vnd.sun.xml.writer" manifest:full-path="/"/>
<manifest:file-entry manifest:media-type="application/vnd.sun.xml.ui.configuration" manifest:full-path="Configurations2/"/>
<manifest:file-entry manifest:media-type="application/binary" manifest:full-path="layout-cache"/>
<manifest:file-entry manifest:media-type="text/xml" manifest:full-path="content.xml"/>
<manifest:file-entry manifest:media-type="text/xml" manifest:full-path="styles.xml"/>
<manifest:file-entry manifest:media-type="text/xml" manifest:full-path="meta.xml"/>
<manifest:file-entry manifest:media-type="" manifest:full-path="Thumbnails/thumbnail.png"/>
<manifest:file-entry manifest:media-type="" manifest:full-path="Thumbnails/"/>
<manifest:file-entry manifest:media-type="text/xml" manifest:full-path="settings.xml"/>
</manifest:manifest>


cellog

simplexml does not simply handle CDATA sections in a foreach loop.
<?php
$sx = simplexml_load_string('
<test>
<one>hi</one>
<two><![CDATA[stuff]]></two>
<t>
 <for>two</for>
</t>
<multi>one</multi>
<multi>two</multi>
</test>');
foreach((array) $sx as $tagname => $val) {
   if (is_string($val)) {
      // <one> will go here
   } elseif (is_array($val)) {
      // <multi> will go here because it happens multiple times
   } elseif (is_object($val)) {
     // <t> will go here because it contains tags
     // <two> will go here because it contains CDATA!
   }
}
?>
To test in the loop, do this
<?php
if (count((array) $val) == 0) {
   // this is not a tag that contains other tags
   $val = '' . $val;
   // now the CDATA is revealed magically.
}
?>


joshi

One way to work around the issue that Arnaud presented on 19-Oct-2006 is to check for the existence of the node before doing a 'foreach' on it.
<?php
  $xml = simplexml_load_string('<root></root>');
  if( $xml->b )  // Or maybe 'isset' or 'array_key_exists'
  {
     foreach($xml->b as $dummy);
  }
  echo $xml->asXML();
?>
Gives the expected result:
<?xml version="1.0"?>
<root/>
You can see the same behavior using an array, although you'll get a warning:
<?php
 $p['a'] = '1';
 foreach( $p['b'] as $node );
 print_r( $p );
?>
Result:
Warning:  Invalid argument supplied for foreach()
Array
(
   [a] => 1
   [b] =>
)


nelson_menezes

Note that SimpleXML expects to both read and output XML in UTF-8 encoding. You'll need to add a line such as this at the top of your input XML file if it isn't saved in UTF-8 (adjust to whatever encoding used):
<?xml version="1.0" encoding="ISO-8859-1" ?>
On the output side of things, if you're not serving/handling UTF-8, you'll need to use utf8_decode() [red. but that will only work for ISO-8859-1, not other encodings]. Common mistake: http://bugs.php.net/bug.php?id=28154


jaskas

More new stuff.
<?php
$xml = "
<test></test>
";
$xml = simplexml_load_string($xml);
$xml->addChild('new','value','namespace');
echo $xml->asXml();
?>
output:
<?xml version="1.0"?>
<test><new xmlns="namespace">value</new></test>
Very nice and clean. DOM is so awkward compared to this.


php

Memory leak when setting attributes as in example (#Example 2134. Setting values)
This probably goes unnoticed in web scripts (unless you do a LOT of xml manipulations), but I ran into this in my standalone script that processes a large number of XML files.
The following code will eat up memory quite fast:
<?php
include 'example.php';
while (true) {
 $xml = new SimpleXMLElement($xmlstr);
 $xml->movie[0]->characters->character[0]->name = 'Miss Coder';
}
?>
while this seems to behave correctly:
<?php
include 'example.php';
while (true) {
 $xml = new SimpleXMLElement($xmlstr);
 $c = $xml->xpath("//character");
 $c[0]->name = 'Miss Coder';
}
?>
This looks like bug #38604, and I just confirmed that in 6.0.0-dev (on Windows at least) it is fixed.  It is NOT fixed in 5.2.1 or  5.2.2-dev (2/21 build), so for 5.2 users, use the second form to avoid leaks.


charles

Just a minor modification to Daniel Favire's simplexml2ISOarray function: I added an if-block around the attributes section so you don't get a SimpleXML attributes element along with each attributes array:
function simplexml2ISOarray($xml,$attribsAsElements=0) {
if (get_class($xml) == 'SimpleXMLElement') {
$attributes = $xml->attributes();
foreach($attributes as $k=>$v) {
if ($v) $a[$k] = (string) $v;
}
$x = $xml;
$xml = get_object_vars($xml);
}
if (is_array($xml)) {
if (count($xml) == 0) return (string) $x; // for CDATA
foreach($xml as $key=>$value) {
$r[$key] = simplexml2ISOarray($value,$attribsAsElements);
if (!is_array($r[$key])) $r[$key] = utf8_decode($r[$key]);
}
if (isset($a)) {
if($attribsAsElements) {
$r = array_merge($a,$r);
} else {
$r['@'] = $a; // Attributes
}
}
return $r;
}
return (string) $xml;
}


http://methylblue.com

It is a grave misfortune that this doesn't work:
<?
 $node = new SimpleXml;
 echo $node->{"namespace:tagname"}[attribute'];
?>
Instead you have to go through loops!
<?
 $namespace = $node->children( 'namespace' );
 $attributes = $namespace->tagname->attributes;
 echo $attribute['attribute'];
?>
AFAICT there is no simpler way. SimpleXml is great in premise, but useless for things like RSS feeds, which lets face it, most PHP development with XML is about.
Great shame!


joel from the website purerave.com

It doesn't mention this anywhere, but creationg a new SimpleXMLElement object from a non-valid string throws an exception. It looks ugly in the php log as it dumps the stack in multiple lines.
The correct way to create a new SimpleXMLElement object is like so:
<?php
$xmlstr = ''; // empty to throw an exception
try {
  $xml = new SimpleXMLElement($xmlstr);
} catch (Exception $e) {
  // handle the error
  echo '$xmlstr is not a valid xml string';
}
?>


judas dot iscariote

In response to webmaster at mavoric dot net comment.
It is a complete non-sense to use include() to retrieve an external RSS feed, remember that include is intented to **parse and execute PHP code** and an RSS feed is, quite obivously, **not** PHP code.
people that wants to read external resources should use file_get_contents, fopen or an SplFileObject, never **ever** use include() with remote resources.


anthony dot parsons

If you're handling lots of HTML or mixed-content XML you'll probably want to use the DOM functions instead of SimpleXML. Take this for example:
<?php
$html = new SimpleXMLElement('<div>

Some text, <a href="#">a link,</a> more text</div>');
echo $html->p->a,"
\n"; // "a link,"
echo $html->p;             // "Some text, more text" (!)
?>
In the above example reconstructing the original markup is impossible because of the way SimpleXML represents the data.


leonid kogan

if you want to export an array as xml you can use this script
<?php
$test=array("TEST"=>"nurso",
"none"=>null,
"a"=>"b",
array(
"c"=>"d",
array("d"=>"e")));
$xml=array_to_simplexml($test);
print->($xml);
print_r($xml->asXML());
function array_to_simplexml($array, $name="config" ,&$xml=null )
{
if(is_null($xml))
{
$xml = new SimpleXMLElement("<{$name}/>");
}

foreach($array as $key => $value)
{
if(is_array($value))
{
$xml->addChild($key);
array_to_simplexml($value, $name, $xml->$key);
}
else
{
$xml->addChild($key, $value);
}
}
return $xml;
}
?>


lordi

If you need to do math calculations on values extracted from simplexml document, you might need to cast the value as float to prevent precision loss. Here is an example:
<?
$objXML = new SimpleXMLElement('<test x="-123.45"></test>');

//Shows correctly
echo $objXML['x']."\n";

//We loose the decimals
echo $objXML['x'] + $objXML['x']."\n";

$x = $objXML['x'];

//This works if we cast the amounts
echo (float)$objXML['x'] + (float)$objXML['x']."\n";

//Calculated on a string, no problem
echo "-123.45" + "-123.45";

?>
This is due to the fact that $objXML['x'] is not a string (php would cast it automatically) neither a float, but a SimpleXMLElement object.
"echo var_dump($x);" will output this
~~
object(SimpleXMLElement)#3 (1) {
 [0]=>
 string(7) "-123.45"
}
~~
I opened a bug request on php but here is the answer they gave me:
~~
Status: Won't fix
The behavior is defined by the engine not the extension. When performing mathematical operations on objects, they are treated as integers. It is up to the user to cast the object to the appropriate type to maintain proper precision.
~~


webmaster

If you are using the above examples to get at external XML/RSS files and are encountering errors, you need to understand that PHP Version 5.2.3 + forbids the use of using include to get at external XML/RSS files . You need to change the start of the code slightly...
<?php
$url = 'http://www.a_external_site.com/example.xml';
$rss_file = file_get_contents($url);
$xml = new SimpleXMLElement($rss_file);
echo $xml->movie[0]->plot; // "So this language. It's like..."
?>
Just replace the first two lines of the exsisting code with the first two of the above code.


brcavanagh

If you are looking to use SimpleXML for anything but reading XML documents, you should really reconsider, and use the XML DOM library.  By the time you get enough utilities implemented in DOM to handle all the set backs in SimpleXML, you will have defeated the purpose of using SimpleXML.  There are a few reasons for this, and there are already many workrounds, but the primairy issues are this
1) No complex node assignment.  You cannot switch nodes or replace them.  
2) No appending new child nodes
3) Whenever you do something like $new_node = $xml_doc->node you will always get a reference even if you use a clone method, which will crash the script.
Other than that, its a great tool for reading docs.


gregory boshoff

I've written a tutorial demonstating how to update a Google sitemap dynamically using  the PHP5 SimpleXML extension.
http://www.phpfive.net/article34.htm


nicolas

I've implemented a XML Pull Parser for PHP 5 that somewhat mimics SimpleXML - but doesn't need to load the whole document in memory :
http://tinyurl.com/2e9ew5


galaxiaguy

I tried extending SimpleXMLElement to add some functionality and found you can't set new properties. I assume this is something to do with built-in magic methods or something.
So I wrote a class that behaves the same as SimpleXMLElement (by delegating most of it's work) but is arbitrarily extendable.
http://www.oliverbrown.me.uk/2005/09/03/extending-simplexml/
It's very new and not very well tested but could be useful to somebody.


cmsa

I had a problem with entities.
My first solution:
I saved Data that way:
$ENTRY_->
addchild('Nachricht',htmlentities($_POST["blog"]));
Had Entities in the XML-File like:
<!ENTITY auml "&amp;auml">
And I loaded the Data that way:
html_entity_decode($ENTRY->Nachname);
But after saving and
loading the xml-file the entity-entry
<!ENTITY auml "&amp;auml">
disappeared. strange...
My second solution:
With saving the Data this way:
$ENTRY_->
addchild('Nachricht',htmlentities(htmlentities($_POST["blog"])));
I can now load it with html_entity_decode without the
entity-entry in the XML-file!
I tested it with äöü.
Hope it helpes.


paul

Hi,
If you want to access an element that has a dash in its name, (as is common with the XML documents provided by the Library of Congress, as well as the NWS) you will need to handle it a little bit differently.
You can either use XPATH, which works fine, but will return an array of results every time, even if there is a single result.
eg.
$xml->xpath('/data/time-layout/start-valid-time'}
You can also choose just to encapsulate the element names containing a dash:
$xml->data->{'time-layout'}->{'start-valid-time'}
--
On a only partially related note, dealing with SimpleXML is one of the only times I have employed casting with PHP. While iterating (foreach) through the valid times, echo'ing the element worked great (it merely echo'ed the apropriate time), assigning it to another variable resulted in a SimpleXML object containing the time to be assigned, rather than just the time itself. This was resolved by casting the time to a string:
foreach($xml->data->{'time-layout'}->{'start-valid-time'} AS $time)
{
$weatherDates[] = (string) $time;
}


jason sheets
Here is my Simple XML to array function, it is recursive and has the benefit of maintaining key value relationships and has worked well for me.
function XMLToArray($xml)
{
 if ($xml instanceof SimpleXMLElement) {
   $children = $xml->children();
   $return = null;
 }
 foreach ($children as $element => $value) {
   if ($value instanceof SimpleXMLElement) {
     $values = (array)$value->children();
     
     if (count($values) > 0) {
       $return[$element] = XMLToArray($value);
     } else {
       if (!isset($return[$element])) {
         $return[$element] = (string)$value;
       } else {
         if (!is_array($return[$element])) {
           $return[$element] = array($return[$element], (string)$value);
         } else {
           $return[$element][] = (string)$value;
         }
       }
     }
   }
 }
 
 if (is_array($return)) {
   return $return;
 } else {
   return $false;
 }
}


php dot net

For the poor users who can only use a PHP4 solution, there are some alternatives to it like minixml or my simple php class called sxml which runs with php5 as well as with php4: http://www.shop24-7.info/32-0-simplexml-alternative-php4.html
It is easy to modify and has a clear structure. The result of the class is an array which owns the xml file's data.
have fun with it


bens

Data can be lost when using SimpleXML!!! Consider the following XML:
<root position="base">
<edition id="20070705" onsale="2007-07-06" online="2007-07-06 09:00">
 <headline maxchars="50" someattr="whatever">
  <cell attr="meaningless">The new issue</cell>
 </headline>
</edition>
<monkey id="123">
 <face class="round">red</face>
 <face class="square">pink</face>
</monkey>
</root>
parsed as follows
$res = simplexml_load_string($xml);
print_r($res);
1) The name of the first (root?) tag of the document is lost - there is no way to find out what the root tag was called. (in this case, I called it "root") However, the attributes within that tag are preserved. (position="base")
2) The innermost tag's attributes are lost.  (apparently, any tag with data in it) Note that attr='meaningless' in the cell tag, as well as the class="square"/"round" is lost.
This is when using PHP 5.1.6 on Fedora Core 6 with stock RPMs.


mail

Correct me if I'm wrong, but I think the output of the SimpleXMLElement Object is dependent on the PHP version. Consider this code:
$xml = '<edition id="20070705" onsale="2007-07-06" online="2007-07-06 09:00">
<headline maxchars="50">The new issue</headline>
</edition>';
$res = simplexml_load_string($xml);
print("<pre>");
print_r($res);
print("</pre>");
PHP version 5.0.4 will return this:
SimpleXMLElement Object
(
   [headline] => The new issue
)
While PHP version 5.2.1 returns (some) attributes as well:
SimpleXMLElement Object
(
   [@attributes] => Array
       (
           [id] => 20070705
           [onsale] => 2007-07-06
           [online] => 2007-07-06 09:00
       )
   [headline] => The new issue
)


php

Concerning SimpleXML and sessions:
When creating a SimpleXML object (to be precise: a SimpleXMLElement object) in the context of a session and storing it in $_SESSION['XMLobject'], this object does not "survive" the session!
By the time re-entering the session, print_r($_SESSION['XMLobject']) says:
['XMLobject'] => SimpleXMLElement Object
Warning:  Node no longer exists in /your_php_file.php on line xyz
  (
  )
(Message simplified for the sake of better readability.)


matt

Be careful when using var_export to debug element attributes - it won't work! Always use print() or similar for checking the contents of element attributes.

arnaud bienvenu

As of PHP 5.1.4, trying to iterate on a non-existent node will actually create that node.
<?
$xml = simplexml_load_string('<root></root>');
foreach($xml->b as $dummy);
echo $xml->asXML();
?>
Gives :
<?xml version="1.0"?>
<root><b/></root>
You might think it is a bug, but PHP developers seam to consider it as a feature : http://bugs.php.net/bug.php?id=39164


t chassagnette t_chassagnette

Another method to parse an XML Document into a PHP array with SIMPLEXML inspired from Daniel FAIVRE !
function xml2php($xml)
{
$fils = 0;
$tab = false;
$array = array();
foreach($xml->children() as $key => $value)
{
$child = xml2php($value);

//To deal with the attributes
foreach($node->attributes() as $ak=>$av)
{
$child[$ak] = (string)$av;

}

//Let see if the new child is not in the array
if($tab==false && in_array($key,array_keys($array)))
{
//If this element is already in the array we will create an indexed array
$tmp = $array[$key];
$array[$key] = NULL;
$array[$key][] = $tmp;
$array[$key][] = $child;
$tab = true;
}
elseif($tab == true)
{
//Add an element in an existing array
$array[$key][] = $child;
}
else
{
//Add a simple element
$array[$key] = $child;
}

$fils++;
  }


if($fils==0)
{
return (string)$xml;
}

return $array;

}


maciek ruckgaber
after wondering around some time, i just realized something (maybe obvious, not very much for me). Hope helps someone to not waste time as i did :-P
when you have something like:
$xmlstr = <<<XML
<?xml version="1.0" encoding="utf-8"?>
<double xmlns="http://foosite.foo/">2328</double>
XML;
you will have the simpleXML object "transformed" to the text() content:
$xml = simplexml_load_string($xmlstr);
echo $xml; // this will echo 2328  (string)


igor kraus

A simple way to merge two SimpleXML objects.
<?php
/**
* Pumps all child elements of second SimpleXML object into first one.
*
* @param    object      $xml1   SimpleXML object
* @param    object      $xml2   SimpleXML object
* @return   void
*/
function simplexml_merge (SimpleXMLElement &$xml1, SimpleXMLElement $xml2)
{
   // convert SimpleXML objects into DOM ones
   $dom1 = new DomDocument();
   $dom2 = new DomDocument();
   $dom1->loadXML($xml1->asXML());
   $dom2->loadXML($xml2->asXML());
   // pull all child elements of second XML
   $xpath = new domXPath($dom2);
   $xpathQuery = $xpath->query('/*/*');
   for ($i = 0; $i < $xpathQuery->length; $i++)
   {
       // and pump them into first one
       $dom1->documentElement->appendChild(
           $dom1->importNode($xpathQuery->item($i), true));
   }
   $xml1 = simplexml_import_dom($dom1);
}
$xml1 = simplexml_load_string('<root><child>child 1</child></root>');
$xml2 = simplexml_load_string('<root><child>child 2</child></root>');
simplexml_merge($xml1, $xml2);
echo($xml1->asXml());
?>
Will output:
<?xml version="1.0"?>
<root>
   <child>child 1</child>
   <child>child 2</child>
</root>


philip


http://menic.info

@Leonid Kogan:
Your script is not working in all cases. It has problem with non-uniques elements, ie:
<?php $array = array( 'root' => array( 'first' => array( 'value', 'other' ) ) );?>
In XML it should looks like this:
<root>
 <first>value</first>
 <first>other</first>
</root>
But it will looks:
<root>
 <first>
   <1>value</1>
   <2>other</2>
 </first>
</root>
which is wrong.


julien plee using g mail dot com

<to bens at effortlessis dot com>
I see your problem, but there's a workaround.
After loading your SimpleXML object into $xml, call $xml->getName  () and you'll get your root tag name.
I use PHP 5.1.4 on Apache 1.3.33 on MacOS X and this works on it. I hope there was no SimpleXML ability downgrading :o)
Also, I kinda remember reading somewhere in this doc an advise saying "Don't use data structures parsers like var_dump() on SimpleXML." This may be the reason. And you may will work your second problem around using SimpleXMLElement->attributes() and SimpleXMLElement->getName ().


brett

"When parsing and processing an instance document, SimpleXML is an excellent technology choice. However, if significant manipulation is required, it is important that the technology understands the model for the document, and in that case, SDO [see http://php.net/sdo ] is probably a more appropriate choice."
(Charters, Peters, Maynard and Srinivas from http://www.zend.com/pecl/tutorials/sdo.php )


Change Language


Follow Navioo On Twitter
.NET Functions
Apache-specific Functions
Alternative PHP Cache
Advanced PHP debugger
Array Functions
Aspell functions [deprecated]
BBCode Functions
BCMath Arbitrary Precision Mathematics Functions
PHP bytecode Compiler
Bzip2 Compression Functions
Calendar Functions
CCVS API Functions [deprecated]
Class/Object Functions
Classkit Functions
ClibPDF Functions [deprecated]
COM and .Net (Windows)
Crack Functions
Character Type Functions
CURL
Cybercash Payment Functions
Credit Mutuel CyberMUT functions
Cyrus IMAP administration Functions
Date and Time Functions
DB++ Functions
Database (dbm-style) Abstraction Layer Functions
dBase Functions
DBM Functions [deprecated]
dbx Functions
Direct IO Functions
Directory Functions
DOM Functions
DOM XML Functions
enchant Functions
Error Handling and Logging Functions
Exif Functions
Expect Functions
File Alteration Monitor Functions
Forms Data Format Functions
Fileinfo Functions
filePro Functions
Filesystem Functions
Filter Functions
Firebird/InterBase Functions
Firebird/Interbase Functions (PDO_FIREBIRD)
FriBiDi Functions
FrontBase Functions
FTP Functions
Function Handling Functions
GeoIP Functions
Gettext Functions
GMP Functions
gnupg Functions
Net_Gopher
Haru PDF Functions
hash Functions
HTTP
Hyperwave Functions
Hyperwave API Functions
i18n Functions
IBM Functions (PDO_IBM)
IBM DB2
iconv Functions
ID3 Functions
IIS Administration Functions
Image Functions
Imagick Image Library
IMAP
Informix Functions
Informix Functions (PDO_INFORMIX)
Ingres II Functions
IRC Gateway Functions
PHP / Java Integration
JSON Functions
KADM5
LDAP Functions
libxml Functions
Lotus Notes Functions
LZF Functions
Mail Functions
Mailparse Functions
Mathematical Functions
MaxDB PHP Extension
MCAL Functions
Mcrypt Encryption Functions
MCVE (Monetra) Payment Functions
Memcache Functions
Mhash Functions
Mimetype Functions
Ming functions for Flash
Miscellaneous Functions
mnoGoSearch Functions
Microsoft SQL Server Functions
Microsoft SQL Server and Sybase Functions (PDO_DBLIB)
Mohawk Software Session Handler Functions
mSQL Functions
Multibyte String Functions
muscat Functions
MySQL Functions
MySQL Functions (PDO_MYSQL)
MySQL Improved Extension
Ncurses Terminal Screen Control Functions
Network Functions
Newt Functions
NSAPI-specific Functions
Object Aggregation/Composition Functions
Object property and method call overloading
Oracle Functions
ODBC Functions (Unified)
ODBC and DB2 Functions (PDO_ODBC)
oggvorbis
OpenAL Audio Bindings
OpenSSL Functions
Oracle Functions [deprecated]
Oracle Functions (PDO_OCI)
Output Control Functions
Ovrimos SQL Functions
Paradox File Access
Parsekit Functions
Process Control Functions
Regular Expression Functions (Perl-Compatible)
PDF Functions
PDO Functions
Phar archive stream and classes
PHP Options&Information
POSIX Functions
Regular Expression Functions (POSIX Extended)
PostgreSQL Functions
PostgreSQL Functions (PDO_PGSQL)
Printer Functions
Program Execution Functions
PostScript document creation
Pspell Functions
qtdom Functions
Radius
Rar Functions
GNU Readline
GNU Recode Functions
RPM Header Reading Functions
runkit Functions
SAM - Simple Asynchronous Messaging
Satellite CORBA client extension [deprecated]
SCA Functions
SDO Functions
SDO XML Data Access Service Functions
SDO Relational Data Access Service Functions
Semaphore
SESAM Database Functions
PostgreSQL Session Save Handler
Session Handling Functions
Shared Memory Functions
SimpleXML functions
SNMP Functions
SOAP Functions
Socket Functions
Standard PHP Library (SPL) Functions
SQLite Functions
SQLite Functions (PDO_SQLITE)
Secure Shell2 Functions
Statistics Functions
Stream Functions
String Functions
Subversion Functions
Shockwave Flash Functions
Swish Functions
Sybase Functions
TCP Wrappers Functions
Tidy Functions
Tokenizer Functions
Unicode Functions
URL Functions
Variable Handling Functions
Verisign Payflow Pro Functions
vpopmail Functions
W32api Functions
WDDX Functions
win32ps Functions
win32service Functions
xattr Functions
xdiff Functions
XML Parser Functions
XML-RPC Functions
XMLReader functions
XMLWriter Functions
XSL functions
XSLT Functions
YAZ Functions
YP/NIS Functions
Zip File Functions
Zlib Compression Functions
eXTReMe Tracker