downloads | documentation | faq | getting help | mailing lists | licenses | wiki | reporting bugs | php.net sites | links | conferences | my php.net

search for in the

SimpleXMLElement->addAttribute()> <shmop_write
[edit] Last updated: Mon, 01 Nov 2010

view this page in

CXLIV. SimpleXML関数

導入

SimpleXML拡張モジュールは、 XMLをオブジェクトにとても簡単かつ容易に変換するための機能を 提供します。変換後のオブジェクトでは、 通常のプロパティセレクタや配列反復子を用いて処理を行うことが 可能です。

要件

SimpleXML 拡張モジュールは PHP 5 が必要になります。

インストール手順

SimpleXML 拡張モジュールは、デフォルトで利用可能です。 この機能を無効にするには、 --disable-simplexml コンフィギュアオプションを使用してください。

このリファレンスの多くの例ではXML文字列を必要とします。各例で この文字列をくり返す代わりに、あるファイルにこの文字列を保存して、 各例で読みこむことにします。この読みこまれるファイルは、以下の例 に関するセクションで使用されます。 もしくは、XMLドキュメントを作成し、 simplexml_load_file() により読みこむことも 可能です。

例 1. XML文字列を設定するインクルードファイル example.php

<?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>
  <rating type="thumbs">7</rating>
  <rating type="stars">5</rating>
 </movie>
</movies>
XML;
?>

SimpleXMLの容易さが最も明確に現われるのは、 簡単なXMLドキュメントから文字列または数字を展開する時です。

例 2. <plot> を取得する

<?php
include 'example.php';

$xml = new SimpleXMLElement($xmlstr);

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

例 3. SimpleXMLでユニークでない要素にアクセスする

単一の親要素の子要素としてある要素のインスタンスが複数存在する時、 通常の反復処理を適用することができます。

<?php
include 'example.php';

$xml = new SimpleXMLElement($xmlstr);

/* 個々の <movie> ノードに対して、<plot> を分割して表示します */
foreach ($xml->movie as $movie) {
   echo
$movie->plot, '<br />';
}

?>

例 4. 属性を使用する

ここまでは、要素の名前と値を読む方法のみを扱って来ました。 SimpleXMLは要素の属性にアクセスすることも可能です。 要素の属性にアクセスする方法は、配列 の要素に アクセスするのと全く同じです。

<?php
include 'example.php';

$xml = new SimpleXMLElement($xmlstr);

/* 最初の映画の <rating> ノードにアクセスします。
 * また、その評価も出力します。*/
foreach ($xml->movie[0]->rating as $rating) {
    switch((string)
$rating['type']) { // 要素のインデックスとして、属性を取得します
   
case 'thumbs':
        echo
$rating, ' thumbs up';
        break;
    case
'stars':
        echo
$rating, ' stars';
        break;
    }
}
?>

例 5. 要素および属性をテキストと比較する

要素または属性を文字列と比較する、もしくは、文字列を引数とする関数に 渡すには、(string) により文字列にキャストする 必要があります。さもないと、PHPはこの要素をオブジェクトとして扱います。

<?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);
?>

例 6. XPath の使用

SimpleXML は、XPath を標準でサポートしています。 <character> 要素を全て見つけるには、 以下のようにします。

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

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

'//' はワイルドカードとして動作します。絶対パスを指定するには、 スラッシュを一つだけにします。

例 7. 値を設定する

SimpleXMLの中のデータは、定数とすることができません。 オブジェクトは、その全ての要素について変更が可能です。

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

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

echo
$xml->asXML();
?>

上のコードは、元のXMLドキュメントと全く同じXMLドキュメントを新規に 出力しますが、新しいXMLファイルでは、Ms. Coder が Miss Coder に変更されているところが異なります。

例 8. 要素と属性を追加する

PHP 5.1.3 以降では、SimpleXML を使用して簡単に子要素および属性を追加することができます。

<?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();
?>

上のコードは、元と同じオブジェクトを出力しますが、 そこに新しいキャラクターと評価が追加されています。

