简体   繁体   English

PHP XPath 根据“子”值返回父节点

[英]PHP XPath to return parent nodes based on 'child' values

Is it possible to run just a single query to replace multiple queries?是否可以只运行一个查询来替换多个查询?

 //host_info[hostname="localhost" and vulnerability_id="remote_execution"][1]
 //host_info[hostname="localhost" and vulnerability_id="remote_execution"][1]/@exclude
 //host_info[hostname="localhost" and vulnerability_id="remote_execution"][1]/../problem[1]
 //host_info[hostname="localhost" and vulnerability_id="remote_execution"][1]/../reference[1]
 //host_info[hostname="localhost" and vulnerability_id="remote_execution"][1]/../impact[1]
 //host_info[hostname="localhost" and vulnerability_id="remote_execution"][1]/../background[1]
 //host_info[hostname="localhost" and vulnerability_id="remote_execution"][1]/../resolution[1]

For some reason this doesn't work in PHP's xpath() function.由于某种原因,这在 PHP 的 xpath() function 中不起作用。

//host_info[hostname="localhost" and vulnerability_id="remote_execution"]/(*, ../background, ../impact, ../problem)

I feel there has to be a better way here.我觉得这里必须有更好的方法。 Please note it's possible to have multiple <host_info> nodes which is why I'm targeting the hostname and vulnerability_id.请注意,可能有多个<host_info>节点,这就是我针对主机名和漏洞 ID 的原因。 But there are only one <background> , <resolution> nodes contained in the parent <vulnerability_id> node.但是父<vulnerability_id>节点中只包含一个<background><resolution>节点。

<report>
<vulnerability>
   <host_info>
      <hostname></hostname>
      <vulnerability_id></vulnerability_id>
   </host_info>
   <host_info>
      <hostname></hostname>
      <vulnerability_id></vulnerability_id>
   </host_info>
   <background></background>
   <resolution></resolution>
</vulnerability>
<vulnerability>
   <host_info></host_info>
   <host_info></host_info>
   <host_info></host_info>
   <host_info></host_info>
   <background></background>
   <resolution></resolution>
</vulnerability>
</report>

A node list has only a single dimension, so it is not really useful to serialize details of multiple items into a single list.节点列表只有一个维度,因此将多个项目的详细信息序列化到单个列表中并不是很有用。

Typically you would use one Xpath expression to identify your list nodes and then DOM methods and relative expressions to fetch data related to these nodes:通常,您会使用一个 Xpath 表达式来识别您的列表节点,然后使用 DOM 方法和相关表达式来获取与这些节点相关的数据:

$document = new DOMDocument();
$document->loadXML($xml);
$xpath = new DOMxpath($document);

foreach ($xpath->evaluate('//host_info[hostname="localhost" and vulnerability_id="remote_execution"]') as $hostInfo) {
    var_dump(
      [
          $hostInfo->getAttribute('exclude'),
          $xpath->evaluate('string(parent::*/background)', $hostInfo),
          $xpath->evaluate('string(parent::*/resolution)', $hostInfo)
        ]
    );
}

For a single item it is possible to fetch all the detail nodes into a single result list.对于单个项目,可以将所有详细节点提取到单个结果列表中。 However an expression like that will get complex fast and you then have to add logic that recognizes the different detail nodes.但是,这样的表达式会很快变得复杂,然后您必须添加识别不同细节节点的逻辑。

$document = new DOMDocument();
$document->loadXML($xml);
$xpath = new DOMxpath($document);

$expression = <<<'XPATH'
//host_info[hostname="localhost" and vulnerability_id="remote_execution"][1]/@exclude|
(//host_info[hostname="localhost" and vulnerability_id="remote_execution"][1]/parent::*/background)[1]|
(//host_info[hostname="localhost" and vulnerability_id="remote_execution"][1]/parent::*/resolution)[1]
XPATH;

foreach ($xpath->evaluate($expression) as $detail) {
    var_dump(
       $detail->localName, $detail->textContent
    );
} 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM