I've been thinking I could make it into a module. It could be used like:
package Some::Node;
use Class::XPath
get_parent => 'parent',
get_root =>
sub { local $_ = shift;
while($_->parent) {
$_ = $_->parent
}
return $_;
},
get_name => 'name',
get_kids => 'children',
get_attr => 'attr';
Then clients of Some::Node can do:
@nodes = Some::Node->match('/foo/bar[1]/*');
The idea being that you give Class::XPath some instructions on how to perform various operations - either in the form of method names or as subroutines. Then Class::XPath creates customized versions of xpath() and match() that work with your class.
The value-add here is the XPath parser and executor. At start it would be a straight port of the simple parser I've written already. Later it could grow to include support for more of XPath and learn to optimize match() requests using caches and such. Then others can enjoy the benefits of having full XPath support for their trees without much work at all.
Feedback would be appreciated. Would you use such a module?
-sam
Tree Matching? (Score:2, Informative)
I just wrote B::SAX yesterday (yes, it fires SAX events based on traversing a compiled Perl optree). Is it possible to run XPath over SAX events?
Otherwise, I'll have to write a little state machine to find the subtree I'm seeking. That doesn't sound too awful, but the less work, the better.
Re:Tree Matching? (Score:2)
Either that or build a DOM (using something like XML::LibXML::SAX::Builder) and go from there.
yup (Score:3, Informative)
I'd love to
I can also imagine that it would also be handy to have the module work without having Some::Node's author build in support. This could allow your code to work with modules which were written before your release, and modules that didn't feel like adding yet another feature.or maybeIf get_attr is supposed to return a list of attributes, then you'll probably need a get_attr_value or something too.
On the other hand, if get_attr is expected to take an attribute name and return a value (or undefined if the attribute does not exist) then there may be a problem in situations where the underlying object may allow for undef to be a reasonable value for an attribute. For example, if someone wanted to use Class::XPath to traverse a messy perl data structure, some of the values might well be undef.
I'm curious: how does XPATH handle meta-character escapes? I'm imagining the case of applying it to some representation of a CSS document. A selector's value may well contain a whole host of XPATH-looking syntax. You may want to expose an escape method, or alternate versions of each method (one which escapes the path/attr, one which does not).
In any case, I think the module is a great idea. It seems like a very sensible abstraction that lets XPATH work happen in one place and allows everyone the option of bolting XPATH support onto their project.
-matt
Reply to This
Re:yup (Score:1)
How about maybe:
Class::XPathcan be designed to be mixed-in to any arbitrary class, and simply provide amatchmethod. Seems much simpler.(darren)
Re:yup (Score:2)
-sam
Re:yup (Score:1)
I wasn't disgreeing with the need for configuration, just the need usage examples. I was suggesting something more like:
Though I would suggest that a good default
matchmethod would be one that could automatically walk a data structure (i.e., didn't use metho(darren)