Using SimpleXMLIterator with a Iterator Filter.

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi.

I can never seem to get the SPL right in my head.

So, I hope someone can help.

I have many XML streams that I can use SimpleXMLIterator on.

Each streams is structured slightly differently.

Some streams contain unused data and may or may not hold the data at
the same level in the stream.

I need to be able to filter out specific nodes on a per stream basis.

So, for example, in 1 stream, I only want to examine the /entry nodes,
not the /title, /id nodes.

In another, only the /products/product nodes.

Currently, code along the lines of the snippet below is functional ...

<?pseudo-php
// Get the stream.
$o_Stream = new SimpleXMLIterator($s_URL, 0, True);

// Add an xpath() filter if necessary.
if ('xxxx' === $s_URL) { $o_Stream->xpath('/products'); }
... (repeat as required for each URL that requires it)

// Iterate the stream.
foreach($o_Stream as $s_Tag => $o_Element) {
 // Filter out the unwanted tags, based upon the stream url.
 if ('xxxx' === $s_URL && 'entry' === $s_Tag) {
  // Process $o_Element
  $o_Product = new \FS\Product();
  $o_Product->id = (string)$o_Element->id;
  ... (process the remaining properties of the element into the product).
 }
 ... (repeat the filtering of the tags for each stream url)
}
?>

Whilst the code above works it is unwieldy and is getting more and
more complex as new streams become available. And so I need to
refactor it.


I would like to remove the specifics of the filtering and the
processing to a point that I can take a feed URL and a filter and get
back Products, irrespective of the feed or filter. e.g.

<?php
// Iterate the DB, getting the FilterClassName and the associated URL.
foreach($o_DB->getStreams() as $o_StreamInfo) {

  // Iterate the products for the URL (post filtering).
  foreach(new $o_StreamInfo->s_FilterClassName($o_StreamInfo->s_FeedUrl)
as $o_Product) {

    // The product is standardised irrespective of the feed or the filter.

  }

}

?>

(As an aside, the
$o_StreamInfo->s_FilterClassName($o_StreamInfo->s_FeedUrl) line works
fine. A property of a class containing the name of a class to be
instantiated.)



I cannot work out do I use FilterIterator or RecursiveFilterIterator
or something other.

I expect to have at least 1 concrete class per filter - some will be
shared amongst multiple streams. There may be an abstract base class
to consolidate any duplication.

I may also need a mapper class to take the data from the stream and
present it as a standardised Product. I suppose they are 2 separate
concerns and could be treated as such. At the moment, I do not have a
need to have a mapper apply to different streams structures, so
combining the mapper and the filter into 1 entity does work with the
existing data I have. But I think having them separate will help in
the long run.


But I just can't seem to get my head around this.

I think applying a filter to the SimpleXMLIterator is causing the
filter to examine every node. This is not what I want.


Any ideas, suggestions, reading. I've got the manual but the iterator
documentation isn't great. I don't know who knows this stuff inside
out, or how to describe things in a useful way for the documentation.

So. Help!

Regards,

Richard Quadling.


-- 
Richard Quadling
Twitter : EE : Zend : PHPDoc : Fantasy Shopper
@RQuadling : e-e.com/M_248814.html : bit.ly/9O8vFY : bit.ly/lFnVea :
fan.sh/6/370

-- 
PHP General Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php




[Index of Archives]     [PHP Home]     [Apache Users]     [PHP on Windows]     [Kernel Newbies]     [PHP Install]     [PHP Classes]     [Pear]     [Postgresql]     [Postgresql PHP]     [PHP on Windows]     [PHP Database Programming]     [PHP SOAP]

  Powered by Linux