Hướng dẫn xml php extension

  • Introduction
  • Installing/Configuring
    • Requirements
    • Installation
    • Runtime Configuration
    • Resource Types
  • Predefined Constants
  • Examples
    • Basic SimpleXML usage
    • Dealing with XML errors
  • SimpleXMLElement — The SimpleXMLElement class
    • 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::count — Counts the children of an element
    • 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::saveXML — Alias of SimpleXMLElement::asXML
    • SimpleXMLElement::__toString — Returns the string content
    • SimpleXMLElement::xpath — Runs XPath query on XML data
  • SimpleXMLIterator — The SimpleXMLIterator class
    • SimpleXMLIterator::current — Returns the current element
    • SimpleXMLIterator::getChildren — Returns the sub-elements of the current element
    • SimpleXMLIterator::hasChildren — Checks whether the current element has sub elements
    • SimpleXMLIterator::key — Return current key
    • SimpleXMLIterator::next — Move to next element
    • SimpleXMLIterator::rewind — Rewind to the first element
    • SimpleXMLIterator::valid — Check whether the current element is valid
  • SimpleXML Functions
    • 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

soloman at textgrid dot com

11 years ago

Three line xml2array:

$xml

= simplexml_load_string($xmlstring);
$json = json_encode($xml);
$array = json_decode($json,TRUE);?>

Ta da!

whyme

9 years ago

Simple means simple.  If you know the structure and just want the value of a tag:

$xml = simplexml_load_file($xmlfile);
print
$xml->City->Street->Address->HouseColor;
?>

Warning, numbers can come out as strings, empty elements like come out as array(0)

xaviered at gmail dot com

10 years ago

Here is a recursive function that will convert a given SimpleXMLElement object into an array, preserving namespaces and attributes.

function xmlObjToArr($obj) {
       
$namespace = $obj->getDocNamespaces(true);
       
$namespace[NULL] = NULL; $children = array();
       
$attributes = array();
       
$name = strtolower((string)$obj->getName()); $text = trim((string)$obj);
        if(
strlen($text) <= 0 ) {
           
$text = NULL;
        }
// get info for all namespaces
       
if(is_object($obj)) {
            foreach(
$namespace as $ns=>$nsUrl ) {
               
// atributes
               
$objAttributes = $obj->attributes($ns, true);
                foreach(
$objAttributes as $attributeName => $attributeValue ) {
                   
$attribName = strtolower(trim((string)$attributeName));
                   
$attribVal = trim((string)$attributeValue);
                    if (!empty(
$ns)) {
                       
$attribName = $ns . ':' . $attribName;
                    }
                   
$attributes[$attribName] = $attribVal;
                }
// children
               
$objChildren = $obj->children($ns, true);
                foreach(
$objChildren as $childName=>$child ) {
                   
$childName = strtolower((string)$childName);
                    if( !empty(
$ns) ) {
                       
$childName = $ns.':'.$childName;
                    }
                   
$children[$childName][] = xmlObjToArr($child);
                }
            }
        }

                return array(

'name'=>$name,
           
'text'=>$text,
           
'attributes'=>$attributes,
           
'children'=>$children
       
);
    }
?>

xananax at yelostudio dot com

11 years ago

