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

Gabriel Rossetti mailing_lists at evotex.ch
Wed Feb 20 10:19:52 EST 2008

Gabriel Rossetti wrote:
> 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
> _______________________________________________
> Twisted-Python mailing list
> Twisted-Python at twistedmatrix.com
> http://twistedmatrix.com/cgi-bin/mailman/listinfo/twisted-python
Hi, one more question,

I'm trying to do the following :

receive an xml message, run different actions depending on XML Stanzas, 
modify the original message and send it back. I'm starting to wonder if 
XmlStream is really what I need? If I'm not mistaking, I have no way of 
getting the original message as a whole, correct? And if I'm not 
mistaking, if I have multiple connections, then the events get mixed up 
(from my own tests anyways), the processing is not atomic. If I have 
let's say that I have :

client1 : <test><header  id="1"/>
client2 : <test><header  id="2"/><feed name="myName">toto</feed></test>
client2 : <feed name="myName2">lala</feed></test>

my stanzas will get processed in that order, thus I can't even recreate 
the message (without a complicated state machine of some kind).

I'm kind of mixed up, because when using a thread based network 
framework, one tcp connection = one thread, thus the protocol execution 
is atomic, but this doesn't seam to be the case with Twisted (event 
based), is this correct or have I missed something again?


More information about the Twisted-Python mailing list