Ralph Meijer wrote: > On Wed, 2008-02-20 at 10:36 +0100, Gabriel Rossetti wrote: > >> [..] >> >> I'm having some trouble with the XPath I think when trying to react on >> xml messages. I am feeding the twisted.words.xish.xmlstream.XmlStream >> the following : >> >> <?xml version="1.0" encoding="utf-8"?> >> <test><feed name='monNom'>toto</feed></test> >> >> and the callback functions are : >> >> def onTest(self, element): >> print "got test : ", element >> >> def onFeed(self, element): >> print "got feed : ", element >> >> def onFeedFilteredByName(self, element): >> print "got feed name : ", element >> >> def onWildcard(self, element): >> print "got wildcard : ", element >> >> and the bootstrap is added like so : >> >> f.addBootstrap(xmlstream.STREAM_START_EVENT, connected) >> >> and the bootstrap callback is : >> >> def connected(self, xs): >> print 'Connected!' >> xs.addObserver("/test", self.onTest) >> xs.addObserver("/test/feed", self.onFeed) >> xs.addObserver("/test/feed[@name]", self.onFeedFilteredByName) >> xs.addObserver("/*", self.onWildcard) >> >> The only one that gets called is "/*". I tested out the others using >> XPathQuery manually with : >> >> xpath.XPathQuery("//feed[@name]").queryForNodes(root)[0] >> >> root being the above xml, and they work, I can even get the attributes >> (which is what I really need to get) like so : >> >> >> xpath.XPathQuery("//feed[@name]").queryForNodes(root)[0].getAttribute("name") >> >> What am I doing wrong when adding observers? How can I get them to react >> on attribute names too? >> > > Hi, > > A somewhat lengthy explanation follows, > > XML Streams are a result of the work on Jabber. As such, the generalized > version of XmlStream in xish works similarly, but without the Jabber > specifics in terms of namespaces and elements. However, the concept > behind XML Streams is that you open the stream with a root element, and > after that the units of exchange are the first-level childs of that root > element, or so-called XML Stanzas. > > EventDispatcher, a superclass of XmlStream, is responsible for calling > back observers upon calls to its dispatch method. For each XML Stanza, > XmlStream will dispatch the DOM object at the root of that snippet of > XML (domish.Element) for the XML Stanza. Observers are registered to > XPath (-like) queries to match those Elements. > > Now that's out of the way, in your specific example, the <feed/> element > would be an XML Stanza. So you can only register an observer to that, > like this: > > xs.addObserver('/feed', self.onFeed) > > If some <feed/>'s would have child <title/>, you could add an observer > on just those <feed/>'s with a title like this: > > xs.addObserver('/feed/title', self.onFeedWithTitle) > > The observer would still get the whole <feed/> element passed. So, to be > clear: the XPath-like queries are for matching against XML Stanzas, and > each XML Stanza that matches is then passed to the callbacks registered > to that query. > > For completeness, ff you want to hook up an event to the start tag of > the root element having been received, you'd do this: > > xs.addObserver(STREAM_START_EVENT, self.onTest) > > In that case, you need to do change the bootstrap registration to this: > > f.addBootstrap(xmlstream.STREAM_CONNECTED_EVENT, connected) > > Hope that clears some things up. > > Ralph, Thank you! Your explanation cleared up a lot for me, I had misunderstood the whole thing, this is exactly what I needed. Thanks again, Gabriel