None of the XML2Array functions that I found satisfied me completely; Their results did not always fit the project I was working on, and I found none that would account for repeating XML elements (such as
)
So I rolled out my own; hope it helps someone.
/**
* Converts a simpleXML element into an array. Preserves attributes.

* You can choose to get your elements either flattened, or stored in a custom
* index that you define.

* For example, for a given element
*
*
*

*

* if you choose to flatten attributes, you would get:
*
* $array['field']['name'] = 'someName';
* $array['field']['type'] = 'someType';
*

* If you choose not to flatten, you get:
*
* $array['field']['@attributes']['name'] = 'someName';
*

*
__________________________________________________________

* Repeating fields are stored in indexed arrays. so for a markup such as:
*
*
*     a
*     b
*     c
* ...
*

* you array would be:
*
* $array['parent']['child'][0] = 'a';
* $array['parent']['child'][1] = 'b';
* ...And so on.
*

* @param simpleXMLElement    $xml            the XML to convert
* @param boolean|string    $attributesKey    if you pass TRUE, all values will be
*                                            stored under an '@attributes' index.
*                                            Note that you can also pass a string
*                                            to change the default index.

*                                            defaults to null.
* @param boolean|string    $childrenKey    if you pass TRUE, all values will be
*                                            stored under an '@children' index.
*                                            Note that you can also pass a string
*                                            to change the default index.

*                                            defaults to null.
* @param boolean|string    $valueKey        if you pass TRUE, all values will be
*                                            stored under an '@values' index. Note
*                                            that you can also pass a string to
*                                            change the default index.

*                                            defaults to null.
* @return array the resulting array.
*/
function simpleXMLToArray(SimpleXMLElement $xml,$attributesKey=null,$childrenKey=null,$valueKey=null){

    if(

$childrenKey && !is_string($childrenKey)){$childrenKey = '@children';}
    if(
$attributesKey && !is_string($attributesKey)){$attributesKey = '@attributes';}
    if(
$valueKey && !is_string($valueKey)){$valueKey = '@values';} $return = array();
   
$name = $xml->getName();
   
$_value = trim((string)$xml);
    if(!
strlen($_value)){$_value = null;};

    if(

$_value!==null){
        if(
$valueKey){$return[$valueKey] = $_value;}
        else{
$return = $_value;}
    }
$children = array();
   
$first = true;
    foreach(
$xml->children() as $elementName => $child){
       
$value = simpleXMLToArray($child,$attributesKey, $childrenKey,$valueKey);
        if(isset(
$children[$elementName])){
            if(
is_array($children[$elementName])){
                if(
$first){
                   
$temp = $children[$elementName];
                    unset(
$children[$elementName]);
                   
$children[$elementName][] = $temp;
                   
$first=false;
                }
               
$children[$elementName][] = $value;
            }else{
               
$children[$elementName] = array($children[$elementName],$value);
            }
        }
        else{
           
$children[$elementName] = $value;
        }
    }
    if(
$children){
        if(
$childrenKey){$return[$childrenKey] = $children;}
        else{
$return = array_merge($return,$children);}
    }
$attributes = array();
    foreach(
$xml->attributes() as $name=>$value){
       
$attributes[$name] = trim($value);
    }
    if(
$attributes){
        if(
$attributesKey){$return[$attributesKey] = $attributes;}
        else{
$return = array_merge($return, $attributes);}
    }

    return

$return;
}
?>

maikel at yuluma dot com

8 years ago

In reply to  soloman at textgrid dot com,

2 line XML2Array:

$xml = simplexml_load_string($file);
$array = (array)$xml;

emmanuel

12 years ago

dynamic sql in php using xml:

test.xml:


   
        SELECT * FROM USERS
        WHERE id = %d
        WHERE username = "%s";
   

index.php:
function callMe($param) {
   
$search = array('byUsername' => 'dynsql');

        if (isset(

$search[$param[1]])) {
        return
sprintf($param[2], $search[$param[1]]);
    }

        return

"";
}
$xml = simplexml_load_file("test.xml");
$string = $xml->statement->asXML();
$string = preg_replace_callback('/(.*?)<\/call>/', 'callMe', $string);
$node = simplexml_load_string($string);
echo
$node;
?>

obviously, this example can be improved [in your own code.]

streaver91 at gmail dot com

11 years ago

The BIGGEST differece between an XML and a PHP array is that in an XML file, the name of elements can be the same even if they are siblings, eg. "", while in an PHP array, the key of which must be different.

I think the array structure developed by svdmeer can fit for XML, and fits well.

here is an example array converted from an xml file:
array(
"@tag"=>"name",
"@attr"=>array(
    "id"=>"1","class"=>"2")
"@text"=>"some text",
)

or if it has childrens, that can be:

array(
"@tag"=>"name",
"@attr"=>array(
    "id"=>"1","class"=>"2")
"@items"=>array(
    0=>array(
        "@tag"=>"name","@text"=>"some text"
    )
)

Also, I wrote a function that can change that array back to XML.

function array2XML($arr,$root) {
$xml = new SimpleXMLElement("<{$root}>{$root}>");
$f = create_function('$f,$c,$a','
        foreach($a as $v) {
            if(isset($v["@text"])) {
                $ch = $c->addChild($v["@tag"],$v["@text"]);
            } else {
                $ch = $c->addChild($v["@tag"]);
                if(isset($v["@items"])) {
                    $f($f,$ch,$v["@items"]);
                }
            }
            if(isset($v["@attr"])) {
                foreach($v["@attr"] as $attr => $val) {
                    $ch->addAttribute($attr,$val);
                }
            }
        }'
);
$f($f,$xml,$arr);
return
$xml->asXML();
}
?>

mahmutta at gmail dot com

12 years ago

while using simple xml and get double or float int value from xml object for using math operations (+ * - / ) some errors happens on the operation, this is because of simple xml returns everythings to objects.
exmple;

$name

= "somestring";
$size = 11.45;
$xml = '

somestring
11.45
'
;$xmlget = simplexml_load_string($xml)

echo

$xml->size*2;    // 20  its false
// ($xml->size is an object (int)11 and  (45) )

// this is true

echo $size*2;            // 22.90
echo (float)$size*2;   // 22.90
?>

oscargodson at gmail dot com

13 years ago

To add to what others have said, you can't directly put a $_GET or $_POST value into a variable then into an attribute using SimpleXML. You must first convert it to an integer.

This will NOT work

      $page_id = $_GET['id'];
      echo
$xml->page[$page_id]
?>

You will get something like:
Notice: Trying to get property of non-object in /Applications/MAMP/htdocs/mysite/index.php on line 10

However, this WILL work and is much simpler then using (string) or other methods.
   $page_id = intval($_GET['id']);
   echo
$xml->page[$page_id]
?>

philipp at strazny dot com

11 years ago

Here's a quick way to dump the nodeValues from SimpleXML into an array using the path to each nodeValue as key. The paths are compatible with e.g. DOMXPath. I use this when I need to update values externally (i.e. in code that doesn't know about the underlying xml). Then I use DOMXPath to find the node containing the original value and update it.

function XMLToArrayFlat($xml, &$return, $path='', $root=false)
{
   
$children = array();
    if (
$xml instanceof SimpleXMLElement) {
       
$children = $xml->children();
        if (
$root){ // we're at root
           
$path .= '/'.$xml->getName();
        }
    }
    if (
count($children) == 0 ){
       
$return[$path] = (string)$xml;
        return;
    }
   
$seen=array();
    foreach (
$children as $child => $value) {
       
$childname = ($child instanceof SimpleXMLElement)?$child->getName():$child;
        if ( !isset(
$seen[$childname])){
           
$seen[$childname]=0;
        }
       
$seen[$childname]++;
       
XMLToArrayFlat($value, $return, $path.'/'.$child.'['.$seen[$childname].']');
    }
}
?>

Use like this:

$xml = simplexml_load_string(...some xml string...);
$xmlarray = array(); // this will hold the flattened data
XMLToArrayFlat($xml, $xmlarray, '', true);
?>

You can also pull multiple files in one array:

foreach($files as $file){
   
$xml = simplexml_load_file($file);
   
XMLToArrayFlat($xml, $xmlarray, $file.':', true);
}
?>
The respective filename/path is thus prefixed to each key.

kristof at viewranger dot com

11 years ago

If you tried to load an XML file with this, but the CDATA parts were not loaded for some reason, is because you should do it this way:

$xml = simplexml_load_file($this->filename, 'SimpleXMLElement', LIBXML_NOCDATA);

This converts CDATA to String in the returning object.

mail at kleineedv dot de

13 years ago

I had a problem with simplexml reading nodes from an xml file. It always return an SimpleXML-Object but not the text inside the node.

Example:


    123

Reading this xml into a variable called $xml and then doing the following
$myId = $xml->Id;
?>
Did not return 123 in $myId, but instead I got a SimpleXMLElement Object.

The solution is simple, when you know it. Use explicit string conversion.
$myId = (string)$xml->Id;
?>

charlie at blankcanvasstudios dot com

14 years ago

Optimizing aalaap at gmail dot com's php

function is_rss($feedxml) {
    @
$feed = simplexml_load_string($feedxml);

    return (

$feed->channel->item)?true:false;
}

function

is_atom($feedxml) {
    @
$feed = new SimpleXMLElement($feedxml);
    (
$feed->entry):true:false;
}
?>

dkrnl at yandex dot ru

8 years ago

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

