Xpath - find number more and show to parents
I'm trying to get the enddate object higher than 20170199
and these are the parents, I tried to get the parents with the parent :: *, but it displays the whole tree instead of the filtered view.
Specified XML
<Delivery>
<Person>
<Name>John</Name>
<LastName>Doe</LastName>
<Facility>
<TypeFacility>2</TypeFacility>
<StartDate>20161131</StartDate>
<EndDate>20161231</EndDate>
</Facility>
<Facility>
<TypeFacility>2</TypeFacility>
<StartDate>20161131</StartDate>
<EndDate>20170231</EndDate>
</Facility>
</Person>
</Delivery>
What I have tried so far
<?php
$xmlStr = simplexml_load_file("test.xml");
$res = $xmlStr->xpath("Person/Facility[EndDate>20170199]/parent::*");
echo '<pre>';print_r($res);
Expected Result
<Person>
<Name>John</Name>
<LastName>Doe</LastName>
<Facility>
<TypeFacility>2</TypeFacility>
<StartDate>20161131</StartDate>
<EndDate>20170231</EndDate>
</Facility>
</Person>
Actual result
<Person>
<Name>John</Name>
<LastName>Doe</LastName>
<Facility>
<TypeFacility>2</TypeFacility>
<StartDate>20161131</StartDate>
<EndDate>20161231</EndDate>
</Facility>
<Facility>
<TypeFacility>2</TypeFacility>
<StartDate>20161131</StartDate>
<EndDate>20170231</EndDate>
</Facility>
</Person>
source to share
You want to filter / remove all nodes Facility
that have a child EndDate
node with a value less than 20170199
(to keep nodes with a value greater than 20170199
).
Solution using classes DomDocument
and DomXPath
:
$doc = new DOMDocument();
//$doc->preserveWhiteSpace = false;
$doc->load("test.xml");
$person = $doc->getElementsByTagName('Person')->item(0); // context node
$xpath = new DOMXPath($doc);
foreach ($xpath->query('Facility[EndDate <= 20170199]', $person) as $n) {
$person->removeChild($n);
}
echo $doc->saveXML($person);
Output:
<Person>
<Name>John</Name>
<LastName>Doe</LastName>
<Facility>
<TypeFacility>2</TypeFacility>
<StartDate>20161131</StartDate>
<EndDate>20170231</EndDate>
</Facility>
</Person>
source to share
Using DOMDocument I will do this:
$dom = new DOMDocument;
$dom->loadXML($xml);
$xp = new DOMXPath($dom);
$personNodeList = $xp->query('//Person[Facility/EndDate > 20170131]');
$result = '';
foreach($personNodeList as $personNode) {
$facilityNodeList = $xp->query('//Facility[EndDate <= 20170131]', $personNode);
foreach ($facilityNodeList as $facilityNode) {
$facilityNode->parentNode->removeChild($facilityNode);
}
$result .= $dom->saveXML($personNode);
}
In short: I select all Person nodes with at least one correct EndDate and then delete all Facility nodes with the wrong EndDate.
source to share