Чтобы прочитать XML с пространствами имен, вам не нужно знать префикс, используемый в документе. Вам нужно знать и сравнивать URI пространства имен. Поэтому не сравнивайте XMLReader::$name
, но XMLReader::$localName
и XMLReader::$namespaceURI
.
Вот две веские причины для чтения пространства имен из документа.
- Generi c Конвертация ( как XML в JsonML)
- Отладка
В этом случае итерируйте потомков элементов и прочитайте атрибуты с именем узла xmlns
и атрибутами в пространстве имен http://www.w3.org/2000/xmlns/
,
Имейте в виду, что только URI пространства имен являются уникальными. Префиксы не являются уникальными или всегда необходимы.
Демо:
$xml = <<<'XML'
<f:foo xmlns:f="urn:a" xmlns="urn:default" xmlns:b="urn:b">
<f:bar xmlns:f="urn:c" xmlns="urn:a"/>
</f:foo>
XML;
$xmlUrl = 'data://text/plain;base64,'.base64_encode($xml);
$reader = new XMLReader();
$reader->open($xmlUrl);
$namespaces = [];
while ($reader->read()) {
if ($reader->nodeType == XMLReader::ELEMENT && $reader->hasAttributes) {
while ($reader->moveToNextAttribute()) {
if ($reader->name === 'xmlns') {
$namespaces[$reader->value][] = '#default';
} elseif ($reader->namespaceURI === 'http://www.w3.org/2000/xmlns/') {
$namespaces[$reader->value][] = $reader->localName;
}
}
}
}
var_dump($namespaces);
Вывод:
array(4) {
["urn:a"]=>
array(2) {
[0]=>
string(1) "f"
[1]=>
string(8) "#default"
}
["urn:default"]=>
array(1) {
[0]=>
string(8) "#default"
}
["urn:b"]=>
array(1) {
[0]=>
string(1) "b"
}
["urn:c"]=>
array(1) {
[0]=>
string(1) "f"
}
}