例 9. DOMとの相互運用性

PHPは、SimpleXML形式とDOM形式の間でXMLノードを変換する機構を有しています。 この例では、DOM要素を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;
?>

目次
SimpleXMLElement->addAttribute() --  SimpleXML 要素に属性を追加する
SimpleXMLElement->addChild() --  XML ノードに子要素を追加する
SimpleXMLElement->asXML() --  SimpleXML 要素に基づき整形式の XML 文字列を返す
SimpleXMLElement->attributes() --  要素の属性を定義する
SimpleXMLElement->children() --  指定したノードの子ノードを見付ける
SimpleXMLElement->__construct() --  新しい SimpleXMLElement オブジェクトを作成する
SimpleXMLElement->getDocNamespaces() --  ドキュメントで宣言されている名前空間を返す
SimpleXMLElement->getName() -- XML 要素の名前を取得する
SimpleXMLElement->getNamespaces() --  ドキュメントで使用している名前空間を返す
SimpleXMLElement->registerXPathNamespace() --  次の XPath クエリ用の prefix/ns コンテキストを作成する
SimpleXMLElement->xpath() --  XMLデータにXpathクエリを実行する
simplexml_import_dom --  DOMノードからSimpleXMLElementオブジェクトを取得する
simplexml_load_file --  XMLファイルをパースし、オブジェクトに代入する
simplexml_load_string --  XML文字列をオブジェクトに代入する


SimpleXMLElement->addAttribute()> <shmop_write
[edit] Last updated: Mon, 01 Nov 2010
 
add a note add a note User Contributed Notes SimpleXML関数
thomas at guenneguez dot com 14-Dec-2011 02:36
Merge two xml only with SimpleXML :
Function corrected if note containe only value.

<?php
function mergeXML(&$base, $add)
{
    if (
$add->count() != 0 )
       
$new = $base->addChild($add->getName());
    else
       
$new = $base->addChild($add->getName(), $add);
    foreach (
$add->attributes() as $a => $b)
    {
       
$new->addAttribute($a, $b);
    }
    if (
$add->count() != 0 )
    {
        foreach (
$add->children() as $child)
        {
           
mergeXML($new, $child);
        }
    }
}
?>

Use : <?php mergeXML($xmlElement, simplexml_load_string($toMerge)) ?>
julien dot breiner at laposte dot net 09-Dec-2011 10:31
Merge two xml only with SimpleXML :

<?php
private function mergeXML(&$base, $add)
{
   
$new = $base->addChild($add->getName());
    foreach (
$add->attributes() as $a => $b) {
       
$new[$a] = $b;
    }
    foreach (
$add->children() as $child) {
       
$this->mergeXML($new, $child);
    }
}
?>

Use : <?php mergeXML($xmlElement, simplexml_load_string($toMerge)) ?>
k dot antczak at livedata dot pl 22-Apr-2011 01:08
A quick snippet which converts XML Object into array:

<?php
function xml2array ( $xmlObject, $out = array () )
{
        foreach ( (array)
$xmlObject as $index => $node )
           
$out[$index] = ( is_object ( $node ) ) ? xml2array ( $node ) : $node;

        return
$out;
}
?>

Have fun! ;-)
help :-) @ theapotek :-) com 08-Apr-2011 12:54
If you are having trouble accessing CDATA in your simplexml document, you don't need to str_replace/preg_replace the CDATA out before loading it with simplexml.

You can do this instead, and all your CDATA contents will be merged into the element contents as strings.

$xml = simplexml_load_file($xmlfile,
'SimpleXMLElement', LIBXML_NOCDATA);
Andrez zenarter at hotmail dot com 16-Jul-2009 10:56
I just wanna add an additional to
"Append/combine/merge one simplexml to another"
The parent should has attributes too.

<?php

