在 PHP 中使用 XMLDOm 查找节点的值

Finding value of nodes using XMLDOm in PHP

我需要使用 XMLDom 从 XML 中提取信息。

下面是myroot.xml

<?xml version='1.0' encoding='ISO-8859-1'?>
<myroot xml:lang='en'>
<delta>
    <history>
        <detail>
            <id>one</id>
            <degree>
                <dname>alpha</dname>
                <dates>
                    <StartDate>
                        <Year>1998</Year>
                    </StartDate>
                    <EndDate>
                        <Year>2002</Year>
                    </EndDate>
                </dates>
            </degree>
        </detail>
        <detail>
            <id>two</id>
            <degree>
                <dname>beta</dname>
                <dates>
                    <StartDate>
                        <Year>2006</Year>
                    </StartDate>
                    <EndDate>
                        <Year>2008</Year>
                    </EndDate>
                </dates>
            </degree>
        </detail>
    </history>
</delta>    

这是我的代码

$doc = new DOMDocument;
$doc->preserveWhiteSpace = false;
$rootxmldoc = $doc->load('myroot.xml');
$xpath = new DOMXPath($rootxmldoc);
$items = $hrxml_obj->getElementsByTagName("detail");
$subitemarray = array();
$icounter = 0;
foreach ($items as $item) {
    $query = "//dates/*/Year"; //xpath of all occurrence of Year
    $entries = $xpath->query($query, $item);
    foreach ($entries as $entry) {
      $dates["startdate"] = "todo"; //extract StartDate
      $dates["enddate"] = "todo";  //extract EndDate
    }
    $subitemarray[$icounter++] = dates;
}
var_dump($subitemarray);

理想情况下,我需要使用 xpath 提取日期。我无法解决这个问题。任何帮助表示赞赏。问题是循环时 xpath 的使用。

使用 XPath 直接转到 dates 标记,然后使用 DOMElement::getElementsByTagName() to get StartDate and EndDate (you can also go to the dates tag using DOMDocument::getElementsByTagName(), but XPath gives you more flexibility should you need it). This will return a DOMNodeList,但您知道(如果结构不变)您只需要列表的第一个元素。所以:

// $xml ommited, saved in a variable for testing purposes
$doc = new DOMDocument;
$doc->preserveWhiteSpace = false;
$doc->loadXML($xml);
$xpath = new DOMXPath($doc);
$items = $doc->getElementsByTagName("detail");
$subitemarray = array();
$icounter = 0;
foreach ($items as $item) {
    $query = "//dates"; //xpath of all occurrence of Year
    $entries = $xpath->query($query, $item);
    foreach ($entries as $entry) {
        $startDate = $entry->getElementsByTagName("StartDate")[0]->nodeValue;
        $endDate = $entry->getElementsByTagName("EndDate")[0]->nodeValue;
        $dates["startdate"] = $startDate; //extract StartDate
        $dates["enddate"] = $endDate;  //extract EndDate
    }
    $subitemarray[$icounter++] = $dates;
}
var_dump($subitemarray);

Demo

或仅使用 XPath:

$doc = new DOMDocument;
$doc->preserveWhiteSpace = false;
$doc->loadXML($xml);
$xpath = new DOMXPath($doc);
$items = $doc->getElementsByTagName("detail");
$subitemarray = array();
$icounter = 0;
foreach ($items as $item) {
    $queryStart = "//dates/StartDate";
    $entriesStart = $xpath->query($queryStart, $item);
    $dates["startdate"] = $entriesStart[0]->nodeValue;

    $queryEnd = "//dates/EndDate";
    $entriesEnd = $xpath->query($queryEnd, $item);
    $dates["enddate"] = $entriesEnd[0]->nodeValue;
    $subitemarray[$icounter++] = $dates;
}
var_dump($subitemarray);

最后,只使用一个 XPath 查询:

$doc = new DOMDocument;
$doc->preserveWhiteSpace = false;
$doc->loadXML($xml);
$xpath = new DOMXPath($doc);
$items = $doc->getElementsByTagName("detail");
$subitemarray = array();
$icounter = 0;
foreach ($items as $item) {
    $query = "//dates/*[contains(local-name(), 'Date')]
";
    $entries = $xpath->query($query, $item);
    $dates["startdate"] = $entries[0]->nodeValue;
    $dates["enddate"] = $entries[1]->nodeValue;
    $subitemarray[$icounter++] = $dates;
}
var_dump($subitemarray);

Demo

查询将只获取当前 detail 元素中包含单词 "Date" 的所有元素。同样,如果结构不变,您可以假设第一个结果为 StartDate,第二个结果为 EndDate.