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