无法将SimpleXMLElement序列化为Laravel作业

时间:2016-12-09 11:35:40

标签: php xml laravel xml-parsing simplexml

所以,在做了一些研究后,我成功地通过simplexml_load_string解析了我通过Guzzle得到的一些XML。问题是当我随后尝试使用以下代码为每个孩子分派一份工作时,我得到“不允许序列化'SimpleXMLElement'”错误。

$parent = $this->getParent($keywords);
foreach ($parent->children() as $child) {
    dispatch(new ProcessChild($event, true), $this->otherVar);
}

因此,为了尝试解决这个问题,我可以使用以下技巧将XML转换为数组;

json_decode(json_encode($child))

然而,虽然这确实意味着我可以将数据发送到新作业,但这确实意味着,据我所知,我无法访问@attributes。另一种选择将是以下几点;

// ParentJob
    $parent = $this->getParent($keywords);
    foreach ($parent->children() as $child) {
        dispatch(new ProcessChild($child->asXML, true), $this->otherVar);
    }

// ChildJob
    public function __construct($xml, $otherVar)
    {
        $this->xml = simplexml_load_string($xml);
        $this->otherVar = $otherVar;
    }
然而,由于某些原因我无法解决问题,它仍会在调度上抛出序列化错误,因为它只能发送原始XML而不是对象。

所以我的主要问题是在Laravel 5.3中将SimpleXMLObject和子SimpleXMLObject传递给作业的正确方法是什么?

(缺少循环遍历所有节点/属性并从中构建我自己的集合)

2 个答案:

答案 0 :(得分:0)

$xml = <<<'XML' <root> <x a="a1">1</x> <y b="b2">2</y> <z>3</z> </root> XML; $xe = simplexml_load_string($xml); $a = $xe->xpath('*'); $a = array_map(function ($e) { $item = (array) $e; $item['nodeName'] = $e->getName(); return $item; }, $a); // Now `$a` is an array (serializable object) echo json_encode($a, JSON_PRETTY_PRINT); 可以转换为数组,如下所示:

[
    {
        "@attributes": {
            "a": "a1"
        },
        "0": "1",
        "nodeName": "x"
    },
    {
        "@attributes": {
            "b": "b2"
        },
        "0": "2",
        "nodeName": "y"
    },
    {
        "0": "3",
        "nodeName": "z"
    }
]

输出

SimpleXmlElement

注意,您可以通过将其转换为字符串来获取$item['value'] = (string) $e; 的字符串值:

xpath

由于DOM方法支持相对XPath表达式,因此即使使用命名空间XML,星号也应该起作用。请考虑使用SimpleXML扩展程序,因为它比$xpath->registerNamespace('myprefix', 'http://example.com/ns'); $xpath->query('/root/myprefix:*'); 更灵活。特别是,它的DOMXPath类允许register名称空间并使用XPath表达式中注册的标识符:

{{1}}

答案 1 :(得分:0)

事实证明它不起作用的全部原因是由于我在子作业构造函数上使用了simplexml_load_string(),它在将作业实际序列化并推送到队列之前将其转换为simpleXMLElement。正确的方法是在handle方法上解析XML字符串,这是在从队列中提取作业进行实际处理之后完成的。

现在这个工作我可以简单地用$ child-&gt; asXML调度子作业,并在实际处理作业时解析它,这意味着我仍然可以使用所有漂亮的simpleXML功能,例如attributes()。

示例ParentJob:

foreach ($parent->children() as $child) {
    dispatch(new ProcessChild($event, true), $this->otherVar);
}

示例ChildJob:

protected $xml;
protected $otherVar;

public function __construct($xml, $otherVar)
{
    $this->xml = $xml;
    $this->otherVar = $otherVar;
}

public function handle()
{
    $child = simplexml_load_string($this->xml);
    $attributes = $child->attributes();
}