function append_simplexml(&$simplexml_to, &$simplexml_from)
{
   
static
$firstLoop=true;
           
//Here adding attributes to parent           
if( $firstLoop )
            {
                foreach(
$simplexml_from->attributes() as $attr_key => $attr_value )
                {
                   
$simplexml_to->addAttribute($attr_key, $attr_value);
                }
            }

foreach (
$simplexml_from->children() as $simplexml_child)
    {
       
$simplexml_temp = $simplexml_to->addChild($simplexml_child->getName(), (string) $simplexml_child);
        foreach (
$simplexml_child->attributes() as $attr_key => $attr_value)
        {
           
$simplexml_temp->addAttribute($attr_key, $attr_value);
        }

      
$firstLoop=false;

       
append_simplexml($simplexml_temp, $simplexml_child);
    }

unset(
$firstLoop=false );
}

?>

I have aproblem to assign an object into a variable used as an object later, Then i found the code above, it solve half of my problem. I have it should have the parent name assign too but it didnt. Any better code?
Douglas Marsh 06-Jul-2009 08:53
SimpleXML is really nice for loading/converting XML data into native PHP data structures. I was considering crude searching of SVG for the width/height and since it really is an XML file... I found a SUPER easy method for parsing out the information I wanted:

<?php
// putting incomplete SVG data inline for readability
$RawXML = <<< XML
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
   xmlns:dc="http://www.example.com/dc"
   xmlns:cc="http://www.example.com/cc"
   xmlns:rdf="http://www.example.com/rdf"
   xmlns:svg="http://www.example.com/svg"
   xmlns="http://www.example.com/"
   xmlns:sodipodi="http://www.example.com/sodipodi"
   xmlns:inkscape="http://www.example.com/inkscape"
   id="svg2"
   sodipodi:version="0.32"
   inkscape:version="0.46"
   width="586.25"
   height="743.75"
   xml:space="preserve"
   sodipodi:docname="some_svg_file.svg"
   inkscape:output_extension="org.inkscape.output.svg.inkscape">
 <!-- portions removed to keep this short -->
</svg>
XML;

$svg = new SimpleXMLElement($RawXML);

$height = $svg['height'];
$width = $svg['width'];

echo
"The width x height is: ${width} x ${height} \n";

?>
info at ajaxforum dot ru 17-Jun-2009 12:32
Append/combine/merge one simplexml to another:

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

// wrong way!
// php convert $el2->movie[0] to string silently
$el1->addChild('movie', $el2->movie[0]);

// wrong way!
// php 5.1 convert $el2->movie[0] to string and generate Warning: It is not yet possible to assign complex types to properties. It is not possible to assign complex types to nodes
// php 5.2 convert $el2->movie[0] to string silently
$el1->addChild('movie');
$el1->movie[2] = $el2->movie[0];

// right way!
$el1_movie = $el1->addChild('movie');
append_simplexml($el1_movie, $el2->movie[0]);

echo
"<pre>"; print_r($el1); echo "</pre>";

/**
 * Add one simplexml to another
 *
 * @param object $simplexml_to
 * @param object $simplexml_from
 * @author Boris Korobkov
 * @link http://www.ajaxforum.ru/
 */
function append_simplexml(&$simplexml_to, &$simplexml_from)
{
    foreach (
$simplexml_from->children() as $simplexml_child)
    {
       
$simplexml_temp = $simplexml_to->addChild($simplexml_child->getName(), (string) $simplexml_child);
        foreach (
$simplexml_child->attributes() as $attr_key => $attr_value)
        {
           
$simplexml_temp->addAttribute($attr_key, $attr_value);
        }
       
       
append_simplexml($simplexml_temp, $simplexml_child);
    }
}
?>
codejunky32 at NOSPAM dot com 22-May-2009 08:45
Just wanted to add a post as to how you can extract the value from a SimpleXMLElement. Its not as straightforward as you think. Because its a complex object you can't just access the element directly. Here is a sample of data that represents a var_dump of a SimpleXmlElement

array(1) {
  [0]=>
  object(SimpleXMLElement)#13 (2) {
    ["@attributes"]=>
    array(1) {
      ["name"]=>
      string(5) "title"
    }
    [0]=>
    string(19) "PHP Tech Book"
  }
}

