Jump to content

SimpleXmlIterator and namespaces


sKunKbad

Recommended Posts

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.

 

Link to comment
Share on other sites

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;
}
Link to comment
Share on other sites

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.