Бочонок
http://frontender.info
Обработка XML c порстранством имен c SimpleXML. 3 способа. Какой лучше?
Приятного времени суток.
Есть некий XML с пространствами имен. Например, такой:
Нужно работать с данными из него.
Так как если загрузить XML в SimpleXML объекты,
непосредственный доступ к элементам c префиксами пространст имен будет закрыт
Что можно сделать:
1. Вырезать пространства имен из XML перед созданием SimpleXML объекта
2. Все получать через XPath. По идее более ресурсоемко чем 1 и 3. Кроме того у меня возникали сложности с запросами типа $xml->xpath("//link[@rel='self']"); Иногда корректный запрос возвращает пустое множество. Даже если элемент есть.
3. По очереди обрабатывать узлы каждого пространства имен
Все три способа, на мой взгляд, один извращеннее другого.
Сейчас я использую 1. способ.
Как по вашему, что лучше?
И нет ли какого либо способа работать с ними с помощью SimpleXML нормально. Без лишних телодвижений?
С уважением.
Приятного времени суток.
Есть некий XML с пространствами имен. Например, такой:
PHP:
<?php
$responce='<entry xmlns="http://www.w3.org/2005/Atom" xmlns:app="http://www.w3.org/2007/app" xmlns:f="yandex:fotki">
<id>urn:yandex:fotki:maxum:photo:126746</id>
<title>Я и Саша на фоне Бранденбургских ворот</title>
<link href="http://api-fotki.yandex.ru/api/users/maxum/photo/126746/" rel="self" />
<link href="http://api-fotki.yandex.ru/api/users/maxum/photo/126746/" rel="edit" />
<published>2009-01-27T11:57:32Z</published>
<app:edited>2009-01-27T11:57:32Z</app:edited>
<updated>2009-01-27T11:57:32Z</updated>
<f:created>2008-07-10T22:02:40</f:created>
<f:hide_original value="false" />
<f:disable_comments rel="just test" value="false" />
<content src="http://img-fotki.yandex.ru/get/3306/maxum.0/0_1ef1a_9a6e7171_XL" type="image/*" />
</entry>';
?>
Так как если загрузить XML в SimpleXML объекты,
PHP:
<?php
$xml = new SimpleXMLElement('<?xml version="1.0" encoding="UTF-8"?>'.$responce);
?>
PHP:
<?php
echo $xml->disable_comments->arguments()->rel; //выдаст ошибку "Node no longer exists"
?>
1. Вырезать пространства имен из XML перед созданием SimpleXML объекта
PHP:
<?php
deleteXmlNamespace($responce);
$xml = new SimpleXMLElement('<?xml version="1.0" encoding="UTF-8"?>'.$responce);
echo $xml->disable_comments->attributes()->rel; //выдаст ожидаемое "just test"
function deleteXmlNamespace(&$xml){
$pattern = "|(<[/]*)[a-z][^:\s>]*:([^:\s>])[\s]*|sui";
$replacement="\\1\\2";
$xml = preg_replace($pattern, $replacement, $xml);
$pattern = "|(<[/]*[^\s>]+)[-]|sui";
$replacement="\\1_";
$xml = preg_replace($pattern, $replacement, $xml);
$pattern = "|xmlns[:a-z]*=\"[^\"]*\"|isu";
$replacement="";
$xml = preg_replace($pattern, $replacement, $xml);
}
?>
PHP:
<?php
$xml = new SimpleXMLElement('<?xml version="1.0" encoding="UTF-8"?>'.$responce);
$disable_comments = $xml->xpath("//f:disable_comments");
echo $disable_comments[0]->attributes()->rel; //выдаст ожидаемое "just test"
?>
PHP:
<?php
$xml = new SimpleXMLElement('<?xml version="1.0" encoding="UTF-8"?>'.$responce);
$namespaces = $xml->getNamespaces(true);
foreach($namespaces as $prefix=>$url){
$result = $xml->children($url);
foreach($result as $entry){
switch($entry->getName()){
case "disable_comments":
echo $entry->attributes()->rel; //выдаст ожидаемое "just test"
break;
}
}
}
?>
Все три способа, на мой взгляд, один извращеннее другого.
Сейчас я использую 1. способ.
Как по вашему, что лучше?
И нет ли какого либо способа работать с ними с помощью SimpleXML нормально. Без лишних телодвижений?
С уважением.