xpath — поиск значения узлов с использованием XMLDOm в переполнении стека

Мне нужно извлечь информацию из XML с использованием XMLDom.

Ниже 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 во время зацикливания.

1

Решение

С XPath иди прямо к тебе dates тег, а затем использовать DOMElement::getElementsByTagName() получить StartDate а также EndDate (Вы также можете перейти к dates использование тегов DOMDocument::getElementsByTagName(), но XPath дает вам больше гибкости, если вам это нужно). Это вернет 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);

демонстрация

Или только с 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);

демонстрация

Запрос просто получит любые элементы внутри текущего detail элемент, который содержит слово «Дата». Опять же, если структура постоянна, вы можете предположить, что первый результат будет StartDate и второй результат будет EndDate,

1

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]