10

我有以下 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 元素(这将是手动工作 - 我正在寻找自动的东西)。也许我在其中一个功能中遗漏了一些选项......或者也许还有另一个技巧可以做到这一点?

4

3 回答 3

9

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

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

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

于 2013-02-27T09:27:14.400 回答
1

一个空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"
}
*/

信用:哈克雷

于 2018-07-13T14:13:01.613 回答
0

检查性能 str_replace 与递归循环

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

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

于 2016-10-27T10:12:35.910 回答