/**
* Simple XML Reader
*
* @license Public Domain
* @author Dmitry Pyatkov(aka dkrnl) <>
* @url http://github.com/dkrnl/SimpleXMLReader
*/
class SimpleXMLReader extends XMLReader
{/**
     * Callbacks
     *
     * @var array
     */
   
protected $callback = array();/**
     * Add node callback
     *
     * @param  string   $name
     * @param  callback $callback
     * @param  integer  $nodeType
     * @return SimpleXMLReader
     */
   
public function registerCallback($name, $callback, $nodeType = XMLREADER::ELEMENT)
    {
        if (isset(
$this->callback[$nodeType][$name])) {
            throw new
Exception("Already exists callback $name($nodeType).");
        }
        if (!
is_callable($callback)) {
            throw new
Exception("Already exists parser callback $name($nodeType).");
        }
       
$this->callback[$nodeType][$name] = $callback;
        return
$this;
    }
/**
     * Remove node callback
     *
     * @param  string  $name
     * @param  integer $nodeType
     * @return SimpleXMLReader
     */
   
public function unRegisterCallback($name, $nodeType = XMLREADER::ELEMENT)
    {
        if (!isset(
$this->callback[$nodeType][$name])) {
            throw new
Exception("Unknow parser callback $name($nodeType).");
        }
        unset(
$this->callback[$nodeType][$name]);
        return
$this;
    }
/**
     * Run parser
     *
     * @return void
     */
   
public function parse()
    {
        if (empty(
$this->callback)) {
            throw new
Exception("Empty parser callback.");
        }
       
$continue = true;
        while (
$continue && $this->read()) {
            if (isset(
$this->callback[$this->nodeType][$this->name])) {
               
$continue = call_user_func($this->callback[$this->nodeType][$this->name], $this);
            }
        }
    }
/**
     * Run XPath query on current node
     *
     * @param  string $path
     * @param  string $version
     * @param  string $encoding
     * @return array(SimpleXMLElement)
     */
   
public function expandXpath($path, $version = "1.0", $encoding = "UTF-8")
    {
        return
$this->expandSimpleXml($version, $encoding)->xpath($path);
    }
/**
     * Expand current node to string
     *
     * @param  string $version
     * @param  string $encoding
     * @return SimpleXMLElement
     */
   
public function expandString($version = "1.0", $encoding = "UTF-8")
    {
        return
$this->expandSimpleXml($version, $encoding)->asXML();
    }
/**
     * Expand current node to SimpleXMLElement
     *
     * @param  string $version
     * @param  string $encoding
     * @param  string $className
     * @return SimpleXMLElement
     */
   
public function expandSimpleXml($version = "1.0", $encoding = "UTF-8", $className = null)
    {
       
$element = $this->expand();
       
$document = new DomDocument($version, $encoding);
       
$node = $document->importNode($element, true);
       
$document->appendChild($node);
        return
simplexml_import_dom($node, $className);
    }
/**
     * Expand current node to DomDocument
     *
     * @param  string $version
     * @param  string $encoding
     * @return DomDocument
     */
   
public function expandDomDocument($version = "1.0", $encoding = "UTF-8")
    {
       
$element = $this->expand();
       
$document = new DomDocument($version, $encoding);
       
$node = $document->importNode($element, true);
       
$document->appendChild($node);
        return
$document;
    }

}

?>

reibeltel at gmail dot com

6 months ago

I rewrite the function to convert xml object to array because my case is more simple:

function xmlObjToArr($obj) {

        $array = [];
    foreach($obj as $item){
        $row = [];
        foreach($item as $key => $val){
            $col = array(
                (string)$key => (string)$val
            );
            array_push($row,$col);

        }
        array_push($array,$row);
    }

    return $array;
}

aalaap at gmail dot com

14 years ago

Here are two quick and dirty functions that use SimpleXML to detect if a feed xml is RSS or ATOM:

function is_rss($feedxml) {
    @
$feed = new SimpleXMLElement($feedxml);

    if (

$feed->channel->item) {
        return
true;
    } else {
        return
false;
    }
}

function

is_atom($feedxml) {
    @
$feed = new SimpleXMLElement($feedxml);

    if (

$feed->entry) {
        return
true;
    } else {
        return
false;
    }
}
?>

The functions take in the full text feed (retrieved via cURL, for example) and return a true or a false based on the result.

thedoc8786 at gmail dot com

10 years ago

I know it is over-done, but the following is a super-short example of a XML to Array conversion function (recursive):

    function toArray(SimpleXMLElement $xml) {
       
$array = (array)$xml;

        foreach (

array_slice($array, 0) as $key => $value ) {
            if (
$value instanceof SimpleXMLElement ) {
               
$array[$key] = empty($value) ? NULL : toArray($value);
            }
        }
        return
$array;
    }

