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


Groups > comp.lang.php > #14211

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-04 23:21 +0200
Organization PointedEars Software (PES)
Message-ID <2974602.zgg0cvazeg@PointedEars.de> (permalink)
References (4 earlier) <lsqvb1$rpq$1@dont-email.me> <13165688.lB41CWTE6m@PointedEars.de> <lsrc1c$enm$1@dont-email.me> <35250817.Fx3NucNZ4e@PointedEars.de> <lu8ao0$ha6$1@dont-email.me>

Show all headers | View raw


Jerry Stuckle wrote:

> On 9/3/2014 5:10 PM, Thomas 'PointedEars' Lahn wrote:
>> 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.
> 
> No, it is not - which you would know if you understood what premature
> optimization is.  But we also know you don't.

- Premature optimization is the root of all evil[tm].
- It is not optimization.
- Yes, it is, because …
- No, it's not.

I really don't have time for such a "discussion".  I have better things to 
do, like being paid for creating robust software and making existing 
software more robust.

>>> 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*.
> 
> Not if the code is designed correctly - as the OP has done.  His code
> will catch ALL elements - not just the first.

As will making full use of XPath, without a filtering loop.

(You appear to have a serious problem with understanding conditional 
statements, and I do not mean PHP.)
 
>>> 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
> 
> It does not lead to PHP syntax errors.

You had not claimed there would be a *syntax* error, you have claimed there 
would be an error.  Assuming that the object of a rebuttal would be what you 
have not claimed, is a fallacy.

There is no error in that case; the behavior will be exactly the same 
regardless whether you used a full path.  Now you are trying to muddy the 
issue so that you do not have to admit that you were wrong in the first 
place.

> But it does lead to errors in the code.

Using the full *potential* of XPath instead of a filtering loop does not 
lead to more errors in the code.  Using the full *path* instead of the 
context node approach does _not_ lead to less errors, because the XPath 
Specification and its implementations simply do not care.  If the 
syntactically correct XPath does not match a node, for whatever reason,
the result is empty and and query does not result in an error.

>>> 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).
> 
> Exactly.  And his code does that.

Yes, to a degree.

> Yours does not.

Plain wrong.

>> 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.
> 
> Yes, but with his code he will be able to detect an error,
> and figure out what changed in the XML.  He will then be able to change
> his code to resolve the difference.

No, in general he will not.  If the XPath result is empty, execution will 
not enter his filtering loop.

> In your code he will have no idea there was a change - which can result
> in a very difficult to detect (and correct) problem.

Without changing their code, they will have no idea that there was a change 
in the markup either way.  The “foreach” will be a *no-op* either way.  The 
difference is, though, that with the context node approach there is no need 
to iterate over elements that are eventually ignored.  This makes the 
context node approach more efficient than a filtering loop.

Also, the filtering loop only considers child nodes.  Should the markup 
change so that the data nodes are no longer child nodes, but other 
descendants, the context node approach will still work (BTDT), and the 
filtering loop approach will not.  This makes the context node approach more 
robust than the filtering loop approach.
 
>>>> 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.
> 
> Yes, I KNOW what it returns (better then YOU DO, obviously).

How come then that you do not see that if the path cannot be matched, with 
the *current* code of the OP there is *no way* to detect why?

> But the element you are interested in may NOT be the first one - there is
> NEVER a guarantee that is the case.

I am aware of that.  Your problem is not understanding or not wanting to 
understand conditional statements in an argument.  Hopefully the former.
 
> You are assuming the first element is always the one the OP wants.

I am not.

> That is generally NOT the case in XML - which is why each element has an
> identity as well as a value.

Nonsense.
 
> Optional elements may be placed before or after the desired element.

True.
 
> It's also pretty obvious you don't understand XML at all.

Is that so?  Then point out to me the sections in the XML Specification that 
back up your claim “every element has an identity as well as a value”.
 
>>>> 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 */
>>>>   }

(There, you quoted it.  Do you *still* want to deny that?)

>>> 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.
> 
> We can assume he has a fair idea of the CURRENT PATH.  But now you're
> arguing that he use the full path

I am not.  I wrote “full potential of XPath”, not “full path”.
Big difference.

> - which is just the opposite of what you argued before.

Wrong.

> Once you have the full path, the loop will pick out the correct values
> based on the identity of the element. [snip nonsense]

XML elements do not have identity.  You are confusing this with objects, 
presumably.

>>>> 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*.
> 
> Once again, unless he has hundreds of elements, it is not inefficient.

But you do not know that he does not have hundreds of elements.  So in 
general you cannot make the *sound* claim that it would not be inefficient.  
In general it is, compared to making full use of XPath.

> But now it is YOU who is prematurely optimizing.

No.  It is a mistake to use XPath but not use its full potential.

>>>>> 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.
> 
> Yes, you do.

