[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