Anonymous

2 years ago

function array_to_xml( $array, $xml = null ) {
  if (
is_array( $array ) ) {
    foreach(
$array as $key => $value ) {
      if (
is_int( $key ) ) {
        if (
$key == 0 ) {
         
$node = $xml;
        } else {
         
$parent = $xml->xpath( ".." )[0];
         
$node = $parent->addChild( $xml->getName() );
        }
      } else {
       
$node = $xml->addChild( $key );
      }
     
array_to_xml( $value, $node );
    }
  } else {
   
$xml[0] = $array;
  }
}
$xml = new SimpleXMLElement("" );array_to_xml( $array, $xml );
echo
$xml->asXML();
?>

sherwinterunez at yahoo dot com

12 years ago

// Sherwin R. Terunez
//
// This is my own version of XML Object to Array
//
function amstore_xmlobj2array($obj, $level=0) {$items = array();

        if(!

is_object($obj)) return $items;$child = (array)$obj;

        if(

sizeof($child)>1) {
        foreach(
$child as $aa=>$bb) {
            if(
is_array($bb)) {
                foreach(
$bb as $ee=>$ff) {
                    if(!
is_object($ff)) {
                       
$items[$aa][$ee] = $ff;
                    } else
                    if(
get_class($ff)=='SimpleXMLElement') {
                       
$items[$aa][$ee] = amstore_xmlobj2array($ff,$level+1);
                    }
                }
            } else
            if(!
is_object($bb)) {
               
$items[$aa] = $bb;
            } else
            if(
get_class($bb)=='SimpleXMLElement') {
               
$items[$aa] = amstore_xmlobj2array($bb,$level+1);
            }
        }
    } else
    if(
sizeof($child)>0) {
        foreach(
$child as $aa=>$bb) {
            if(!
is_array($bb)&&!is_object($bb)) {
               
$items[$aa] = $bb;
            } else
            if(
is_object($bb)) {
               
$items[$aa] = amstore_xmlobj2array($bb,$level+1);
            } else {
                foreach(
$bb as $cc=>$dd) {
                    if(!
is_object($dd)) {
                       
$items[$obj->getName()][$cc] = $dd;
                    } else
                    if(
get_class($dd)=='SimpleXMLElement') {
                       
$items[$obj->getName()][$cc] = amstore_xmlobj2array($dd,$level+1);
                    }
                }
            }
        }
    }

    return

$items;
}
?>

Serge

7 years ago

XML data values should not contain "&" and that need to be replaced by html-entity "&"

You can use this code to replace lonely "&" to "&":

$sText = preg_replace('#&(?![a-z]{1,6};)#i', '&', $sText);
?>

This will replace just "&" into "&" but dont touches other html-entities like " ", "<" etc and, of course, "&".

P.S. In regexp max length is 6 becouse I found that is the maximum length of possible html entity using this code:
max(array_map('strlen', array_values(get_html_translation_table(HTML_ENTITIES, ENT_QUOTES | ENT_HTML5)))) - 2
?>
minus two is for first "&" and last ";" in an any html entity.

phil at dier dot us

11 years ago

Here's a function I came up with to convert an associative array to XML.  Works for multidimensional arrays as well.

function assocArrayToXML($root_element_name,$ar)
{
   
$xml = new SimpleXMLElement("<{$root_element_name}>{$root_element_name}>");
   
$f = create_function('$f,$c,$a','
            foreach($a as $k=>$v) {
                if(is_array($v)) {
                    $ch=$c->addChild($k);
                    $f($f,$ch,$v);
                } else {
                    $c->addChild($k,$v);
                }
            }'
);
   
$f($f,$xml,$ar);
    return
$xml->asXML();
}
?>

bxt at die-optimisten dot net

13 years ago

Addition to QLeap's post:
SimpleXML will return a reference to an object containing the node value and you can't use references in session variables as there is no feasible way to restore a reference to another variable.

This won't work too:
$val=$this->xml->node->attributes()->name;
echo $array[$val]; // will cause a warning because of the wrong index type.

You have to convert/cast to a String first:
echo $array[(string)$val];

This will work as expected, because converting will call the __toString() method. Therefor echo works too:
echo $val; // will display the name

QLeap

13 years ago

