解析类似XMPP的XML流的最佳方法是什么?

问题描述:

我正在研究一个服务器应用程序,它通过一个类似XMPP的XML格式的TCP套接字接收数据,也就是说,<root>元素的每个孩子都基本上代表一个单独的请求(节)。一旦收到</root>,连接就会关闭。 我知道我必须以某种方式使用像SAX这样的流解析器。尽管为了方便起见,我宁愿有一个树形界面来访问每个节的子元素。 (每次请求发送的数据都不是很大,所以我认为将每个节作为一个整体进行读取是有意义的。)解析类似XMPP的XML流的最佳方法是什么?

在Python(最好是v3)中实现这一点的最佳方式是什么?

这是我想要构建它的代码。随意指向一个完全不同的方向来解决这个问题。

import socketserver 
import settings 

class MyServer(socketserver.ThreadingMixIn, socketserver.TCPServer): 
    pass 

class MyRequestHandler(socketserver.StreamRequestHandler): 
    def handle(self): 
     pass 

if __name__ == '__main__': 
    server = MyServer((settings.host, settings.port), MyRequestHandler) 
    server.serve_forever() 

您将需要使用基于推送的解析器来发出SAX事件。基本上你需要一个解析器,你可以用一部分数据调用pushChunk(data),并为它生成一段第一级子结束标记事件的事件处理程序。然后可以将其发送到应用程序处理逻辑。

如果你想看到这样的一个例子,这里是libstrophe Expat解析器,一个XMPP客户端库我写道: http://github.com/metajack/libstrophe/blob/master/src/parser_expat.c

号楼为每节整个文档是相当昂贵的。可以使用单个解析器实例来实现此功能,而不是为每个节创建新的文档解析器。

如果您需要一个可用的Python版本,您可以使用或从Twisted Words(twisted.words.xish我相信)中提取代码。

+0

另一个诀窍是使用单个元素指针作为当前位置的堆栈。当你得到一个新的元素事件时,你在你的dom中创建一个元素。如果堆栈不为空,则将此元素作为子元素添加到堆栈元素,并将堆栈指针设置为新元素。当你得到一个结束元素事件时,你将堆栈指针设置为当前堆栈指针的父元素。如果在此操作结束时堆栈指针为零,则您有一个节。注意:这是杰克的代码与上面或多或少有关联。 – 2010-05-05 05:27:53

+0

以防万一任何人需要此解决方案的Python解决方案:http://*.com/questions/1459648/non-blocking-method-for-parsing-streaming-xml-in-python(该帖子标记为接受的答案) 。 – balu 2010-05-19 23:20:52

我们为Skates什么是我们使用SAX解析器来构建流,但使用这个解析器接收到的每个节建立一个整个文档。