PHP SimpleXML. How to get the last item?

陌路散爱 提交于 2019-12-17 21:14:26

问题


How would I get the last item (or any specific item for that matter) in a simplexml object? Assume you don't know how many nodes there will be.

ex.

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

And I want to grab the last <obj></obj> chunk (or even just part of it).


回答1:


Use XPath's last() function, which solves this very problem:

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

Here it looks for the last inner <obj>, and therein for the <int> with the name of "energy_in_kwh".

Watch out for the namespace registration. (All your elements are part of the "http://obix.org/ns/schema/1.0" namespace, the XPath query must reflect that.


EDIT: Note that [last()] is equivalent to [position() = last()].




回答2:


There is a XPath expression that'll do exactly what you want:

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

For example /bookstore/book[last()] will select the last book element that is the child of the bookstore element.




回答3:


Quickest way to access nodes in XML, for a programmer, is XPath. Take a look at the xpath methods and xpath itself.




回答4:


You can start with this.. You'll be able to dig it out.. I don't like that they used the same tag name at 2 levels.. I try to avoid duplicate tag names.

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



回答5:


I think SimpleXML loads the whole XML anyway and (if I remember correctly) you can use the SimpleXML nodes as if they were arrays, so you could just use array functions to get the last node. It's a while since I used PHP but you should be able to get the length and then get the item at length-1...

Edit: You can of course use XPath too, I thought I should mention that too but I wasn't sure if last() worked in the SimpleXML XPath implementation.

I'm not sure wich is fastest, using array indexes or XPath, I would guess that array indexes were faster but you should try both in a loop a few thousand times getting the time before and after the loop to check.

But as allways in CS: what you choose depends on many things.

Is it time critical or used very often: then find the fastest solution.

If you will need more complicated queries and speed isn't an issue: then use whatever is easiest to implement and gives the power you need (XPath is good for complex tree navigation, array indexing is good for quick random access in list-type datastructures; XML can be used for both.)




回答6:


As it was already mentioned, you can use array notation and functions.

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

or

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

You can also use end() to get the last element but only if you always have more than one <obj>, otherwise it will return different result.



来源:https://stackoverflow.com/questions/295112/php-simplexml-how-to-get-the-last-item

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!