Storing SimpleXMLElement values in $_SESSION does not work. Saving the results as an object or individual elements of the object will result in the dreaded "Warning: session_start() [function.session-start]: Node no longer exists" error.

For example, this does not work:

    $xml  = new SimpleXMLElement($page);
    $country  = $xml->Response->Placemark->AddressDetails->Country->CountryNameCode;
    $_SESSION['country'] = $country;

This will work:

    $_SESSION['country'] = (string) $country;

gwhitescarver at yahoo dot com

14 years ago

Moving some code from a PHP 5.2.6 / Windows environment to a 5.2.0 / Linux environment, I somehow lost access to a plain text node within a SimpleXML Object.  On a var_dump of $xml_node, a [0] element was shown as the string '12'.  However, $xml_node[0] was evaluating NULL in 5.2.0.  You can see below the code change I made, pulling my data out of the raw XML with a regular expression.  Hope this is useful to someone.

//In some versions of PHP it seems we cannot access the [0] element of a SimpleXML Object.  Doesn't work in 5.2.0:
//$count = $xml_node[0];
//grab the raw XML:
$count = ($xml_node->asXML());
//pull out the number between the closing and opening brace of the xml:
$count = preg_replace('/.*>(\d*)<.*/', '$1', $count);

Laurent Vervisch

10 years ago

Here is an example of an easy mapping between xml and classes defined by user.

class XmlClass extends SimpleXMLElement
{
   
/**
     * Returns this object as an instance of the given class.
     */
   
public function asInstanceOf($class_name)
    {
       
// should check that class_name is validreturn simplexml_import_dom(dom_import_simplexml($this), $class_name);
    }

    public function

__call($name, array $arguments)
    {
        echo
"magic __call called for method $name on instance of ".get_class()."\n";// class could be mapped according $this->getName()
       
$class_name = 'Test';$instance = $this->asInstanceOf($class_name);
        return
call_user_func_array(array($instance, $name), $arguments);
    }
}

class

Test extends XmlClass
{
    public function
setValue($string)
    {
       
$this->{0} = $string;
    }
}
$xml = new XmlClass('');
$test = $xml->test->asInstanceOf('Test');
echo
get_class($xml->test), "\n";
echo
get_class($test), "\n";$test->setValue('value set directly by instance of Test');
echo (string)
$xml->test, "\n";
echo (string)
$test, "\n";$xml->test->setValue('value set by instance of XmlClass and magic __call');
echo (string)
$xml->test, "\n";
echo (string)
$test, "\n";
?>

XmlClass
Test
value set directly by instance of Test
value set directly by instance of Test
magic __call called for method setValue on instance of XmlClass
value set by instance of XmlClass and magic __call
value set by instance of XmlClass and magic __call

thedoc8786 at gmail dot com

10 years ago

FAIL! This function works better than the one I posted below:

    function toArray($xml) {
       
$array = json_decode(json_encode($xml), TRUE);

                foreach (

array_slice($array, 0) as $key => $value ) {
            if ( empty(
$value) ) $array[$key] = NULL;
            elseif (
is_array($value) ) $array[$key] = toArray($value);
        }

        return

$array;
    }

antoine dot rabanes at gmail dot com

12 years ago

if for some reasons you need the string value instead of the simpleXML Object you can cast the return value as a string.

exemple:

$all_api_call = simplexml_load_file($url);
$all_api = array();
$all_api = $all_api_call->result;
$list_all_api_name = array();
$i = 0;
foreach (
$all_api->children() as $funcky_function)
{
   
$string_tmp = (string )$funcky_function->function;
   
$list_all_api_name[$i++] = $putain;
}
?>

...

oleg at mastak dot fi

6 years ago

Two lines xml2array:

$xml

= simplexml_load_string($xmlstring);
$array = (array) $xml;?>

michael dot allen at emp dot shentel dot com

12 years ago

Here is a very robust SimpleXML parser.  Can be used to load files, strings, or DOM into SimpleXML, or can be used to perform the reverse when handed SimpleXML.

