基于';返回父节点的PHP XPath;儿童';价值观

基于';返回父节点的PHP XPath;儿童';价值观,php,xml,xpath,Php,Xml,Xpath,是否可以只运行一个查询来替换多个查询 //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_exe

是否可以只运行一个查询来替换多个查询

 //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]
出于某种原因,这在PHP的xpath()函数中不起作用

//host_info[hostname="localhost" and vulnerability_id="remote_execution"]/(*, ../background, ../impact, ../problem)
我觉得这里应该有更好的方法。请注意,可能有多个
节点,这就是我将主机名和漏洞id作为目标的原因。但是父
节点中只包含一个
节点

<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>

节点列表只有一个维度,因此将多个项目的详细信息序列化到一个列表中并没有真正的用处

通常,您会使用一个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)
        ]
    );
}
对于单个项目,可以将所有细节节点提取到单个结果列表中。但是,这样的表达式会很快变得复杂,然后必须添加识别不同细节节点的逻辑

$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
    );
} 
$document=新的DOMDocument();
$document->loadXML($xml);
$xpath=newdomxpath($document);
$expression=textContent
);
} 

很好的解释。谢谢这清理了一堆代码,使速度提高了约4倍。你说得对,事情很快就会变得复杂。再次感谢。