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>

      

+3


source to share


2 answers


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>

      


DEMO link

+1


source


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.

-1


source







All Articles