Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.php > #14178

Re: Extracting values from xml file using php/xpath/namespace/simplexml/

From Thomas 'PointedEars' Lahn <PointedEars@web.de>
Newsgroups comp.lang.php
Subject Re: Extracting values from xml file using php/xpath/namespace/simplexml/
Date 2014-08-17 23:41 +0200
Organization PointedEars Software (PES)
Message-ID <13165688.lB41CWTE6m@PointedEars.de> (permalink)
References <a8eb7607-8c39-4062-917c-d815b223a021@googlegroups.com> <lsfp0k$cpj$1@dont-email.me> <b2d1ddf1-3b88-4f33-9336-d5f77ea186f4@googlegroups.com> <1443898.x2o4gcXilq@PointedEars.de> <lsqvb1$rpq$1@dont-email.me>

Show all headers | View raw


Jerry Stuckle wrote:

> On 8/17/2014 1:43 PM, Thomas 'PointedEars' Lahn wrote:
>> You do not have to register namespaces that you do not use in your XPath
>> query.  See below.
> 
> It doesn't hurt - and if he wants to use them in the future, he's
> already got it.  I often register namespaces I don't need *immediately*.

Premature "optimization"…
 
>>> $xpath->registerNamespace('dc', 'http://purl.org/dc/elements/1.1/');
>>>
>>> $records = $xpath->evaluate('/oai:OAI-PMH/oai:ListRecords/oai:record',
>>> NULL, FALSE); foreach ($records as $entry) {
>>>   // […]
>>>   $dc = $xpath->evaluate('oai:metadata/oai-dc:dc/dc:*', $entry, FALSE);
>>>   foreach ($dc as $dcElement){
>>>     switch ($dcElement->localName) {
>>>     case 'title' :
>>>       echo 'Title: '.$dcElement->nodeValue;
>>>       echo "\n";
>>>       break;
>>>     case 'date' :
>>>       echo 'Date: '.$dcElement->nodeValue;
>>>       echo "\n";
>>>       break;
>>>     case 'relation' :
>>>       echo 'Relation: '.$dcElement->nodeValue;
>>>       echo "\n";
>>>       break;
>>>
>>>     }
>>>   }
>>> }
>>> ?>
>> 
>> You do not have to specify the whole path with XPath if you are certain
>> of uniqueness (or content with iteration over content-duplicates is
>> acceptable), and you certainly do not have to iterate over elements to
>> find
>> matches.  All of this is built into XPath, see the XPath 1.0
>> Specification [0], particularly the “Location Paths” section.
> 
> Again, it's a good idea to specify the whole path.

No, it is not.  It makes the code very inflexible at no advantage.  For 
example, no elements will be found if the full path is specified and the 
namespace prefix or the namespace URI changes.  Of course, if the prefix is 
not allowed to change you can find out the URI by reading the namespace 
attribute, but it would still be an unnecessary step because the pertaining 
elements are not of interest here.

> Unless he created the XML file, he can't ensure that it will be unique. 

It is not possible to apply XPath to a document whose basic structure is 
unknown in any case, so that is a specious argument.

If the target elements are not unique, but exist pair-wise per “record” 
element (which can be assumed here), the result will be the same because 
SimpleXMLElement::xpath() always returns an array.

However, if that cannot be guaranteed or not only the first match is of 
interest, then the best (shortest, most efficient) approach is to first find 
the ancestors that are not unique, and then use them as context nodes:

  foreach ($xml->xpath('./ListRecords/record') as $record)
  {
    $title = $record->xpath('.//dc:title')[0];
    $date  = $record->xpath('.//dc:date')[0];

    /* do something with $title and $date */
  }

It certainly is _not_ to reinvent the wheel^WXPath query engine like the OP 
did.

> As for iterating over the elements - it's not uncommon to do it that way. 

It is uncommon to do it the way of the OP among those who know both XPath 
and the DOM well.

> Otherwise you have to check to ensure each element exists before using it. 

No, one does not have to.  That’s the beauty of it.

> By iterating, you can set default values and change those which exist.

One can do that anyway.
 
> Of course, if you have 100 elements and are only interested in 2-3 of
> them, this is way inefficient.  However, if you have 5 elements and want
> all of them, it can be more efficient and is definitely shorter.

The proof is in the pudding.  My first suggestion had 4 statements in 5 
lines.  My new suggestion has 3 statements in 7 lines, not counting the 
instantiation and namespace registration.  How many had the OP’s?  How many 
would it have if rewritten to use SimpleXMLElement but keeping the same 
approach?
 
>> Here it is with SimpleXMLElement, which you can apply to your DOMDocument
>> approach, too:
>> 
>> <?php
>>   $xml = new SimpleXMLElement('tmp/test-oai.xml', 0, true);
>>   $xml->registerXPathNamespace('dc', 'http://purl.org/dc/elements/1.1/');
>>   echo $xml->xpath('.//dc:title')[0] . PHP_EOL;
>>   echo $xml->xpath('.//dc:date')[0] . PHP_EOL;
> 
> Which will give an E_NOTICE if the path does not exist.