If you want to extract the title of the book you have to cast the specified element to a string like so.
$newTitle = (string) $title[0]; 

The $title variable is the SimpleXMLElement that you have extracted from the xml document using simplexml_load_string for instance.  To initially access the title element from the xml document you can do like so, using xpath.
$title = $doc->xpath('str[@name="title"]');

Hope this helps someone out there.
james dot ellis at gmail dot com 28-Aug-2008 06:55
While SimpleXML is a powerful tool, developers using it to process and handle large XML documents & strings should take into careful consideration its memory usage requirements.
SimpleXML requires the entire XML tree to be available prior to any processing actions on that tree -- this requires the entire tree to be in memory. Ok for a 40kb XML file but when dealing with > 100MB files you will see performance degradation, especially if you have a busy server.

An alternative to processing large XML files is the XMLReader class, which operates in streaming mode, of which an excellent tutorial is presented here:
http://www.ibm.com/developerworks/library/x-pullparsingphp.html

XML is an incredibly verbose format. If you are dealing with large data structures, especially in web services, do you you actually need to represent the data as an XML tree? - other serialisation formats such as JSON, Serialised PHP, Google Protocol Buffers (http://code.google.com/p/protobuf/) and even CSV can remarkably reduce processing time, bandwidth and load  when dealing with large files. A 110MB XML file can become a 65MB CSV file, with the same data in it, simply because the data identifiers (tags) are only represented once in the entire document.
m0sh3 at hotmail dot com 22-May-2008 03:24
Be aware of quirks like this one:

<?php

$a
= new SimpleXMLElement('<a><b/></a>');

$a->b = 'test &amp; test';
$a->c = 'test &amp; test';

print_r($a);
/*
OUTPUT:

SimpleXMLElement Object
(
    [b] => test & test
    [c] => test &amp; test
)
*/
nathan at gimpstraw dot com 05-Apr-2008 09:43
I'm using SimpleXML to process data sent back from an API request, and I ran into the CDATA problem and the error you get from html entities, and here is a solution i came up with, don't know if it's the most practical, but it's working.

<?php
$str
= <<< XML
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<menu>
    <item>
        <title><![CDATA[Caf&eacute;]]></title>
        <description><![CDATA[Some description.]]></description>
    </item>
</menu>
XML;

$str = preg_replace("/\<\!\[CDATA\[(.*?)\]\]\>/ies", "'[CDATA]'.base64_encode('$1').'[/CDATA]'", $str);
$xml = new SimpleXMLElement($str);

// Return item title's
foreach ($xml->item as $item) {
   
$tmp = (string) $item->title;
   
$tmp = preg_replace("/\[CDATA\](.*?)\[\/CDATA\]/ies", "base64_decode('$1')", $tmp);
    echo
$tmp;
}
?>
ngkongs at gmail dot com 19-Mar-2008 10:44
fix the function i posted before, have a wrong quote placement

function implode2($glue="", $var){
    if ($var){
        foreach ($var as $value){
            $array[]=strval($value);
        }
        return implode($glue, $array);
    }
    else return false;
}
philippe_marc_--a---t--_novartis_com 12-Feb-2008 09:46
TIP: if you run into memory issue using simpleXML.
You may want to use PHP>5.2.5 in order to avoid that: http://bugs.php.net/bug.php?id=38604
If not possible, avoid "foreach ( $xmldata->node as $node )" like calls.
andrvm 02-Jan-2008 03:01
<?php
/**
    * Remove node/nodes xml with xpath
    *
    * @param SimpleXMLElement                 $xml
    * @param string XPath                     $path
    * @param string ('one'|'child'|'all')     $multi
    *
    * Use:
    *
    * Example xml file - http://ru2.php.net/manual/ru/ref.simplexml.php
    *
    * $xml = simplexml_load_file($xmlfile);
    *
    * //1. remove only 1 node (without child nodes)
    * //   $path must return only 1 (unique) node without child nodes
    * removeNode($xml, '//movie/rating[@type="thumbs"]');
    *
    * //2. remove 1 node (with 1 child nodes)
    * //    $path can return any nodes - will be removed only first node
    * //   with all child nodes
    * removeNode($xml, '//characters', 'child')
    *
    * //3. remove all nodes (with child nodes)
    * //   $path can return any nodes - will be removed all
    * //   with child nodes
    * removeNode($xml, '//rating', 'all')
    *
    * $xml->asXML($xmlfile);
    *
    */
  
function removeNode($xml, $path, $multi='one')
   {
      
$result = $xml->xpath($path);
                
         
# for wrong $path
         
if (!isset($result[0])) return false;
        
          switch (
$multi) {
              case
'all':
                   
$errlevel = error_reporting(E_ALL & ~E_WARNING);
                    foreach (
$result as $r) unset ($r[0]);
                   
error_reporting($errlevel);
                    return
true;
                   
                case
'child':
                   unset(
$result[0][0]);
                   return
true;
                
                case
'one':
                   if (
count($result[0]->children())==0 && count($result)==1) {
                       unset(
$result[0][0]);
                       return
true;
                   }
                  
                default:
                      return
false;            
          }
 } 
?>

p.s. after use (if deleted all nodes):
<?php

  
function trimXml($xmlfile)
   {
      
$dom = new DOMDocument();
       
         
$dom->preserveWhiteSpace = false;
     
         if (!
$dom->load($xmlfile)) return false;
     
        
$dom->formatOutput = true;
     
         if (!
$dom->save($xmlfile)) return false;
       
         return
true;
   }
?>
onPHP5.com 17-Nov-2007 04:37
It does not say in the docs, but SimpleXML will convert all text into UTF-8, if the source XML declaration has another encoding. Eg, if the source has the following XML decl:

<?xml version="1.0" encoding="windows-1251" ?>

all the text in the resulting SimpleXMLElement will be in UTF-8 automatically.
lordi at msdi dot ca 23-Oct-2007 05:35
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:

<?php
    $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.
~~
cmsa at gmx dot de 27-Aug-2007 05:07
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.
karsten dot bruch at bms-verlage dot de 16-Aug-2007 08:28
When creating a new XML document and adding text with umlauts and such

<?php $SimpleXMLElement->asXML(); ?>

will silently NOT output any content with umlauts.

Use htmlentities () while adding Umlauts & co to solve the "problem"
anthony dot parsons at manx dot net 03-Aug-2007 07:40
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><p>Some text, <a href="#">a link,</a> more text</p></div>');

echo
$html->p->a,"<br>\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.
php at werner dash ott dot de 28-Mar-2007 06:03
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.)
codje2 at lboro dot ac dot uk 11-Mar-2007 01:46
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();
}

