[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?
Thanks,
Gabriel
More information about the Twisted-Python
mailing list