php simpleXMLElement to array: null value

回眸只為那壹抹淺笑 提交于 2019-12-09 09:55:00

问题


I've got following XML:

<account>
    <id>123</id>
    <email></email>
    <status>ACTIVE</status>
</account>

I want to have it as an array variable. Therefore I read it with $xml = simplexml_load_file(). The simplest way to convert simpleXMLElement to an associative array I know is to grind it with: json_decode(json_encode((array) $xml),1);

The problem is that I don't want to get the email key as an empty array, but rather as a NULL value. As SimpleXMLElement, it looks like:

public 'email' => 
    object(SimpleXMLElement)[205]

whereas in array it looks like:

'email' => 
    array (size=0)
      empty

I'd like to get:

'email' => NULL

The only way to achieve this I thought of is iterate through all elements and replace empty array with null value. The problem is that my XML is way bigger (above is just to explain the problem) and I'd have to iterate a lot of XML elements (and this would be manual work - I'm looking for something automatic). Maybe I'm missing some options in one of the functions... or maybe there's another trick to do this?


回答1:


I cannot add a comment, but I think this will work for you, it should be faster then a regex or a loop:

//after you json_encode, before you decode
$str = str_replace(':[]',':null',json_encode($array));

An empty array in JSON is represented by "[]". Sometimes the arrays are parsed as objects, in that case (or as a fallback) you can replace ":{}" too.




回答2:


An empty SimpleXMLElement object will be casted to an empty array. You can change this by by extending from SimpleXMLElement and implementing the JsonSerializable interface and casting an it to null.

/**
 * Class JsonXMLElement
 */
class JsonXMLElement extends SimpleXMLElement implements JsonSerializable
{

    /**
     * Specify data which should be serialized to JSON
     *
     * @return mixed data which can be serialized by json_encode.
     */
    public function jsonSerialize()
    {
        $array = array();

        // json encode attributes if any.
        if ($attributes = $this->attributes()) {
            $array['@attributes'] = iterator_to_array($attributes);
        }

        // json encode child elements if any. group on duplicate names as an array.
        foreach ($this as $name => $element) {
            if (isset($array[$name])) {
                if (!is_array($array[$name])) {
                    $array[$name] = [$array[$name]];
                }
                $array[$name][] = $element;
            } else {
                $array[$name] = $element;
            }
        }

        // json encode non-whitespace element simplexml text values.
        $text = trim($this);
        if (strlen($text)) {
            if ($array) {
                $array['@text'] = $text;
            } else {
                $array = $text;
            }
        }

        // return empty elements as NULL (self-closing or empty tags)
        if (!$array) {
            $array = NULL;
        }

        return $array;
    }
}

Then tell simplexml_load_string to return an object of JsonXMLElement class

$xml = <<<XML
<account>
   <id>123</id>
   <email></email>
   <status>ACTIVE</status>
</account>
XML;

$obj = simplexml_load_string($xml, 'JsonXMLElement');

// print_r($obj);

print json_encode($obj, true);

/*
 * Output...
{
   "id": 123,
   "email": null,
   "status": "ACTIVE"
}
*/

Credit: hakre




回答3:


Check performance srt_replace vs recursive loop

  • Iterations: 100000
  • XML lenght: 4114 bytes
  • Init script time: ~1.2264486691986E-6 seconds
  • Json encode/decode time: ~9.8956169957496E-5 seconds
  • str_replace average time: 0.00010692856433176 seconds
  • recursive loop average time: 0.00011844366600813 seconds

The str_replace quickly on ~0.00001 seconds. The difference will be noticeable in many calls



来源:https://stackoverflow.com/questions/15092338/php-simplexmlelement-to-array-null-value

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!