You mean it would issue “PHP Notice: Undefined offset: 0”?  Yes.  But that 
would not appear in production because the recommended production setting 
includes “& ~E_NOTICE”; whereas E_NOTICE is an error constant, not a message 
type.
 
The result of the array element access would be “null”, where the suggested 
defaults could take effect:

  $title = ($record->xpath('.//dc:title')[0] ?: '(unknown)');
  $date  = ($record->xpath('.//dc:date')[0]  ?: '(unknown)');

> To the OP:
> 
> Better yet […] post just like you did before.  There was nothing wrong
> with your post.

I have stated what was wrong.  It is there for all to see.  Why do you want 
to mislead them?  And why do you think name-calling is going to achieve 
that?

-- 
PointedEars
Zend Certified PHP Engineer
Twitter: @PointedEars2
Please do not Cc: me. / Bitte keine Kopien per E-Mail.

Back to comp.lang.php | Previous | Next — Previous in thread | Next in thread | Find similar | Unroll thread


Thread

Extracting values from  xml file using php/xpath/namespace/simplexml/ ofuuzo@gmail.com - 2014-08-13 04:02 -0700
  Re: Extracting values from  xml file using php/xpath/namespace/simplexml/ Jerry Stuckle <jstucklex@attglobal.net> - 2014-08-13 09:25 -0400
    Re: Extracting values from  xml file using php/xpath/namespace/simplexml/ ofuuzo@gmail.com - 2014-08-14 03:29 -0700
      Re: Extracting values from  xml file using php/xpath/namespace/simplexml/ Jerry Stuckle <jstucklex@attglobal.net> - 2014-08-14 10:06 -0400
      Re: Extracting values from  xml file using php/xpath/namespace/simplexml/ Thomas 'PointedEars' Lahn <PointedEars@web.de> - 2014-08-17 19:43 +0200
        Re: Extracting values from  xml file using php/xpath/namespace/simplexml/ Jerry Stuckle <jstucklex@attglobal.net> - 2014-08-17 15:21 -0400
          Re: Extracting values from  xml file using php/xpath/namespace/simplexml/ Thomas 'PointedEars' Lahn <PointedEars@web.de> - 2014-08-17 23:41 +0200
            Re: Extracting values from  xml file using php/xpath/namespace/simplexml/ Jerry Stuckle <jstucklex@attglobal.net> - 2014-08-17 18:57 -0400
              Re: Extracting values from  xml file using php/xpath/namespace/simplexml/ Thomas 'PointedEars' Lahn <PointedEars@web.de> - 2014-09-03 23:10 +0200
                Re: Extracting values from  xml file using php/xpath/namespace/simplexml/ Jerry Stuckle <jstucklex@attglobal.net> - 2014-09-03 20:11 -0400
                Re: Extracting values from  xml file using php/xpath/namespace/simplexml/ "Christoph M. Becker" <cmbecker69@arcor.de> - 2014-09-04 02:42 +0200
                Re: Extracting values from  xml file using php/xpath/namespace/simplexml/ Jerry Stuckle <jstucklex@attglobal.net> - 2014-09-03 21:57 -0400
                Re: Extracting values from  xml file using php/xpath/namespace/simplexml/ Thomas 'PointedEars' Lahn <PointedEars@web.de> - 2014-09-04 23:21 +0200
                Re: Extracting values from  xml file using php/xpath/namespace/simplexml/ Jerry Stuckle <jstucklex@attglobal.net> - 2014-09-04 20:43 -0400
                Re: Extracting values from  xml file using php/xpath/namespace/simplexml/ "Christoph M. Becker" <cmbecker69@arcor.de> - 2014-09-05 04:08 +0200
                Re: Extracting values from  xml file using php/xpath/namespace/simplexml/ Denis McMahon <denismfmcmahon@gmail.com> - 2014-09-05 02:50 +0000
                Re: Extracting values from  xml file using php/xpath/namespace/simplexml/ Jerry Stuckle <jstucklex@attglobal.net> - 2014-09-05 08:24 -0400
                Re: Extracting values from  xml file using php/xpath/namespace/simplexml/ Thomas 'PointedEars' Lahn <PointedEars@web.de> - 2014-09-07 11:57 +0200
                Re: Extracting values from  xml file using php/xpath/namespace/simplexml/ Jerry Stuckle <jstucklex@attglobal.net> - 2014-09-07 09:54 -0400
                Re: Extracting values from  xml file using php/xpath/namespace/simplexml/ "M. Strobel" <sorry_no_mail_here@nowhere.dee> - 2014-09-07 23:53 +0200

csiph-web