[Twisted-Python] Help using XmlStreamFactory & XmlStream : XPathQuery error?

Gabriel Rossetti mailing_lists at evotex.ch
Wed Feb 20 06:08:56 MST 2008


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





More information about the Twisted-Python mailing list