/**
* XMLParser Class File
*
* This class loads an XML document into a SimpleXMLElement that can
* be processed by the calling application.  This accepts xml strings,
* files, and DOM objects.  It can also perform the reverse, converting
* an SimpleXMLElement back into a string, file, or DOM object.
*/
class XMLParser {
   
/**
     * While parsing, parse the supplied XML document.
     *
     * Sets up a SimpleXMLElement object based on success of parsing
     * the XML document file.
     *
     * @param string $doc the xml document location path
     * @return object
     */
   
public static function loadFile($doc) {
        if (
file_exists($doc)) {
            return
simplexml_load_file($doc);
        } else {
            throw new
Exception ("Unable to load the xml file " .
                                
"using: \"$doc\"", E_USER_ERROR);
        }
    }
   
/**
     * While parsing, parse the supplied XML string.
     *
     * Sets up a SimpleXMLElement object based on success of parsing
     * the XML string.
     *
     * @param string $string the xml document string
     * @return object
     */
   
public static function loadString($string) {
        if (isset(
$string)) {
            return
simplexml_load_string($string);
        } else {
            throw new
Exception ("Unable to load the xml string " .
                                
"using: \"$string\"", E_USER_ERROR);
        }
    }
   
/**
     * While parsing, parse the supplied XML DOM node.
     *
     * Sets up a SimpleXMLElement object based on success of parsing
     * the XML DOM node.
     *
     * @param object $dom the xml DOM node
     * @return object
     */
   
public static function loadDOM($dom) {
        if (isset(
$dom)) {
            return
simplexml_import_dom($dom);
        } else {
            throw new
Exception ("Unable to load the xml DOM node " .
                                
"using: \"$dom\"", E_USER_ERROR);
        }
    }
   
/**
     * While parsing, parse the SimpleXMLElement.
     *
     * Sets up a XML file, string, or DOM object based on success of
     * parsing the XML DOM node.
     *
     * @param object $path the xml document location path
     * @param string $type the return type (string, file, dom)
     * @param object $simplexml the simple xml element
     * @return mixed
     */
   
public static function loadSXML($simplexml, $type, $path) {
        if (isset(
$simplexml) && isset($type)) {
        switch (
$type) {
            case
'string':
                return
$simplexml->asXML();
            break;
            case
'file':
                if (isset(
$path)) {
                    return
$simplexml->asXML($path);
                } else {
                    throw new
Exception ("Unable to create the XML file. Path is missing or" .
                                        
"is invalid: \"$path\"", E_USER_ERROR);
                }
            break;
            case
'dom':
                return
dom_import_simplexml($simplexml);
            break;
        }
        } else {
            throw new
Exception ("Unable to load the simple XML element " .
                                
"using: \"$simplexml\"", E_USER_ERROR);
        }
    }
}
?>

charles dot a dot dacosta at gmail dot com

5 years ago

I had to do the following to catch the fact that my simplexml_load_string call was not working right (it was returning empty objects).

$statistik = simplexml_load_string($record,"SimpleXMLElement",LIBXML_NSCLEAN,$ns,TRUE);

    if (($statistik === FALSE) or ($statistik === NULL) or empty($statistik))
    {
        echo "$ctr) STATISTIK ERROR---\n";
        var_dump($statistik);
        echo "\n\n";
        echo "Failed loading XML\n";
        foreach(libxml_get_errors() as $error)
        {
            echo "\n", $error->message;
        }
        die();
    }

before I put the check for "empty()" I was not catching the error.

Tim Adam Perez

8 years ago

XML to Array in a single line:
$array = (array) simplexml_load_string($xml);

Enjoy!

walter

13 years ago

Working fix for the infamous SimpleXML + memcache bug.

Improves code at http://tinyurl.com/bmoon-simplexml to actually work for arbitrary-depth structures.  (Because neither the function nor the json_decode(json_encode($obj)) hack listed there worked for me.)

There's probably some superfluous code in here that could be improved on -- but it works!

# convert a structure that may include objects to a pure
# array-based structure (that can be stored in memcache)
#  ... includes support for simplexml!
# (nb: may have problems with infinite recursive structs)
function enforce_array($obj) {
 
$array = (array)$obj;
  if(empty(
$array)) {
  
$array = '';
  }
  else {
   foreach(
$array as $key=>$value) {
    if(!
is_scalar($value)) {
     if(
is_a($value,'SimpleXMLElement')) {
     
$tmp = memcache_objects_to_array($value);
      if(!
is_array($tmp)) {
      
$tmp = ''.$value;
      }
     
$array[$key] = $tmp;
     }
     else {
     
$array[$key] = enforce_array($value);
     }
    }
    else {
    
$array[$key] = $value;
    }
   }
  }
  return
$array;
}
?>