通过复杂的 SimpleXMLElement 进行复杂循环
Complex Loop through a complex SimpleXMLElement
我需要从 XML 中保存一些值。
第一步 - 我得到了结构:
$xml = $dom_xml->saveXML();
$xml_ = new \SimpleXMLElement($xml);
dd($xml_);
这里TextFrame
有8个数组。他们每个人都有PathPointType
,其中有
还有 4 个数组,每个数组有 3 个属性。我需要每个 TextFrame
的这些属性。
我可以获得,例如,Anchor
这样做的价值:
$res = $xml_
->Spread
->TextFrame
->Properties
->PathGeometry
->GeometryPathType
->PathPointArray
->PathPointType
->attributes();
dd($res['Anchor']);
(顺便说一句:还有更漂亮的方法吗?)
但问题是 - 如何遍历所有数组并分别为每个数组保存值?
我假设这里必须是一个多维 foreach
循环和 for
循环?
还是使用 DOMDocument
更好?
看起来好像您是从 DOMDocument 开始的(因为您正在使用 $dom_xml->saveXML()
生成 XML),继续使用它可能更容易,并且它也有一些简单的获取详细信息的功能。
使用getElementsByTagName()
可以让您从起点获取具有特定标签名称的元素列表,因此从$dom_xml
开始,获取所有<TextFrame>
元素。然后 foreach()
遍历此列表并使用此元素作为起点,使用 getElementsByTagName("PathPointType")
获取嵌套的 <PathPointType>
元素。此时,您可以对 <PathPointType>
元素中需要的每个属性使用 getAttribute("Anchor")
...
$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;
作为 的补充,我想我会展示使用 SimpleXML 时相同循环的外观。
首先,请注意,如果您出于任何原因想要在 DOM 和 SimpleXML 之间切换,则无需将 XML 转换为字符串并返回,您可以使用 simplexml_import_dom 只是换出接口:
$sxml = simplexml_import_dom($dom_xml);
接下来我们需要 TextFrame
个元素;我们可以显式地遍历结构,就像你之前做的那样:
$textFrames = $sxml->Spread->TextFrame;
或者我们可以使用 XPath 在当前节点中搜索匹配的标签名称(.
是当前元素,//
表示 "any descendant":
$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;
}
我需要从 XML 中保存一些值。
第一步 - 我得到了结构:
$xml = $dom_xml->saveXML();
$xml_ = new \SimpleXMLElement($xml);
dd($xml_);
这里TextFrame
有8个数组。他们每个人都有PathPointType
,其中有
还有 4 个数组,每个数组有 3 个属性。我需要每个 TextFrame
的这些属性。
我可以获得,例如,Anchor
这样做的价值:
$res = $xml_
->Spread
->TextFrame
->Properties
->PathGeometry
->GeometryPathType
->PathPointArray
->PathPointType
->attributes();
dd($res['Anchor']);
(顺便说一句:还有更漂亮的方法吗?)
但问题是 - 如何遍历所有数组并分别为每个数组保存值?
我假设这里必须是一个多维 foreach
循环和 for
循环?
还是使用 DOMDocument
更好?
看起来好像您是从 DOMDocument 开始的(因为您正在使用 $dom_xml->saveXML()
生成 XML),继续使用它可能更容易,并且它也有一些简单的获取详细信息的功能。
使用getElementsByTagName()
可以让您从起点获取具有特定标签名称的元素列表,因此从$dom_xml
开始,获取所有<TextFrame>
元素。然后 foreach()
遍历此列表并使用此元素作为起点,使用 getElementsByTagName("PathPointType")
获取嵌套的 <PathPointType>
元素。此时,您可以对 <PathPointType>
元素中需要的每个属性使用 getAttribute("Anchor")
...
$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;
作为
首先,请注意,如果您出于任何原因想要在 DOM 和 SimpleXML 之间切换,则无需将 XML 转换为字符串并返回,您可以使用 simplexml_import_dom 只是换出接口:
$sxml = simplexml_import_dom($dom_xml);
接下来我们需要 TextFrame
个元素;我们可以显式地遍历结构,就像你之前做的那样:
$textFrames = $sxml->Spread->TextFrame;
或者我们可以使用 XPath 在当前节点中搜索匹配的标签名称(.
是当前元素,//
表示 "any descendant":
$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;
}