Pregunta

¿Cómo obtendría el último elemento (o cualquier elemento específico para ese asunto) en un objeto simplexml? Suponga que no sabe cuántos nodos habrá.

ej.

<?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>

Y quiero tomar el último <obj></obj> fragmento (o incluso solo parte de él).

¿Fue útil?

Solución

Utilice la función last() de XPath, que resuelve este mismo problema:

<?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); 
?> 

Aquí busca el último <obj> interior, y allí el <int> con el nombre de "energy_in_kwh".

Cuidado con el registro del espacio de nombres. (Todos sus elementos son parte del espacio de nombres "http://obix.org/ns/schema/1.0", la consulta XPath debe reflejar eso.


EDITAR: tenga en cuenta que [last()] es equivalente a [position() = last()].

Otros consejos

Hay una expresión XPath que hará exactamente lo que quieres:

$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);

Por ejemplo, /bookstore/book[last()] seleccionará el último elemento del libro que es hijo del elemento de la librería.

La forma más rápida de acceder a los nodos en XML, para un programador, es XPath. Eche un vistazo a los métodos xpath y xpath en sí .

Puede comenzar con esto ... Podrá desenterrarlo ... No me gusta que usaran el mismo nombre de etiqueta en 2 niveles ... Intento evitar nombres de etiqueta duplicados.

<?php
$s = simplexml_load_file('in.xml');
$s->registerXPathNamespace('obix', 'http://obix.org/ns/schema/1.0');
$items = $s->xpath('//obix:list');
?>

Creo que SimpleXML carga todo el XML de todos modos y (si no recuerdo mal) puede usar los nodos SimpleXML como si fueran matrices, por lo que podría usar funciones de matriz para obtener el último nodo. Ha pasado un tiempo desde que usé PHP, pero deberías poder obtener la longitud y luego obtener el elemento en longitud-1 ...

Editar: Por supuesto, también puede usar XPath, pensé que debería mencionarlo también, pero no estaba seguro si last() funcionó en la implementación de XPath SimpleXML.

No estoy seguro de cuál es el más rápido, usando índices de matriz o XPath, supongo que los índices de matriz fueron más rápidos, pero debe intentar ambos en un bucle unas miles de veces para obtener el tiempo antes y después del bucle para verificar.

Pero como siempre en CS: lo que elijas depende de muchas cosas.

¿Es el tiempo crítico o se usa con mucha frecuencia? Entonces encuentre la solución más rápida.

Si necesita consultas más complicadas y la velocidad no es un problema: use lo que sea más fácil de implementar y le brinde la potencia que necesita (XPath es bueno para la navegación compleja en árbol, la indexación de matrices es buena para un acceso aleatorio rápido en la lista estructuras de datos de tipo; XML se puede usar para ambos.)

Como ya se mencionó, puede usar la notación de matriz y las funciones.

    <?php 
    $xml = simplexml_load_file('HistoryRecord.xml'); 
    $lastObj = $xml->list->obj[$xml->list->obj->count()-1];

o

    $lastObj = $xml->list->obj[count($xml->list->obj)-1];

También puede usar end() para obtener el último elemento, pero solo si siempre tiene más de un < obj > ;, de lo contrario, devolverá un resultado diferente.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top