PHP SimpleXML. Как получить последний товар? - PullRequest
1 голос
/ 17 ноября 2008

Как бы я получил последний элемент (или какой-либо конкретный элемент в этом отношении) в объекте 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> кусок (или даже просто его часть).

Ответы [ 6 ]

5 голосов
/ 17 ноября 2008

Используйте функцию XPath last(), которая решает эту проблему:

<?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 должен отражать это.


РЕДАКТИРОВАТЬ: Обратите внимание, что [last()] эквивалентно [position() = last()].

4 голосов
/ 17 ноября 2008

Существует выражение 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()] выберет последний элемент книги, который является дочерним элементом элемента книжного магазина.

1 голос
/ 17 ноября 2008

Самый быстрый способ получить доступ к узлам в XML для программиста - это XPath. Взгляните на методы xpath и сам xpath .

0 голосов
/ 26 ноября 2014

Как уже упоминалось, вы можете использовать обозначения и функции массива.

    <?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(), чтобы получить последний элемент, но только если у вас всегда есть более одного , в противном случае он вернет другой результат.

0 голосов
/ 17 ноября 2008

Вы можете начать с этого .. Вы сможете откопать это .. Мне не нравится, что они использовали одно и то же имя тега на 2 уровнях.

<?php
$s = simplexml_load_file('in.xml');
$s->registerXPathNamespace('obix', 'http://obix.org/ns/schema/1.0');
$items = $s->xpath('//obix:list');
?>
0 голосов
/ 17 ноября 2008

Я думаю, что SimpleXML в любом случае загружает весь XML, и (если я правильно помню) вы можете использовать узлы SimpleXML, как если бы они были массивами, поэтому вы можете просто использовать функции массива, чтобы получить последний узел. Прошло много времени с тех пор, как я использовал PHP, но вы должны быть в состоянии получить длину, а затем получить элемент длиной 1 ...

Edit: Конечно, вы также можете использовать XPath, я подумал, что должен упомянуть и это, но я не был уверен, что last() работает в реализации SimpleXML XPath.

Я не уверен, что быстрее всего, используя индексы массивов или XPath, я бы предположил, что индексы массивов были быстрее, но вы должны попробовать оба в цикле несколько тысяч раз, получая время до и после цикла для проверки.

Но как всегда в CS: то, что вы выбираете, зависит от многих вещей.

Это время критично или используется очень часто: найдите самое быстрое решение.

Если вам понадобятся более сложные запросы и скорость не является проблемой: используйте все, что проще в реализации и дает необходимую мощность (XPath хорош для навигации по сложному дереву, индексация массивов хороша для быстрого произвольного доступа в списке типа данных; XML может использоваться для обоих типов.)

...