Гость
Форумы / PHP, Perl, Python [игнор отключен] [закрыт для гостей] / php xpath: некорректно работает метод SimpleXMLElement->xpath() / 6 сообщений из 6, страница 1 из 1
29.11.2016, 18:35
    #39357211
Cyrax_02
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
php xpath: некорректно работает метод SimpleXMLElement->xpath()
В Linux тот же самый код отрабатывает корректно.
Но в Windows наблюдается следующий артефакт (вероятно связанный с различием в символах перехода на новую строку).

Тест 1
Код: php
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
// Тест 1
$xml = <<<XML
<?xml version="1.0" encoding="windows-1251" ?>
<ValCurs Date="29.11.2016" name="Foreign Currency Market">
	<Valute ID="R01010">
		<NumCode>036</NumCode>
		<CharCode>AUD</CharCode>
		<Nominal>1</Nominal>
		<Name>Австралийский доллар</Name>
		<Value>48,6345</Value>
	</Valute>
	<Valute ID="R01235">
		<NumCode>840</NumCode>
		<CharCode>USD</CharCode>
		<Nominal>1</Nominal>
		<Name>Доллар США</Name>
		<Value>64,9153</Value>
	</Valute>
</ValCurs>
XML;

//$xml = strtr($xml, array("\t" => "", "\n" => "", "\r" => ""));
$xmlObj = new SimpleXMLElement($xml);
$value = $xmlObj->xpath('Valute[@ID="R01235"]/Value');
echo "<pre>".print_r($value, true)."</pre>";

Получаем (узел найден, но его значение "потерялось"):
Код: php
1.
2.
3.
4.
5.
6.
Array
(
    [0] => SimpleXMLElement Object
        (
        )
)

Если же раскомментировать строку, удаляющую табуляции и символы перехода на новую строку, получим корректный результат (если табуляции не удалить, то значение не появится - необходимо удалить и табуляции, и символы перевода строки):
Код: php
1.
2.
3.
4.
5.
6.
7.
Array
(
    [0] => SimpleXMLElement Object
        (
            [0] => 64,9153
        )
)


Тест 2
Код: php
1.
2.
3.
4.
5.
$xmlObj = simplexml_load_file('http://www.cbr.ru/scripts/XML_daily.asp?date_req='.date('d/m/Y', time()));
//$xmlObj = new SimpleXMLElement(strtr($xmlObj->asXML(), array("\t" => "", "\n" => "", "\r" => "")));

$value = $xmlObj->xpath('Valute[@ID="R01235"]/Value');
echo "<pre>".print_r($value, true)."</pre>";

Получаем (узел найден, но его значение "потерялось"):
Код: php
1.
2.
3.
4.
5.
6.
Array
(
    [0] => SimpleXMLElement Object
        (
        )
)

Если же раскомментировать строку, удаляющую символы перехода на новую строку, получим корректный результат:
Код: php
1.
2.
3.
4.
5.
6.
7.
Array
(
    [0] => SimpleXMLElement Object
        (
            [0] => 64,9153
        )
)


Независимо от запроса (из Linux или из Windows), по ссылке http://www.cbr.ru/scripts/XML_daily.asp?date_req=29/11/2016 получаем xml-код в кодировке "windows-1251" ( <?xml version="1.0" encoding="windows-1251" ?> ).

В чём точная причина "исчезновения" значения в возвращаемом объекте SimpleXMLElement ?
[ simplexml_load_file ] и [ new SimpleXMLElement ] в обоих случаях выполняются безо всяких ошибок и предупреждений. Но при этом метод xpath узел находит, но в возвращаемый объект SimpleXMLElement значение найденного узла не включает. Почему ?
...
Рейтинг: 0 / 0
29.11.2016, 19:02
    #39357236
Cyrax_02
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
php xpath: некорректно работает метод SimpleXMLElement->xpath()
А Nominal вообще не находит - даже если и удалять символы перехода на новую строку:
Код: php
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
$xml = <<<XML
<?xml version="1.0" encoding="windows-1251" ?>
<ValCurs Date="29.11.2016" name="Foreign Currency Market">
	<Valute ID="R01010">
		<NumCode>036</NumCode>
		<CharCode>AUD</CharCode>
		<Nominal>1</Nominal>
		<Name>Австралийский доллар</Name>
		<Value>48,6345</Value>
	</Valute>
	<Valute ID="R01235">
		<NumCode>840</NumCode>
		<CharCode>USD</CharCode>
		<Nominal>1</Nominal>
		<Name>Доллар США</Name>
		<Value>64,9153</Value>
	</Valute>
</ValCurs>
XML;

$xml = strtr($xml, array("\t" => "", "\n" => "", "\r" => ""));
$xmlObj = new SimpleXMLElement($xml);
$nominal = $xmlObj->xpath('Valute[@ID="R01235"]/Nominal');
echo "<pre>".print_r($nominal, true)."</pre>";

Получаем:
Код: php
1.
2.
3.
4.
5.
6.
Array
(
    [0] => SimpleXMLElement Object
        (
        )
)


Т.е. в Windows xpath ни хрена не работает.
Работает только для последнего подузла и только если удалять символы перехода на новую строку.
...
Рейтинг: 0 / 0
29.11.2016, 20:08
    #39357281
Cyrax_02
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
php xpath: некорректно работает метод SimpleXMLElement->xpath()
Как оказалось, получаемый объект
Код: php
1.
2.
3.
4.
5.
6.
Array
(
    [0] => SimpleXMLElement Object
        (
        )
)

не простой, а волшебный . Это только в виду он пустой. Но на самом деле не совсем пустой. Даже совсем не пустой.

Если сделать вот так:
Код: php
1.
list( , $nominal) = each($nominal); echo $nominal;

то наконец-то получим значение найденного узла.

При использовании любых других способов "вытаскивания" из него значения ( print_r , var_dump , reset , value и пр.) получим бублик с дыркой.
...
Рейтинг: 0 / 0
29.11.2016, 20:38
    #39357291
Cyrax_02
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
php xpath: некорректно работает метод SimpleXMLElement->xpath()
Ещё работают такие варианты:
Код: php
1.
echo (string)$nominal[0];

Код: php
1.
echo $nominal[0]->asXML();

Код: php
1.
echo $nominal[0][0];

Код: php
1.
echo $nominal[0];

Код: php
1.
echo $nominal[0][0][0][0][0][0][0][0][0][0];
...
Рейтинг: 0 / 0
29.11.2016, 21:12
    #39357303
Cyrax_02
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
php xpath: некорректно работает метод SimpleXMLElement->xpath()
А чтобы не привязываться к индексу - так:
Код: php
1.
echo (integer)reset($nominal);
...
Рейтинг: 0 / 0
01.12.2016, 23:55
    #39358999
Cyrax_02
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
php xpath: некорректно работает метод SimpleXMLElement->xpath()
http://stackoverflow.com/a/3109364 Don't use print_r() or var_dump() to inspect a SimpleXMLElement, they won't necessarily work on them because SimpleXML uses lots of magic behind the scene. Instead, look at what asXML() returns.
...
Рейтинг: 0 / 0
Форумы / PHP, Perl, Python [игнор отключен] [закрыт для гостей] / php xpath: некорректно работает метод SimpleXMLElement->xpath() / 6 сообщений из 6, страница 1 из 1
Целевая тема:
Создать новую тему:
Автор:
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]