PHP SimpleXML. Как получить последний предмет?

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

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Установка и настройка Nginx и PHP на Ubuntu-сервере
Установка и настройка Nginx и PHP на Ubuntu-сервере
В этот раз я сделаю руководство по установке и настройке nginx и php на Ubuntu OS.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Как установить PHP на Mac
Как установить PHP на Mac
PHP - это популярный язык программирования, который используется для разработки веб-приложений. Если вы используете Mac и хотите разрабатывать...
1
0
8 289
6
Перейти к ответу Данный вопрос помечен как решенный

Ответы 6

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

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

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

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

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

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

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

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

<?php
$s = simplexml_load_file('in.xml');
$s->registerXPathNamespace('obix', 'http://obix.org/ns/schema/1.0');
$items = $s->xpath('//obix:list');
?>
Ответ принят как подходящий

Используйте функцию 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()].

Вы тестировали этот код? Я просто запустил его, но ничего не вышло. $ last_kwh вернет ложь;

DreamWerx 17.11.2008 14:02

Вероятно, потому что отсутствует регистрация пространства имен. Не заметил, потому что в вопросе он за кадром.

Tomalak 17.11.2008 14:06

Есть выражение 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()] выберет последний элемент book, который является дочерним элементом элемента bookstore.

Забыл префикс пространства имен в выражении XPath ... Извините!

Stefan Gehrig 17.11.2008 15:39

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

    <?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>, иначе он вернет другой результат.

Другие вопросы по теме