提问人:pwbset 提问时间:11/17/2023 最后编辑:pwbset 更新时间:11/17/2023 访问量:45
PHP 从随机嵌套、随机输出的 XML 中获取数组值,然后获取与第一个值搜索相关的关联值
PHP get array value from randomly nested, randomly outputted XML and then get associated values related to first value search
问:
呸。PHP假人在这里对不起。在这里搜索了又搜索,但搜索 foo 不够好。我觉得我在围绕一个答案跳舞,但array_filter、array_search、递归等。我只是在精神上没有掌握它,哈哈。
我从XML导出中获得了这个示例,其中XML的顺序不一致,格式也不好,嵌套级别有时甚至不同,等等,所以我无法根据它在导出中的具体位置来获取值,即使是假人我也可以这样做:
<INFRA>
<GUID>7C32C0A2-EF31-11E9-8128-4CCC6A98779E</GUID>
<ID>501</ID>
<NAME>P Cedar</NAME>
<TYP>36</TYP>
<TYPKRZ>50_IN_36_PARKPLATZ</TYPKRZ>
<TYPNAME>parking place</TYPNAME>
<STATUS>open</STATUS>
<STATUSWERT k="SONSTIGE" v="miscellaneous">1</STATUSWERT>
</INFRA>
在这种情况下,我需要查找/搜索唯一的字符串,无论它可能在导出中的哪个位置结束。然后,我需要为该特定变量分配一个变量,以便我可以对它进行一些运算。TIA!<NAME>P Cedar</NAME>
<STATUS>
<INFRA><NAME>
答:
0赞
Olivier
11/17/2023
#1
$xml = <<<XML
<ROOT>
<NESTED>
<INFRA>
<GUID>7C32C0A2-EF31-11E9-8128-4CCC6A98779E</GUID>
<ID>501</ID>
<NAME>P Cedar</NAME>
<TYP>36</TYP>
<TYPKRZ>50_IN_36_PARKPLATZ</TYPKRZ>
<TYPNAME>parking place</TYPNAME>
<STATUS>open</STATUS>
<STATUSWERT k="SONSTIGE" v="miscellaneous">1</STATUSWERT>
</INFRA>
<INFRA>
<GUID>7C32C0A2-EF31-11E9-8128-4CCC6A98779E</GUID>
<ID>501</ID>
<NAME>D John</NAME>
<TYP>36</TYP>
<TYPKRZ>50_IN_36_PARKPLATZ</TYPKRZ>
<TYPNAME>parking place</TYPNAME>
<STATUS>closed</STATUS>
<STATUSWERT k="SONSTIGE" v="miscellaneous">1</STATUSWERT>
</INFRA>
</NESTED>
</ROOT>
XML;
function getStatus($doc, $name)
{
$xpath = new DOMXPath($doc);
$entries = $xpath->query('//INFRA/NAME');
foreach($entries as $entry)
{
if($entry->textContent == $name)
return $entry->parentNode->getElementsByTagName('STATUS')[0]->textContent;
}
return null;
}
$doc = new DOMDocument();
$doc->loadXML($xml);
echo getStatus($doc, 'P Cedar'); // open
echo getStatus($doc, 'D John'); // closed
出于性能原因,请考虑一次提取所有 NAME/STATUS 对(无需多次执行 XPath 查询)。
评论
0赞
pwbset
11/18/2023
谢谢!我已经进入了 DOM/XPath 兔子洞,事情很好地结合在一起。感谢您的意见/示例!总有新的东西要学!
0赞
ThW
11/17/2023
#2
用。Xpath 表达式允许复杂的条件和强制转换。因此,可以将逻辑直接放入表达式中:DOMXpath::evaluate()
- 文档中的任何元素:
INFRA
//INFRA
- ...带有子元素:
NAME
//INFRA[NAME]
- ...等于:
P Cedar
//INFRA[NAME="P Cedar"]
- ...孩子们:
STATUS
//INFRA[NAME="P Cedar"]/STATUS
- ...作为字符串:
string(//INFRA[NAME="P Cedar"]/STATUS)
Xpath 函数,例如获取节点列表并使用第一个节点的文本内容(或空字符串)。string()
$document = new DOMDocument();
$document->loadXML(getXML());
$xpath = new DOMXPath($document);
var_dump($xpath->evaluate('string(//INFRA[NAME = "P Cedar"]/STATUS)'));
var_dump($xpath->evaluate('string(//INFRA[NAME = "D John"]/STATUS)'));
function getXML() {
return <<<XML
<ROOT>
<NESTED>
<INFRA>
<GUID>7C32C0A2-EF31-11E9-8128-4CCC6A98779E</GUID>
<ID>501</ID>
<NAME>P Cedar</NAME>
<TYP>36</TYP>
<TYPKRZ>50_IN_36_PARKPLATZ</TYPKRZ>
<TYPNAME>parking place</TYPNAME>
<STATUS>open</STATUS>
<STATUSWERT k="SONSTIGE" v="miscellaneous">1</STATUSWERT>
</INFRA>
<INFRA>
<GUID>7C32C0A2-EF31-11E9-8128-4CCC6A98779E</GUID>
<ID>501</ID>
<NAME>D John</NAME>
<TYP>36</TYP>
<TYPKRZ>50_IN_36_PARKPLATZ</TYPKRZ>
<TYPNAME>parking place</TYPNAME>
<STATUS>closed</STATUS>
<STATUSWERT k="SONSTIGE" v="miscellaneous">1</STATUSWERT>
</INFRA>
</NESTED>
</ROOT>
XML;
}
要获取所有名称,您需要迭代节点并将它们用作详细表达式的上下文(的第二个参数):STATUS
DOMXpath::evaluate()
$document = new DOMDocument();
$document->loadXML(getXML());
$xpath = new DOMXPath($document);
$statusByName = array_reduce(
iterator_to_array($xpath->evaluate('//INFRA')),
static function (array $carry, \DOMNode $infra) use ($xpath) {
$name = $xpath->evaluate('string(NAME)', $infra);
$status = $xpath->evaluate('string(STATUS)', $infra);
$carry[$name] = $status;
return $carry;
},
[]
);
var_dump($statusByName);
评论
<NAME>
<INFRA>
<STATUS>