No, if the path cannot be matched, the result is empty.  And there is no 
error if any prefix subset of the path cannot be matched.  For example, 
assume the following XML document:

  <foo>
    <bar>
      <baz />
    </bar>
  </foo>

The result of the XPath query '/foo/bla/baz' is as empty as is that of 
'/foo/bar/bla', and neither results in an error, even though there is no 
“bla” element as child element of the “foo” element.

IOW, with XPath one does *not* need to test for the existence of the “bla” 
element in that context before querying its potential children.  This is 
different with manual tree traversal, which is therefore more error-prone.

> Correct programming practice (which I know you neither understand nor
> observe) requires checking for the existence of a value before using it.

But we are not talking about a general programming case, we are talking 
about XPath, a very specific technology to access very specific (usually 
XML-based) information.

Maybe you mean something else with “testing”.

>>>>> 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. 
> 
> I didn't bother to quote your error-prone code,

Do you take delight in denial?  You did quote my code (at least twice now); 
and as for its error-proneness, you are wrong.

> which by your own admission will produce E_NOTICE messages. 

I have not admitted anything of the sort.  I could not have, because 
E_NOTICE still is an error constant, not a message type, to begin with.

> And these are always potential errors in the code logic. 

So you claim again.  But notices are not “always potential errors in the 
code logic”, nor do they signify such.

> Why do you think Zend went to the trouble of creating these messages?

First of all, it was not Zend who created any messages.  Second, contrary to 
other people, I carefully avoid such intentional fallacies.  See also 
<https://en.wikipedia.org/wiki/Authorial_intent>.
 
>> 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.
> 
> And exactly which circumstances are those? You haven't explained
> anything that describes the unexpected results.  All you've done is say
> your error-prone code is "better".

You need to read more carefully.

>>> 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.
> 
> It will fail if the XPATH changes.  But then that can easily be
> detected.

Only by changing their code.

> Your code will not catch a problem where there are duplicate
> elements in different XPATHs, for instance.  It is full of holes.

My code (the second way) was an example on how to use XPath's context node 
mechanism to avoid a filtering loop; it was not intended as a complete 
solution, nor did I claim that it were.  That you do not understand the 
context node mechanism and projecting your apparent ill will to everyone
who happens to disagree with you, is not my problem.

That said, the OP’s code needs adjustment as well if it is to handle that 
which you call “duplicate elements” (how can there be *duplicates* if 
elements have *identity*, as you also claimed?).

>>> [A notice] indicates a potential bug in the code.
>> Not always.
> 
> It ALWAYS indicates a *potential* bug in the code.  That's why it is
> there.

So you claim again.  And again, where is the evidence to back that up?

>>> 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.
> 
> It is not a SYNTAX error.  But it almost always indicates a logical
> error in the code.

Interesting, now it is “*almost* always” already.  Will it be “sometimes” 
the next time you repeat yourself without evidence to back your statement 
up?  And when will it have become “possibly”?
 
>>> But once again you don't understand good coding practices.
>> My CV says otherwise.
> 
> Who gives a damn about what you put in your CV?

For example, the people who employ me *because* I am known to write very 
clean code (to the extent that several people in the developer community 
find the degree of my defensive coding excessive).

Passing the ZCPE exam and getting certified, which I did (as you can also 
find in my CV as well as the ZCE Directory), also requires thorough 
understanding of that subject.  I can only recommend to you that you prepare 
for, take and hopefully pass that exam which, as far as I can see, at least 
the latter you did not yet.

Preparing for the exam already hones those skills.  Zend provides online 
exam preparation courses, which, from my own experience, I can very much 
recommend taking, too.  I would recommend them especially to you because 
that way you will get to know PHP developers from all over the world and 
lose your destructive “I am always right, everyone else is always wrong” 
attitude very quickly, finally.

>>> You think that just because a message can be suppressed it's not a
>>> potential problem.
>> It is no problem *here*.
> 
> I'm glad I don't have to clean up after any of your code.

Me too.

> And I pity your customers.  Do they know how bad you really are?

I will caution you one last time: Such statements border on, or are, libel.

>>>> 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.
> 
> If you don't suppress E_NOTICE, it will be generated.  Suppressing the
> message does not mean a potential problem does not exist.

First of all, will you please get your terminology right?  You cannot 
*suppress* E_NOTICE; it is an *error constant*.  You can suppress *(PHP) 
notices* by bitwise-OR of an error_reporting value with the negation of that 
constant (or its value, but that is error-prone), or the “@” prefix to an 
expression.

Second, while it is correct to say that suppressing a message does not mean 
a potential problem does not exist, the converse is not true; therefore, 
your argument is fallacious.
 
> Hopefully some potential clients of yours will also see this and go
> somewhere else - where they will get a GOOD programmer.

Someone who fails at simple logic like that, I presume?

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