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


Groups > comp.lang.php > #14206

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-09-03 23:10 +0200
Organization PointedEars Software (PES)
Message-ID <35250817.Fx3NucNZ4e@PointedEars.de> (permalink)
References (2 earlier) <b2d1ddf1-3b88-4f33-9336-d5f77ea186f4@googlegroups.com> <1443898.x2o4gcXilq@PointedEars.de> <lsqvb1$rpq$1@dont-email.me> <13165688.lB41CWTE6m@PointedEars.de> <lsrc1c$enm$1@dont-email.me>

Show all headers | View raw


Jerry Stuckle wrote:

> On 8/17/2014 5:41 PM, Thomas 'PointedEars' Lahn wrote:
>> 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"…
> 
> No, it is not optimization.

In a way it is.

> It is planning for future enhancements (and possible reusability).  Good
> design means planning for such - not that YOU would know.

Trying to take care of all possibilities in advance has never been a logical 
approach, nor an economically sound one.  There is such a thing as over-
engineering, and this is it.
 
>>> 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.
> 
> And the wrong path will be found if the elements are not unique.

No, *if* the elements are not unique, only the first element matching the 
path will be found *either way*.

> If you specify the whole path and it is not found, you will get an error. 

No, the return value (XPath result) is (an) empty (array) instead, and the 
block following the “foreach” statement will not be executed – very silently 
even with display_errors set to TRUE/on, error_reporting lit up like a 
Christmas tree, and libxml_use_internal_errors(FALSE).  That querying non-
existing paths does not lead to errors is the very nature of XPath that 
makes it superior to manual tree traversal.  Your statements show a 
fundamental misconception of that technology.

> If you have a non-unique path, you will get very hard to find bugs.

Which is why I said and recommend that *this* is indeed a possibility that 
needs to be taken care of advance, by either always going after the first 
result item or using a loop (unless it explicitly does not matter) on the 
*XPath result* (where items are already filtered).
 
>>> 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.
> 
> He knows the current structure of the document.  He does not know the
> future structure - which is *exactly why he should specify the whole
> path*.

No, because he knows the current structure but not the future one, there is 
no point in providing for future changes because the XPath query needs to be 
rewritten in any case if the structure changes.  Put politely, it is very 
optimistic of you to assume that an XML document can only change in ways 
that do not affect the namespaces or the existing path in general.  In any 
case, the provider of the document, if both they and we know what they/we 
are doing, would have included a way to distinguish the old from the new 
format, such as a version string.
 
>> 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.
> 
> No, the results will only be the same if the values are the same.

You want to read more carefully.  SimpleXMLElement::xpath() *always* returns 
an array (unless the query is *syntactically* in error).  It does not matter 
how many elements that array has *if* you are always interested in the first 
one.  There are only two possibilities: a) it is there, then the array has 
one or more elements; b) it is not there, then the array has no elements.

>> 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 */
>>   }
>> 
> 
> Only if he knows the path he wants.

We can safely assume that he has a fair idea of the path or he would not be 
using XPath.  The (technical) mistake here is to not use the full potential 
of XPath (i.e., to use neither filter conditions nor the context node 
mechanism), and to use a comparably inefficient, error-prone filtering loop 
instead.
 
>> It certainly is _not_ to reinvent the wheel^WXPath query engine like the
>> OP did.
> 
> He did not "reinvent the wheel".  He processed the data correctly.

The processing may have been correct in a way (using nodeValue makes me 
doubt that).  That is not the issue; but that it was inefficient.  There 
simply is no need for a *filtering* loop with XPath; filters are *built* 
*into* *XPath*.
 
>>> 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.
> 
> And what do you do when an element doesn't exist?  You have to test each
> element you're looking at.

Not with XPath.
 
>>> By iterating, you can set default values and change those which exist.
>> One can do that anyway.
> 
> Yes, oh great moron?

Yes, one can.  I had shown it further below, and you had quoted it.
 
>>> 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?
> 
> And both of your suggestions will fail in many instances - like with
> non-unique elements.

There are circumstances in which the first one gives unexpected results;
I have said so and explained why.  The second one does not fail and never 
will.  Both are more efficient and less error-prone than the OP’s 
alternative.

> The op's will not.

There are circumstances in which it will fail.  There are others in which it 
is error-prone, and even others in which it will simply be inefficient 
compared to what a clean XPath solution offers.
 
>>>> 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.
> 
> And the notice is NOT good.

There is no notice then.

> It indicates a potential bug in the code.

Not always.

> That's why E_NOTICE is issued.

Again, E_NOTICE is an error code, not a message type.  It is never issued.  
Your terminology needs revision.

> But once again you don't understand good coding practices.

My CV says otherwise.

> You think that just because a message can be suppressed it's not a
> potential problem.

It is no problem *here*.
 
>> 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)');
>> 
> 
> And gives the E_NOTICE, which you conveniently ignore.

There will be neither E_NOTICE nor notice because no notices are issued in 
the first place.
 
>>> 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?
> 
> You are a pedantic troll, as you have once again proven (and are known
> in multiple newsgroups).  And you again proved you know nothing about
> good coding practices (as you have also proven in multiple newsgroups).

We disagree here; considering our previous exchanges, I am not surprised 
about that.  However, I think at this point the OP, if they are still 
interested, and the dedicated reader in general, will have sufficient 
material to help them decide whose advice is more worthwhile: That of a 
name-calling may-be IT consultant claiming to be a PHP/software 
development/whatnot expert; or that of a factually arguing Zend Certified 
PHP Engineer with more than a decade of hands-on professional Web 
development experience, including 14 years of professional PHP experience, 
under his belt.
 
-- 
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