2017-06-20 47 views
3

我试图让该设施ENDDATE高于20170199和它的父母,我试着与父母::让父母*,但它显示了整个树,而不是过滤的视图。的XPath - 搜索数量大于,并显示父母

由于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> 
+0

'20170299' - 无效日期,没有这样的日期或月份'99' – RomanPerekhrest

+0

有没有EndDate大于'20170299'(这不是一个约会的日期,2017年2月的最后一天是28) –

+0

@RomanPerekhrest它是一个“日期”,但它的符号是一个整数,从而'20170299 + 1'使得'20170300' –

回答

1

你想被过滤掉/删除具有子EndDate节点与价值小于20170199(以比20170199数值越大保留的节点)的所有节点Facility什么。

使用DomDocumentDomXPath类解决方案:

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

输出:

<Person> 
    <Name>John</Name> 
    <LastName>Doe</LastName> 

    <Facility> 
     <TypeFacility>2</TypeFacility> 
     <StartDate>20161131</StartDate> 
     <EndDate>20170231</EndDate> 
    </Facility> 
    </Person> 

DEMO link

+0

因此,无法在不过滤XML的情况下获得预期结果? – creativename

+0

@creativename,过滤,在这种情况下,会比较简单,可读性和managabble – RomanPerekhrest

+1

我喜欢这样的解决方案,但它不工作VOOR多人.. –

-1

使用DOM文档,我将这样做:

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

总之:我选择所有节点的人至少有一个正确的结束日期,然后我删除所有设施节点用不正确的结束日期。

+0

非常类似于我的。此外,'loadXML'是装载一个字符串,该OP具有文件 – RomanPerekhrest

+0

@RomanPerekhrest:是的,但它不返回一个没有正确的结束日期最终人节点。 *(这些是用第一个查询过滤的)* –

+0

我认为这会产生无效的XML,因为它会在结束标记的同一行添加开始标记。为什么不只是'$ dom-> saveXML()'? –