【问题标题】:php simpleXMLElement to array: null valuephp simpleXMLElement 到数组:空值
【发布时间】:2013-02-12 02:15:32
【问题描述】:

我有以下 XML:

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

我想把它作为一个数组变量。因此我用$xml = simplexml_load_file() 阅读它。我知道将 simpleXMLElement 转换为关联数组的最简单方法是使用:json_decode(json_encode((array) $xml),1);

问题是我不想将email 键作为空数组,而是作为NULL 值。作为 SimpleXMLElement,它看起来像:

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

而在数组中它看起来像:

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

我想得到:

'email' => NULL

我想到的唯一方法是遍历所有元素并将空数组替换为空值。问题是我的 XML 更大(以上只是为了解释问题)并且我必须迭代很多 XML 元素(这将是手动工作 - 我正在寻找自动的东西)。也许我在其中一个函数中遗漏了一些选项......或者也许还有另一个技巧可以做到这一点?

【问题讨论】:

  • 问题是,email 不为空。它是空的。要让它为空,xml 应该是 &lt;email /&gt;
  • @webnoob 没错! :) 但不幸的是,你仍然不会得到预期的NULL
  • @hek2mgl - 好吧,我认为它会 :(。好吧,另一个想法。将 XML 加载到字符串中,使用一些正则表达式去除没有值的标签,然后解析它。如果它们不存在,您可以将它们视为 null。
  • @webnoob 当 xml 增长时会变得混乱。您还必须更改每种 xml 格式的正则表达式。我目前正在考虑使用 SAX 解析器。这将从 php.ini 中的 foreach 循环中保存 OP。循环将在扩展的 C 代码中完成。它也应该比 json_decode/json_encode 方法更快
  • 嗯,好点。虽然,我必须向 OP 询问为什么 null 值如此重要的问题。为什么不检查""。甚至可以有一个辅助函数来为你做这件事......

标签: php xml associative-array


【解决方案1】:

我无法添加评论,但我认为这对你有用,它应该比正则表达式或循环更快:

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

JSON 中的空数组由“[]”表示。有时数组被解析为对象,在这种情况下(或作为后备)您也可以替换“:{}”。

【讨论】:

  • 所以我想要的总体结果是:json_decode(str_replace(':[]',':null',json_encode($array))) - 听起来不错
  • 应该是 "email":{} 而不是 "email":[] 但无论如何感谢您的想法
【解决方案2】:

检查性能 str_replace 与递归循环

  • 迭代次数:100000
  • XML 长度:4114 字节
  • 初始化脚本时间:~1.2264486691986E-6 秒
  • JSON 编码/解码时间:~9.8956169957496E-5 秒
  • str_replace平均时间:0.00010692856433176
  • 递归循环平均时间:0.00011844366600813

str_replace 在 ~0.00001 秒内快速。在许多调用中,差异会很明显

【讨论】:

    【解决方案3】:

    一个空的SimpleXMLElement object 将被转换为一个空数组。您可以通过从 SimpleXMLElement 扩展并实现 JsonSerializable interface 并将其强制转换为 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;
        }
    }
    

    然后告诉simplexml_load_string返回一个JsonXMLElement类的对象

    $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"
    }
    */
    

    信用:hakre

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-02-14
      • 1970-01-01
      • 2019-02-18
      • 1970-01-01
      • 2012-02-03
      • 2013-07-26
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多