?>
php at NOSPAM dot coutch dot com 21-Feb-2007 02:04
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.
joel [from the website] purerave.com 19-Feb-2007 05:57
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';
}
?>
matt at mattbostock dot com 05-Nov-2006 11:40
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 19-Oct-2006 07:35
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
Jason Sheets <jsheets at shadonet dot com> 31-May-2006 10:31
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.

<?php
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;
  }
}
?>
daniel dot oconnor at gmail dot com 17-May-2006 06:21
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>
paul at preinheimer dot com 06-May-2005 05:11
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.

<?php
$xml
->xpath('/data/time-layout/start-valid-time');
?>

You can also choose just to encapsulate the element names containing a dash:
<?php $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:

<?php
foreach($xml->data->{'time-layout'}->{'start-valid-time'} AS $time)
{
 
$weatherDates[] = (string) $time;
}
?>
T CHASSAGNETTE t_chassagnette at yahoo dot fr 04-May-2005 01:57
Another method to parse an XML Document into a PHP array with SIMPLEXML inspired from Daniel FAIVRE !

<?php
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;
   
}
?>
nelson_menezes at yahoo dot co dot uk 01-Mar-2005 05:05
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
brcavanagh AT NO SPAM hotmail.com 02-Jan-2005 09:18
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.

 
show source | credits | sitemap | contact | advertising | mirror sites