sKunKbad Posted February 14, 2014 Share Posted February 14, 2014 First, let me point out that I am familiar with parsing namespaced XML with SimpleXML. For the purposes of iteration over XML, which I want to assume I know nothing about, when the element is namespaced SimpleXmlIterator constructor throws an error, saying that the namespace is not defined. So I define the namespace, and no more error being thrown, but the iteration skips the namespaced element, like it doesn't know what to do with it. I realize that under normal parsing circumstances, I would use getNamespaces and use the namespace to access the element, but I declare that manually, like this: // Vanilla SimpleXML usage to get namespace, apply it to a var, then use the var to get the element contents $namespaces = $feed->getNamespaces(true); $yweather = $feed->channel->children( $namespaces['yweather'] ); echo $yweather->location->attributes()->city; But for the purposes of a generic XML iterator, I can't manually apply the namespaces. So, what I want to know is, in the code below, what would be the best way to get the namespaces and use them, with the intent to iterate over any namespace. As long as the XML is well formed, I'd like to convert it to an array, or use the data in some other way. function xml2array( $fname ) { $sxi = new SimpleXmlIterator( $fname ); return sxiToArray( $sxi ); } function sxiToArray( $sxi ) { $a = array(); for( $sxi->rewind(); $sxi->valid(); $sxi->next() ) { if( ! array_key_exists( $sxi->key(), $a ) ) { $a[ $sxi->key() ] = array(); } if( $sxi->hasChildren() ) { $a[ $sxi->key() ][] = sxiToArray( $sxi->current() ); } else { $a[ $sxi->key() ][] = strval( $sxi->current() ); } } return $a; } Now, I'm not looking for a solution that uses DOMDocument or other unrelated classes. I'm just curious about SPL classes/iterators, and doing some studying. What do you do when your iterator encounters an unknown namespace, and you must get the values it holds (and even do recursive iterations inside that)? I'm still trying to figure out some good use cases for these SPL iterators. That's why I'm focusing on the XML to array code above. Quote Link to comment Share on other sites More sharing options...
sKunKbad Posted February 15, 2014 Author Share Posted February 15, 2014 I'm getting closer to having an expected result, although the method isn't really using SimpleXmlIterator the way I think it should. I'm getting those unknown namespaces and using them nicely. The issue now is that XML can have more than one of the same element, but an array can't. I've got to get to my real job, but this is what I've got now: public function to_array( $xml, $r = NULL, $namespace = NULL ) { if( is_string( $xml ) ) { $sxi = new \SimpleXmlIterator( $xml ); } else { $sxi = $xml; } $namespaces = $sxi->getNameSpaces( TRUE ); $el = $sxi->getName(); $r[ $el ] = strval( $sxi ) ? trim( strval( $sxi ) ) : []; // Do regular children foreach( $sxi->children() as $k => $v ) { $r[ $el ] = $this->to_array( $v, $r[ $el ], '' ); } // Do regular attributes foreach( $sxi->attributes() as $k => $v ) { $r[ $el . '_attrs'][$k] = "$v"; } // Do children and attributes of namespaces foreach( $namespaces as $pre => $ns ) { foreach( $sxi->children( $ns ) as $k => $v ) { $r[ $el ]['_' . $pre] = $this->to_array( $v, @$r[ $el ]['_' . $pre], $pre ); } } return $r; } Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.