2017-06-20 36 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()'? –