php - SimpleXML children's attributes behaves different with and without namespace -
the simplexml examples page, section "example #5 using attributes" states:
access attributes of element elements of array.
and example #1 in simplexmlelement::children()
works using $element['attribute']
syntax access children's attributes;
adding namespace code, disable access attributes:
$xml = new simplexmlelement( '<person xmlns:a="foo:bar"> <a:child role="son"> <a:child role="daughter"/> </a:child> <a:child role="daughter"> <a:child role="son"> <a:child role="son"/> </a:child> </a:child> </person>'); foreach ($xml->children('a', true) $second_gen) { echo ' person begot ' . $second_gen['role']; foreach ($second_gen->children('a', true) $third_gen) { echo ' begot ' . $third_gen['role'] . ';'; foreach ($third_gen->children('a', true) $fourth_gen) { echo ' , ' . $third_gen['role'] . ' begot ' . $fourth_gen['role']; } } } // results // person begot begot ; person begot begot ; , begot // expected // person begot son begot daughter; person begot daughter begot son; , son begot son
there's plenty of questions here pointing same solution, use simplexmlelement::attributes()
function instead of accessing array, none answers explains why.
this different behavior when using namespaces bug? documentation outdated? should use simplexmlelement::attributes()
, avoid recommended array-like syntax?
note: i'm using php 5.5.9-1ubuntu4.9
.
related questions
the reason not simplexml, surprising details of how xml namespaces work, according standard.
in example, have namespace declared prefix a
, declare attribute in namespace, must prefix name a:
, elements:
<a:child a:role="daughter"/>
it seems common assumption attribute without namespace prefix in same namespace element on, not case. example above not equivalent example:
<a:child role="daughter"/>
another case might see there in default (unprefixed) namespace:
<person xmlns="http://example.com/foo.bar"><child role="daughter" /></person>
here, child
element in http://example.com/foo.bar
namespace, but role
attribute still isn't! discussed in this related question, relevant section of xml namespaces spec includes statement:
the namespace name unprefixed attribute name has no value.
that is, an attribute no namespace prefix never in namespace, regardless of rest of document looks like.
so, what effect have on simplexml?
simplexml works on basis of altering "current namespace" whenever use ->children()
or ->attributes()
methods, , tracking on.
so when write:
$children = $xml->children('a', true);
or:
$children = $xml->children('http://example.com/foo.bar');
the "current namespace" foo:bar
. subsequent use of ->childelement
or ['attribute']
syntax in namespace - don't need call children()
again every time - but unprefixed attributes won't found there, because have no namespace.
when subsequently write:
$attributes = $children->attributes();
this interpreted same way as:
$attributes = $children->attributes(null);
so now, "current namespace" null
. when attributes have no namespace, find them.
Comments
Post a Comment