xpath - 搜索大于的数字并显示父项

时间:2017-06-20 08:51:31

标签: php xml xpath simplexml

我试图让设施的结束日期高于20170199并且它是父母,我试图让父母使用父:: *但它显示整个树而不是过滤后的视图。

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

到目前为止我尝试了什么

<?php
$xmlStr = simplexml_load_file("test.xml");
$res = $xmlStr->xpath("Person/Facility[EndDate>20170199]/parent::*");
echo '<pre>';print_r($res);

预期结果

   <Person>
     <Name>John</Name>
     <LastName>Doe</LastName>
     <Facility>
       <TypeFacility>2</TypeFacility>
       <StartDate>20161131</StartDate>
       <EndDate>20170231</EndDate>
     </Facility>
   </Person>

实际结果

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

2 个答案:

答案 0 :(得分:1)

您想要的是过滤/移除所有Facility个节点,这些节点的子节点为EndDate,其值 小于 {{1} }(保留值大于20170199的节点)。

使用20170199DomDocument类的解决方案:

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

DEMO link

答案 1 :(得分:-1)

使用DOMDocument,我会这样做:

$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);
}

简而言之:我选择所有具有至少一个正确EndDate的Person节点,然后删除所有具有不正确EndDate的Facility节点。