Как я могу получить последний объект (или любой конкретный элемент) в объекте simplexml? Предположим, вы не знаете, сколько узлов будет.
ех.
<?xml version="1.0" encoding="UTF-8"?> <?xml-stylesheet type="text/xsl" href="/xsl.xml"?> <obj href="http://xml.foo.com/" display="com.foo.bar" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://obix.org/ns/schema/1.0" > <list name="data" of="HistoryRecord"> <obj> <abstime name="timestamp" val="1876-11-10T00:00:00-08:00"></abstime> <int name="energy_in_kwh" val="1234"></int> <int name="energy_out_kwh" val="123456"></int> </obj> <obj> <abstime name="timestamp" val="1876-11-10T00:15:00-08:00"></abstime> <int name="energy_in_kwh" val="1335"></int> <int name="energy_out_kwh" val="443321"></int> </obj> </list> <int name="count" val="2"></int> </obj>
И я хочу захватить последний кусок <obj></obj>
(или даже его часть).
Используйте функцию last()
XPath, которая решает эту проблему:
<?php $xml = simplexml_load_file('HistoryRecord.xml'); $xml->registerXPathNamespace('o', 'http://obix.org/ns/schema/1.0'); $xpath = "/o:obj/o:list/o:obj[last()]/o:int[@name = 'energy_in_kwh']"; $last_kwh = $xml->xpath($xpath); ?>
Здесь он ищет последний внутренний <obj>
, а для него <int>
с именем "energy_in_kwh"
.
Следите за регистрацией пространства имен. (Все ваши элементы являются частью пространства имен "http://obix.org/ns/schema/1.0"
, запрос XPath должен отражать это.
EDIT: Обратите внимание, что [last()]
эквивалентно [position() = last()]
.
Существует выражение XPath, которое будет делать именно то, что вы хотите:
$xml='<?xml version="1.0" encoding="UTF-8"?> <?xml-stylesheet type="text/xsl" href="/xsl.xml"?> <obj href="http://xml.foo.com/" display="com.foo.bar" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://obix.org/ns/schema/1.0" > <list name="data" of="HistoryRecord"> <obj> <abstime name="timestamp" val="1876-11-10T00:00:00-08:00"></abstime> <int name="energy_in_kwh" val="1234"></int> <int name="energy_out_kwh" val="123456"></int> </obj> <obj> <abstime name="timestamp" val="1876-11-10T00:15:00-08:00"></abstime> <int name="energy_in_kwh" val="1335"></int> <int name="energy_out_kwh" val="443321"></int> </obj> </list> <int name="count" val="2"></int> </obj>'; $x=simplexml_load_string($xml); $x->registerXPathNamespace('obix', 'http://obix.org/ns/schema/1.0'); $objects=$x->xpath('/obix:obj/obix:list/obix:obj[last()]'); print_r($objects);
Например, /bookstore/book[last()]
выберет последний элемент книги, являющийся дочерним элементом элемента книжного магазина.
Самый быстрый способ доступа к узлам в XML для программиста – XPath. Взгляните на методы xpath и xpath .
Вы можете начать с этого .. Вы сможете выкопать его. Мне не нравится, что они использовали одно и то же имя тега на 2 уровнях. Я стараюсь избегать дублирования имен тегов.
<?php $s = simplexml_load_file('in.xml'); $s->registerXPathNamespace('obix', 'http://obix.org/ns/schema/1.0'); $items = $s->xpath('//obix:list'); ?>
Я думаю, что SimpleXML все равно загружает весь XML и (если я правильно помню) вы можете использовать узлы SimpleXML, как если бы они были массивами, поэтому вы могли просто использовать функции массива для получения последнего узла. Это время, так как я использовал PHP, но вы должны иметь возможность получить длину, а затем получить элемент длиной 1 …
Редактирование. Конечно, вы можете использовать XPath, я думал, что должен упомянуть об этом, но я не был уверен, что last()
работал в реализации SimpleXML XPath.
Я не уверен, что быстрее, используя индексы массивов или XPath, я бы предположил, что индексы массивов были быстрее, но вы должны попробовать оба в цикле несколько тысяч раз получить время до и после цикла для проверки.
Но как всегда в CS: то, что вы выбираете, зависит от многих вещей.
Это время критично или используется очень часто: затем найдите самое быстрое решение.
Если вам потребуются более сложные запросы, и скорость не является проблемой: используйте то, что проще всего реализовать и дает необходимую вам мощность (XPath хорош для сложной навигации по дереву, индексирование массива полезно для быстрого произвольного доступа в структурах типов списка , XML может использоваться для обоих.)
Как уже упоминалось, вы можете использовать обозначения и функции массива.
<?php $xml = simplexml_load_file('HistoryRecord.xml'); $lastObj = $xml->list->obj[$xml->list->obj->count()-1];
или
$lastObj = $xml->list->obj[count($xml->list->obj)-1];
Вы также можете использовать end()
чтобы получить последний элемент, но только если у вас всегда есть более одного <obj>, иначе он вернет другой результат.