PHP XPath для возврата родительских узлов на основе «дочерних» значений - PullRequest
1 голос
/ 14 октября 2019

Можно ли выполнить только один запрос для замены нескольких запросов?

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

Я чувствую, что здесь должен быть лучший путь. Обратите внимание, что возможно иметь несколько <host_info> узлов, поэтому я нацеливаюсь на имя хоста и уязвимость_ид. Но в родительском узле <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>

1 Ответ

1 голос
/ 14 октября 2019

Список узлов имеет только одно измерение, поэтому на самом деле нецелесообразно сериализовать детали нескольких элементов в один список.

Обычно вы используете одно выражение 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
    );
} 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...