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

Gabriel Rossetti mailing_lists at evotex.ch
Wed Feb 20 10:34:09 EST 2008


Gabriel Rossetti wrote:
> 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 forgot to say that when I say send it back, it may be also sent to 
another server instead of back to the client that originally sent it, 
kind of like a forwarder that modifies some of the data before sending 
it along.

> 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?
>
> Thanks,
> Gabriel
>
> _______________________________________________
> Twisted-Python mailing list
> Twisted-Python at twistedmatrix.com
> http://twistedmatrix.com/cgi-bin/mailman/listinfo/twisted-python
>





More information about the Twisted-Python mailing list