©
本文档使用
php.cn手册 发布
(PHP 5)
simplexml_load_string — Interprets a string of XML into an object
$data
[, string $class_name
= "SimpleXMLElement"
[, int $options
= 0
[, string $ns
= ""
[, bool $is_prefix
= false
]]]] )Takes a well-formed XML string and returns it as an object.
data
A well-formed XML string
class_name
You may use this optional parameter so that simplexml_load_string() will return an object of the specified class. That class should extend the SimpleXMLElement class.
options
Since PHP 5.1.0 and Libxml 2.6.0, you may also use the
options
parameter to specify additional Libxml parameters.
ns
Namespace prefix or URI.
is_prefix
TRUE
if ns
is a prefix, FALSE
if it's a URI;
defaults to FALSE
.
Returns an object of class SimpleXMLElement with
properties containing the data held within the xml document, 或者在失败时返回 FALSE
.
此函数可能返回布尔值
FALSE
,但也可能返回等同于 FALSE
的非布尔值。请阅读 布尔类型章节以获取更多信息。应使用
===
运算符来测试此函数的返回值。
Produces an E_WARNING
error message for each error
found in the XML data.
Use libxml_use_internal_errors() to suppress all XML errors, and libxml_get_errors() to iterate over them afterwards.
Example #1 Interpret an XML string
<?php
$string = <<<XML
<?xml version='1.0'?>
<document>
<title>Forty What?</title>
<from>Joe</from>
<to>Jane</to>
<body>
I know that's the answer -- but what's the question?
</body>
</document>
XML;
$xml = simplexml_load_string ( $string );
print_r ( $xml );
?>
以上例程会输出:
SimpleXMLElement Object ( [title] => Forty What? [from] => Joe [to] => Jane [body] => I know that's the answer -- but what's the question? )
At this point, you can go about using $xml->body and such.
[#1] artistan at gmail dot com [2015-06-11 12:32:10]
Here is my update to Bob's simple SimpleXML wrapper function.
I noticed his version would turn an empty SimpleXMLElement into an empty array.
<?php
function unserialize_xml($input, $callback = null, $recurse = false)
{
// Get input, loading an xml string with simplexml if its the top level of recursion
$data = ((!$recurse) && is_string($input))? simplexml_load_string($input): $input;
// Convert SimpleXMLElements to array
if ($data instanceof SimpleXMLElement){
if(!empty($data)){
$data = (array) $data;
} else {
$data = '';
}
}
// Recurse into arrays
if (is_array($data)) foreach ($data as &$item) $item = unserialize_xml($item, $callback, true);
// Run callback and return
return (!is_array($data) && is_callable($callback))? call_user_func($callback, $data): $data;
}
?>
[#2] meustrus [2015-05-07 15:38:04]
Be careful checking for parse errors. An empty SimpleXMLElement may resolve to FALSE, and if your XML contains no text or only contains namespaced elements your error check may be wrong. Always use `=== FALSE` when checking for parse errors.
<?php
$xml = <<<XML
<?xml version="1.0" encoding="UTF-8"?>
<ns1:Root xmlns:ns1="http://example.com/custom">
<ns1:Node>There's stuff here</ns1:Node>
</ns1:Root>
XML;
$simplexml = simplexml_load_string($xml);
// This prints "Parse Error".
echo ($simplexml ? 'Valid XML' : 'Parse Error'), PHP_EOL;
// But this prints "There's stuff here", proving that
// the SimpleXML object was created successfully.
echo $simplexml->children('http://example.com/custom')->Node, PHP_EOL;
// Use this instead:
echo ($simplexml !== FALSE ? 'Valid XML' : 'Parse Error'), PHP_EOL;
?>
See:
https://bugs.php.net/bug.php?id=31045
https://bugs.php.net/bug.php?id=30972
https://bugs.php.net/bug.php?id=69596
[#3] dkrnl at yandex dot ru [2013-09-30 02:58:17]
Wrapper XMLReader class, for simple SAX-reading huge xml:
https://github.com/dkrnl/SimpleXMLReader
Usage example: http://github.com/dkrnl/SimpleXMLReader/blob/master/examples/example1.php
[#4] AllenJB [2012-10-12 08:09:06]
<?php
$xml = json_decode(json_encode((array) simplexml_load_string($string)), 1);
?>
A reminder that json_encode attempts to convert data to UTF-8 without specific knowledge of the source encoding. This method can cause encoding issues if you're not working in UTF-8.
[#5] Anonymous [2012-02-29 20:54:11]
Use libxml_disable_entity_loader() to restrict loading of external files. See http://www.idontplaydarts.com/2011/02/scanning-the-internal-network-using-simplexml/
[#6] lb at bostontech dot net [2011-11-07 22:40:45]
please note that:
<?php
$data_array = (array) simplexml_load_string($xml_string);
?>
will only convert the root element to an array, where as the child elements remain XML objects.
To prove this, try returning a value N objects deep by association. Then try the same exercise using something like the object2array example below. (Which works great).
[#7] Diego Araos, diego at klapmedia dot com [2011-02-05 12:57:12]
A simpler way to transform the result into an array (requires json module).
<?php
function object2array($object) { return @json_decode(@json_encode($object),1); }
?>
Example:
<?php
$xml_object=simplexml_load_string('<SOME XML DATA');
$xml_array=object2array($xml_object);
?>
[#8] ascammon at hotmail dot com [2010-12-28 13:04:47]
I had a hard time finding this documented, so posting it here in case it helps someone:
If you want to use multiple libxml options, separate them with a pipe, like so:
<?php
$xml = simplexml_load_string($string, 'SimpleXMLElement', LIBXML_NOCDATA | LIBXML_NOBLANKS);
?>
[#9] thejhereg at gmail dot com [2010-08-30 11:24:48]
"simplexml_load_string() : Entity: line #: parser error : Comment not terminated"
On the off chance you see this error and you're pulling your hair out over it, simplexml can't seem to correctly parse XML comment tags if the comment contains "--".
Is silly and likely won't happen very often -- but sometimes it does. ;-)
[#10] jeff at creabilis dot com [2009-11-17 02:28:11]
If you want to set the charset of the outputed xml, simply set the encoding attribute like this :
<?php simplexml_load_string('<?xml version="1.0" encoding="utf-8"?>
<xml/>'); ?>
The generated xml outputed by $xml->asXML will containt accentuated characters like '??' instead of é.
Hope this help
[#11] Bob [2009-06-17 02:16:42]
Here is my simple SimpleXML wrapper function.
As far as I can tell, it does the same as Julio Cesar Oliveira's (above).
It parses an XML string into a multi-dimensional associative array.
The second argument is a callback that is run on all data (so for example, if you want all data trimmed, like Julio does in his function, just pass 'trim' as the second arg).
<?php
function unserialize_xml($input, $callback = null, $recurse = false)
{
// Get input, loading an xml string with simplexml if its the top level of recursion
$data = ((!$recurse) && is_string($input))? simplexml_load_string($input): $input;
// Convert SimpleXMLElements to array
if ($data instanceof SimpleXMLElement) $data = (array) $data;
// Recurse into arrays
if (is_array($data)) foreach ($data as &$item) $item = unserialize_xml($item, $callback, true);
// Run callback and return
return (!is_array($data) && is_callable($callback))? call_user_func($callback, $data): $data;
}
?>
[#12] tiznull [2009-04-06 22:16:45]
SimpleXMLElement - Warning: unserialize() [function.unserialize]: Node no longer exists in ?? .php
If you get this error from storing serialized SimpleXMLElement data then this is your fix??
<?php
function sxml_unserialze($str) {
return unserialize(str_replace(array('O:16:"SimpleXMLElement":0:{}', 'O:16:"SimpleXMLElement":'), array('s:0:"";', 'O:8:"stdClass":'), $str));
}
?>
[#13] Julio Cesar Oliveira [2009-03-30 07:14:43]
The XML2Array func now Recursive!
<?php
function XML2Array ( $xml , $recursive = false )
{
if ( ! $recursive )
{
$array = simplexml_load_string ( $xml ) ;
}
else
{
$array = $xml ;
}
$newArray = array () ;
$array = ( array ) $array ;
foreach ( $array as $key => $value )
{
$value = ( array ) $value ;
if ( isset ( $value [ 0 ] ) )
{
$newArray [ $key ] = trim ( $value [ 0 ] ) ;
}
else
{
$newArray [ $key ] = XML2Array ( $value , true ) ;
}
}
return $newArray ;
}
?>
[#14] Julio Cesar Oliveira [2009-03-26 08:57:40]
<?php
function XML2Array ( $xml )
{
$array = simplexml_load_string ( $xml );
$newArray = array ( ) ;
$array = ( array ) $array ;
foreach ( $array as $key => $value )
{
$value = ( array ) $value ;
$newArray [ $key] = $value [ 0 ] ;
}
$newArray = array_map("trim", $newArray);
return $newArray ;
}
?>
[#15] supzero at phparts dot net [2009-03-07 10:04:11]
if we don't know children number. How many loop. How many key.
<?php
class XML {
protected $pointer;
public $degerler=array();
function loadString($string){
$this->pointer = simplexml_load_string($string);
return $this->pointer;
}
function loadFile($file){
$this->pointer = simplexml_load_file($file);
return $this->pointer;
}
function getname(){
return $this->pointer->getName();
}
function child(){
return $this->pointer->children();
}
function att(){
return $this->pointer->attributes();
}
function toArray(){
foreach ($this->child() as $sq){
$this->degerler[$this->getname()][$sq->getname()][][] = $sq; // How many key
}
return;
}
}
?>
[#16] Mark Omohundro, ajamyajax.com [2008-11-04 10:33:09]
How about a recursive function to reduce the xml hard-coding in your apps? Here is my simple listing routine as an example:
<?php
function list_xml($str) {
$root = simplexml_load_string($str);
list_node($root);
}
function list_node($node) {
foreach ($node as $element) {
echo $element. "\n";
if ($element->children()) {
echo "<br/>";
list_node($element);
}
}
}
?>
[#17] javalc6 at gmail dot com [2008-10-18 06:25:57]
I wanted to convert an array containing strings and other arrays of the same type into a simplexml object.
Here is the code of the function array2xml that I've developed to perform this conversion. Please note that this code is simple without any checks.
<?php
function array2xml($array, $tag) {
function ia2xml($array) {
$xml="";
foreach ($array as $key=>$value) {
if (is_array($value)) {
$xml.="<$key>".ia2xml($value)."</$key>";
} else {
$xml.="<$key>".$value."</$key>";
}
}
return $xml;
}
return simplexml_load_string("<$tag>".ia2xml($array)."</$tag>");
}
$test['type']='lunch';
$test['time']='12:30';
$test['menu']=array('entree'=>'salad', 'maincourse'=>'steak');
echo array2xml($test,"meal")->asXML();
?>
[#18] rowan dot collins at gmail dot com [2008-07-10 07:07:10]
There seems to be a lot of talk about SimpleXML having a "problem" with CDATA, and writing functions to rip it out, etc. I thought so too, at first, but it's actually behaving just fine under PHP 5.2.6
The key is noted above example #6 here:
http://uk2.php.net/manual/en/simplexml.examples.php
"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."
If a tag contains CDATA, SimpleXML remembers that fact, by representing it separately from the string content of the element. So some functions, including print_r(), might not show what you expect. But if you explicitly cast to a string, you get the whole content.
<?php
$xml = simplexml_load_string('<foo>Text1 & XML entities</foo>');
print_r($xml);
$xml2 = simplexml_load_string('<foo><![CDATA[Text2 & raw data]]></foo>');
print_r($xml2);
// Where's my CDATA?
// Let's try explicit casts
print_r( (string)$xml );
print_r( (string)$xml2 );
// Much better
?>
[#19] SmartD [2008-06-11 08:40:24]
A small 'n nice function to extract an XML and return it as an array. If there is a bug, please let me know here. I testet it for my purposes and it works.
<?php
public function extractXML($xml) {
if (!($xml->children())) {
return (string) $xml;
}
foreach ($xml->children() as $child) {
$name=$child->getName();
if (count($xml->$name)==1) {
$element[$name] = $this->extractXML($child);
} else {
$element[][$name] = $this->extractXML($child);
}
}
return $element;
}
// you can call it this way
$xml = false;
$xml = @simplexml_load_string($xmlstring);
// 1)
if ($xml) {
$array = extractXML($xml);
} else {
$array = false;
}
// 2)
if ($xml) {
$array[$xml->getName()] = extractXML($xml);
} else {
$array = false;
}
?>
[#20] nospam at qool dot com [2008-06-05 11:45:09]
simplexml doesn't appear to like long attributes. I have tried passing it a valid xhtml document but the url in the anchor tag was causing simplexml to generate an error.
[#21] kyle at codeincarnate dot com [2008-04-21 17:28:05]
A looked through a lot of the sample code for reading XML files with CDATA, but they didn't work out that well for me. However, I found that the following piece of code worked perfectly for reading through a file using lots of CDATA.
<?php
$article_string = file_get_contents($path);
$article_string = preg_replace_callback('/<!\[CDATA\[(.*)\]\]>/', 'filter_xml', $article_string);
$article_xml = simplexml_load_string($article_string);
function filter_xml($matches) {
return trim(htmlspecialchars($matches[1]));
}
?>
[#22] paulyg76 at NOSPAM dot gmail dot com [2008-02-18 18:39:04]
Be careful using nested SimpleXML objects in double quoted strings.
<?php
$xmlstring = '<root><node>123</node><foo><bar>456</bar></foo></root>';
$root = simplexml_load_string($xmlstring);
echo "Node is: $root->node"; // Works: Node is 123
echo "Bar is: $root->foo->bar"; // Doesn't work, outputs: Bar is: ->bar
// use curly brackets to fix
echo "Bar is: {$root->foo->bar}"; // Works: Bar is 456
?>
[#23] amir_abiri at ipcmedia dot com [2008-02-08 08:47:01]
It doesn't seem to be documented anywhere, but you can refer to an element "value" for the purpose of changing it like so:
<?php
$xml = simplexml_load_string('<root><number>1</number></root>');
echo $xml->asXml(). "\n\n";
$xml->number->{0} = $xml->number->{0} + 1;
echo $xml->asXml();
?>
echos:
<?phpxml version="1.0"?>
<root><number>1</number></root>
<?phpxml version="1.0"?>
<root><number>2</number></root>
However, this only works with a direct assignment, not with any of the other operators:
<?php
$xml = simplexml_load_string('<root><number>1</number></root>');
echo $xml->asXml(). "\n\n";
$xml->number->{0} += 1;
// Or:
$xml->number->{0}++;
echo $xml->asXml();
?>
Both of the above cases would result in:
<?phpxml version="1.0"?>
<root><number>1</number></root>
<?phpxml version="1.0"?>
<root><number>1<0/></number></root>
[#24] bojan [2008-02-04 04:38:34]
As was said before don't use var_dump() or print_r() to see SimpleXML object structure as they do not returns always what you expect.
Consider the following:
<?php
// data in xml
$xml_txt = '
<root>
<folder ID="65" active="1" permission="1"><![CDATA[aaaa]]></folder>
<folder ID="65" active="1" permission="1"><![CDATA[bbbb]]></folder>
</root>';
// load xml into SimpleXML object
$xml = simplexml_load_string($xml_txt, 'SimpleXMLElement', LIBXML_NOCDATA);//LIBXML_NOCDATA LIBXML_NOWARNING
// see object structure
print_r($xml);
// but...
foreach ($xml->folder as $value){
print_r($value);
}
?>
[#25] hattori at hanso dot com [2007-10-15 15:19:18]
Theres a problem with the below workaround when serializing fields containing html CDATA. For any other content type then HTML try to modfiy function parseCDATA.
Just add these lines before serializing.
This is also a workaround for this bug http://bugs.php.net/bug.php?id=42001
<?PHP
if(strpos($content, '<![CDATA[')) {
function parseCDATA($data) {
return htmlentities($data[1]);
}
$content = preg_replace_callback(
'#<!\[CDATA\[(.*)\]\]>#',
'parseCDATA',
str_replace("\n", " ", $content)
);
}
?>
[#26] hattori at hanso dot com [2007-09-17 02:15:12]
If you want to serialize and unserialize SimpleXMLElement objects for caching, you need to transform the SimpleXMLElement object into a standard class object before unserializing.
This is only if you want to cache converted data, the functionallity of the SimpleXMLElement will not be held.
$content = '<SomeXML....'
$serialized = str_replace(
array('O:16:"SimpleXMLElement":0:{}', 'O:16:"SimpleXMLElement":'),
array('s:0:"";', 'O:8:"stdClass":'),
serialize(simplexml_load_string($content))
);
$unserialized = unserialize($serialized);
[#27] nbijnens at servs dot eu [2007-09-10 05:17:16]
Please note that not all LIBXML options are supported with the options argument.
For instance LIBXML_XINCLUDE does not work. But there is however a work around:
<?php
$xml = new DOMDocument();
$xml->loadXML ($XMLString);
$xml->xinclude();
$xml = simplexml_import_dom($xml);
?>
[#28] Pedro [2007-07-06 01:28:57]
Attention:
simplexml_load_string has a problem with entities other than (<, >, &, " and ').
Use numeric character references instead!
[#29] youx_free_fr [2007-05-23 09:52:15]
While needing to add an xml subtree to an existing simplexml object, I noticed that simplexml_load_string fails with strings like
<emptynode></emptynode>
I needed to use dom instead of simplexml to bypass this problem and work with any kind of xml strings.
[#30] php at teamhirsch dot com [2007-04-24 14:46:45]
It's worth noting that in the example above, $xml->body will actually return an object of type SimpleXMLElement, not a string, e.g.
SimpleXMLElement Object (
[0] => this is the text in the body tag
)
If you want to get a string out of it you must explicitly cast it using (string) or double quotes, or pass $xml->body (or whatever attribute you want to access) to any function that returns a string, such as urldecode() or trim().
[#31] m dot ament at mailcity dot com [2007-03-06 06:51:25]
Warning:
The parsing of XML-data will stop when reaching character 0.
Please avoid this character in your XML-data.
[#32] mindpower [2007-01-30 03:03:43]
A simple extension that adds a method for retrieving a specific attribute:
<?php
class simple_xml_extended extends SimpleXMLElement
{
public function Attribute($name)
{
foreach($this->Attributes() as $key=>$val)
{
if($key == $name)
return (string)$val;
}
}
}
$xml = simplexml_load_string('
<xml>
<dog type="poodle" owner="Mrs Smith">Rover</dog>
</xml>', 'simple_xml_extended');
echo $xml->dog->Attribute('type');
?>
outputs 'poodle'
I prefer to use this technique rather than typecasting attributes.
[#33] h [2006-11-15 10:44:58]
seems like simplexml has a line-length restriction - fails if a largeish XML doc with no linebreaks is passed as a string or file.
h
[#34] roy dot walter at nospam dot brookhouse dot co dot uk [2006-10-16 09:15:08]
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.
<?php
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());
?>
[#35] paul at santasoft dot com [2006-07-25 08:22:26]
If you have PHP > 5.1 and LibXML > 2.6, use this function call to have simplexml convert CDATA into plain text.
simplexml_load_string($xmlstring, 'SimpleXMLElement', LIBXML_NOCDATA);
Too bad, so sad with PHP < 5.1.
[#36] lists at cyberlot dot net [2005-09-07 12:51:29]
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>
[#37] Maciek Ruckgaber <maciekrb at gmai dot com> [2005-06-07 17:07:48]
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:
<?php
$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:
<?php
$xml = simplexml_load_string($xmlstr);
echo $xml; // this will echo 2328 (string)
?>
[#38] igor kraus [2005-01-07 10:37:24]
A simple way to merge two SimpleXML objects.
<?php
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('
$cities = array( "Austin" , "Novato" , "Seattle" );
wddx_add_vars ( $packet_id , "cities" );
$packet = wddx_packet_end ( $packet_id );
echo $packet ;
?>
This example will produce:
<wddxPacket version='1.0'><header comment='PHP'/><data><struct> <var name='pi'><number>3.1415926</number></var><var name='cities'> <array length='3'><string>Austin</string><string>Novato</string> <string>Seattle</string></array></var></struct></data></wddxPacket>
Note:
If you want to serialize non-ASCII characters you have to convert your data to UTF-8 first (see utf8_encode() and iconv() ).