У меня есть следующий XML-файл с пространством имен:
<?xml version = "1.0" encoding = "utf-8"?>
<dc:languages xmlns:dc = "http://purl.org/dc/elements/1.1/">
<dc:lang name = "C">
<dc:appeared>1972</dc:appeared>
<dc:creator>Dennis Ritchie</dc:creator>
</dc:lang>
<dc:lang name = "PHP">
<dc:appeared>1995</dc:appeared>
<dc:creator>Rasmus Lerdorf</dc:creator>
</dc:lang>
<dc:lang name = "Java">
<dc:appeared>1995</dc:appeared>
<dc:creator>James Gosling</dc:creator>
</dc:lang>
</dc:languages>
Я хочу прочитать значение создателя, но мой код не работает.
$languages = simplexml_load_string($myXMLData);
$ns = $languages->getNamespaces(true);
$parent = $languages->$ns["lang"];
foreach($parent as $lang) {
$dc = $lang->children($ns["dc"]);
echo $dc->creator.'<br>';
}
Помогите, пожалуйста!






Вы не должны использовать SimpleXMLElement::getNamespaces() для извлечения URI пространства имен из документа. Это определяющие значения, а не префиксы. Префиксы / псевдонимы являются необязательными для узлов XML-элементов и могут изменяться в любом узле элемента. Так что просто определите массив для всех пространств имен, которые вы используете.
SimpleXMLElement::children() действует как фильтр и возвращает SimpleXMLElement. Вы можете использовать синтаксис свойства для доступа к отфильтрованным дочерним элементам.
$languages = simplexml_load_string($xml);
$ns = [
'dc' => 'http://purl.org/dc/elements/1.1/'
];
$parent = $languages->children($ns["dc"])->lang;
foreach($parent as $lang) {
$creator = $lang->children($ns["dc"])->creator;
echo htmlspecialchars($creator).'<br>';
}
Выход:
Dennis Ritchie<br>Rasmus Lerdorf<br>James Gosling<br>
В DOM вы можете использовать Xpath (после регистрации пространств имен) для получения значений:
$document = new DOMDocument();
$document->loadXML($xml);
$xpath = new DOMXpath($document);
$xpath->registerNamespace('d', 'http://purl.org/dc/elements/1.1/');
foreach($xpath->evaluate('/d:languages/d:lang') as $lang) {
$creator = $xpath->evaluate('string(d:creator)', $lang);
echo htmlspecialchars($creator), '<br>';
}
Несмотря на действительно хороший ответ от ThW, похоже, это тоже работает ....
<?php
$xml= simplexml_load_string(
'<?xml version = "1.0" encoding = "utf-8"?>
<dc:languages version = "2" xmlns:dc = "http://purl.org/dc/elements/1.1/">
<dc:lang name = "C">
<dc:appeared>1972</dc:appeared>
<dc:creator>Dennis Ritchie</dc:creator>
</dc:lang>
<dc:lang name = "PHP">
<dc:appeared>1995</dc:appeared>
<dc:creator>Rasmus Lerdorf</dc:creator>
</dc:lang>
<dc:lang name = "Java">
<dc:appeared>1995</dc:appeared>
<dc:creator>James Gosling</dc:creator>
</dc:lang>
</dc:languages>'
);
foreach($xml->xpath('//dc:lang') as $lang) {
echo $lang->xpath('dc:creator')[0]."<br>";
}
и производит этот вывод из интерфейса командной строки.
Dennis Ritchie<br>Rasmus Lerdorf<br>James Gosling<br>
Однако мне пришлось изменить ваш XML, или simplexml_load_string () вернет ошибку.
<dc:languages xmlns:dc = "http://purl.org/dc/elements/1.1/">
к
<dc:languages version = "2" xmlns:dc = "http://purl.org/dc/elements/1.1/">
В LibXML есть некорректная функция, которая регистрирует определения пространств имен текущего контекста. Вы можете использовать Xpath с SimpleXML, но вы должны зарегистрировать пространства имен в каждом экземпляре SimpleXMLElement, на котором вы вызываете метод xpath().
Я всегда с подозрением отношусь к своим излишне простым ответам.