Reputation: 532
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.
//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. But there are only one <background>
, <resolution>
nodes contained in the parent <vulnerability_id>
node.
<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>
Upvotes: 1
Views: 29
Reputation: 19492
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:
$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
);
}
Upvotes: 1