通过复杂的SimpleXMLElement

时间:2019-02-17 16:09:09

标签: php arrays xml loops simplexml

我需要从XML保存一些值。

第一步-我得到了结构:

 $xml = $dom_xml->saveXML();
 $xml_ = new \SimpleXMLElement($xml);
 dd($xml_);

这里TextFrame有8个数组。每个人都有PathPointType,其中有 还有4个数组,每个数组具有3个属性。我需要每个TextFrame的这些属性。

enter image description here

例如,我可以获得Anchor的值:

$res = $xml_
        ->Spread
        ->TextFrame
        ->Properties
        ->PathGeometry
        ->GeometryPathType
        ->PathPointArray
        ->PathPointType
        ->attributes();
    dd($res['Anchor']);

(顺便说一句:还有其他更漂亮的方式来获得它吗?)

但是问题是-如何遍历所有数组并分别为每个数组保存值?

我假设这里必须是一个多维foreach循环和for循环吗?

还是最好使用DOMDocument来实现?

2 个答案:

答案 0 :(得分:2)

好像您从DOMDocument开始一样(使用$dom_xml->saveXML()来生成XML),继续使用它可能会更容易,并且它还具有一些简单的功能来获取您的详细信息后。

使用getElementsByTagName()可让您从起点获取具有特定标签名称的元素列表,因此从$dom_xml开始,获取所有<TextFrame>元素。然后在该列表上的foreach()上并将该元素用作起点,使用getElementsByTagName("PathPointType")获取嵌套的<PathPointType>元素。此时,您可以对getAttribute("Anchor")元素中需要的每个属性使用<PathPointType> ...

$textFrames = $dom_xml->getElementsByTagName("TextFrame");

foreach ( $textFrames as $frame )   {
    $pathPointTypes = $frame->getElementsByTagName("PathPointType");
    foreach ( $pathPointTypes as $type )    {
        echo $type->getAttribute("Anchor").PHP_EOL;
    }
}

修改

您可以扩展代码以构建框架数组,然后构建其中的锚点。这段代码还将锚点存储在一个关联数组中,这样,如果您添加其他属性,则可以在此处添加它们(如果不需要另一层细节,则可以将其删除)...

$frames =[];
foreach ( $textFrames as $frame )   {
    $anchors = [];
    $pathPointTypes = $frame->getElementsByTagName("PathPointType");
    foreach ( $pathPointTypes as $type )    {
        $anchors[] = ['Anchor' => $type->getAttribute("Anchor")];
    }
    $frames[] = $anchors;
}

此外,如果您有某种方法可以识别框架,也可以在该级别创建一个关联数组...

$frames[$frameID] = $anchors;

答案 1 :(得分:2)

作为the existing answer from Nigel Ren的补充,我认为我将展示SimpleXML的相同循环。

首先,请注意,如果您出于任何原因要在DOM和SimpleXML之间切换,则不需要将XML转换为字符串,而是可以使用simplexml_import_dom来交换接口:

 $sxml = simplexml_import_dom($dom_xml);

接下来,我们需要TextFrame元素;我们可以像以前一样显式地遍历结构:

$textFrames = $sxml->Spread->TextFrame;

或者我们可以使用XPath在当前节点内搜索匹配的标记名(.是当前元素,而//的意思是“任何后代”:

$textFrames = $sxml->xpath('.//TextFrame');

第一个将为您提供一个SimpleXMLElement对象,第二个将为您提供数组,但是无论哪种方式,您都可以使用foreach来进行匹配。

这一次,我们绝对希望XPath表达式获得PathPointType节点,以避免所有我们不感兴趣的级别上的所有嵌套循环:

foreach ( $textFrames as $frame )   {
    $pathPointTypes = $frame->xpath('.//PathPointType');
    foreach ( $pathPointTypes as $type )    {
        echo $type['Anchor'] . PHP_EOL;
    }
}

请注意,您无需致电$type->attributes();除非您要处理名称空间,否则获取属性所需的全部就是$node['AttributeName']。请注意,尽管SimpleXML中的属性是对象,所以您经常需要使用(string)$node['AttributeName']强制它们为字符串。

以最后一个例子为例,您可能会遇到类似这样的情况:

$frames = [];
foreach ( $sxml->Spread->TextFrame as $frame )   {
    $anchors = [];
    $pathPointTypes = $frame->xpath('.//PathPointType');
    foreach ( $pathPointTypes as $type )    {
        $anchors[] = ['Anchor' => (string)$type['Anchor']];
    }
    $frames[] = $anchors;
}