To correctly extract a value from a CDATA just make sure you cast the SimpleXML Element to a string value by using the cast operator:
<?php
$xml = '<?xml version="1.0" encoding="UTF-8" ?>
<rss>
<channel>
<item>
<title><![CDATA[Tom & Jerry]]></title>
</item>
</channel>
</rss>';
$xml = simplexml_load_string($xml);
// echo does the casting for you
echo $xml->channel->item->title;
// but vardump (or print_r) not!
var_dump($xml->channel->item->title);
// so cast the SimpleXML Element to 'string' solve this issue
var_dump((string) $xml->channel->item->title);
?>
Above will output:
Tom & Jerry
object(SimpleXMLElement)#4 (0) {}
string(11) "Tom & Jerry"
simplexml_load_file
(PHP 5)
simplexml_load_file — Interpreta un fichero XML en un objeto
Descripción
Esta función convertirá un documento XML válido en un fichero especificado por filename en un objeto de clase SimpleXMLElement. Si ocurre algún error durante el acceso o la interpretación, la función devolverá FALSE.
Puedes utilizar el parámetro opcional class_name de forma que simplexml_load_file() devolverá un objeto de la clase especificada. Esa clase deberí debe extender la clase SimpleXMLElement.
Desde PHP 5.1.0 y Libxml 2.6.0, también puedes usar el parámetro options para especificar parámetros de Libxml adicionales.
Note: Libxml 2 decodifica la URI, así que si quieres pasar e.j. b&c como parámetro URI a, tienes que llamar simplexml_load_file(rawurlencode('http://example.com/?a=' . urlencode('b&c'))). A partir de PHP 5.1.0 ya no es necesario hacer esto porque PHP lo hará automáticamente.
Example #1 Interpretar un documento XML
<?php
// El fichero test.xml contiene un documento XML con el elemento raiz
// y almenos un elemento /[root]/title.
if (file_exists('test.xml')) {
$xml = simplexml_load_file('test.xml');
var_dump($xml);
} else {
exit('Error al abrir test.xml.');
}
?>
Este script mostrará, si tiene éxito:
SimpleXMLElement Object ( [title] => Example Title ... )
A partir de aquí, puedes puedes acceder al nodo title mediante $xml->title y a cualquier otro elemento.
Vea también: simplexml_load_string()
simplexml_load_file
20-Feb-2007 11:08
10-Dec-2006 11:35
In regards to Anonymous on 7th April 2006
There is a way to get back HTML tags. For example:
<?xml version="1.0"?>
<intro>
Welcome to <b>Example.com</b>!
</intro>
<?php
// I use @ so that it doesn't spit out content of my XML in an error message if the load fails. The content could be passwords so this is just to be safe.
$xml = @simplexml_load_file('content_intro.xml');
if ($xml) {
// asXML() will keep the HTML tags but it will also keep the parent tag <intro> so I strip them out with a str_replace. You could obviously also use a preg_replace if you have lots of tags.
$intro = str_replace(array('<intro>', '</intro>'), '', $xml->asXML());
} else {
$error = "Could not load intro XML file.";
}
?>
With this method someone can change the intro in content_intro.xml and ensure that the HTML is well formed and not ruin the whole site design.
07-Apr-2006 06:21
What has been found when using the script is that simplexml_load_file() will remove any HTML formating inside the XML file, and will also only load so many layers deep. If your XML file is to deap, it will return a boolean false.
09-Mar-2006 02:21
Be careful if you are using simplexml data directly to feed your MySQL database using MYSQLi and bind parameters.
The data coming from simplexml are Objects and the bind parameters functions of MySQLi do NOT like that! (it causes some memory leak and can crash Apache/PHP)
In order to do this properly you MUST cast your values to the right type (string, integer...) before passing them to the binding methods of MySQLi.
I did not find that in the documentation and it caused me a lot of headache.
06-Feb-2006 05:26
Sorry there's a mistake in the previous function :
<?php
function &getXMLnode($object, $param) {
foreach($object as $key => $value) {
if(isset($object->$key->$param)) {
return $object->$key->$param;
}
if(is_object($object->$key)&&!empty($object->$key)) {
$new_obj = $object->$key;
// Must use getXMLnode function there (recursive)
$ret = getXMLnode($new_obj, $param);
}
}
if($ret) return (string) $ret;
return false;
}
?>
03-Feb-2006 06:11
So it seems SimpleXML doesn't support CDATA... I bashed together this little regex function to sort out the CDATA before trying to parse XML with the likes of simplexml_load_file / simplexml_load_string. Hope it might help somebody and would be very interested to hear of better solutions. (Other than *not* using SimpleXML of course! ;)
It looks for any <![CDATA [Text and HTML etc in here]]> elements, htmlspecialchar()'s the encapsulated data and then strips the "<![CDATA [" and "]]>" tags out.
<?php
function simplexml_unCDATAise($xml) {
$new_xml = NULL;
preg_match_all("/\<\!\[CDATA \[(.*)\]\]\>/U", $xml, $args);
if (is_array($args)) {
if (isset($args[0]) && isset($args[1])) {
$new_xml = $xml;
for ($i=0; $i<count($args[0]); $i++) {
$old_text = $args[0][$i];
$new_text = htmlspecialchars($args[1][$i]);
$new_xml = str_replace($old_text, $new_text, $new_xml);
}
}
}
return $new_xml;
}
//Usage:
$xml = 'Your XML with CDATA...';
$xml = simplexml_unCDATAise($xml);
$xml_object = simplexml_load_string($xml);
?>
03-Feb-2006 12:37
Suppose you have loaded a XML file into $simpleXML_obj.
The structure is like below :
SimpleXMLElement Object
(
[node1] => SimpleXMLElement Object
(
[subnode1] => value1
[subnode2] => value2
[subnode3] => value3
)
[node2] => SimpleXMLElement Object
(
[subnode4] => value4
[subnode5] => value5
[subnode6] => value6
)
)
When searching a specific node in the object, you may use this function :
<?php
function &getXMLnode($object, $param) {
foreach($object as $key => $value) {
if(isset($object->$key->$param)) {
return $object->$key->$param;
}
if(is_object($object->$key)&&!empty($object->$key)) {
$new_obj = $object->$key;
$ret = getCfgParam($new_obj, $param);
}
}
if($ret) return (string) $ret;
return false;
}
?>
So if you want to get subnode4 value you may use this function like this :
<?php
$result = getXMLnode($simpleXML_obj, 'subnode4');
echo $result;
?>
It display "value4"
12-Jan-2006 03:46
simplexml_load_file creates an xml-tree with values that are UTF-8 strings. To convert them to the more common encoding
ISO-8859-1 (Latin-1), use "utf8_decode".
30-Sep-2005 05:52
Micro$oft Word uses non-standard characters and they create problems in using simplexml_load_file.
Many systems include non-standard Word character in their implementation of ISO-8859-1. So an XML document containing that characters can appear well-formed (i.e.) to many browsers. But if you try to load this kind of documents with simplexml_load_file you'll have a little bunch of troubles..
I believe that this is exactly the same question discussed in htmlentites. Following notes to htmlentitles are interesting here too (given in the reverse order, to grant the history):
http://it.php.net/manual/en/function.htmlentities.php#26379
http://it.php.net/manual/en/function.htmlentities.php#41152
http://it.php.net/manual/en/function.htmlentities.php#42126
http://it.php.net/manual/en/function.htmlentities.php#42511
12-Sep-2005 08:06
If the property of an object is empty the array is not created. Here is a version object2array that transfers properly.
<?php
function object2array($object)
{
$return = NULL;
if(is_array($object))
{
foreach($object as $key => $value)
$return[$key] = object2array($value);
}
else
{
$var = get_object_vars($object);
if($var)
{
foreach($var as $key => $value)
$return[$key] = ($key && !$value) ? NULL : object2array($value);
}
else return $object;
}
return $return;
}
?>
