复杂循环通过复杂的SimpleXMLElement

问题描述 投票:1回答:2

我需要从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更好地实现它?

php arrays xml loops simplexml
2个回答
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;

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;
}
© www.soinside.com 2019 - 2024. All rights reserved.