【问题标题】:Best way to parse XMPP-like XML streams?解析类似 XMPP 的 XML 流的最佳方法?
【发布时间】:2011-02-14 01:26:22
【问题描述】:

我正在开发一个服务器应用程序,它通过 TCP 套接字以类似 XMPP 的 XML 格式接收数据,即<root> 元素的每个子元素本质上代表一个单独的请求(节)。一旦收到</root>,连接就会关闭。 我知道我必须以某种方式使用像 SAX 这样的流解析器。不过,为了方便起见,我更喜欢有一个树状界面来访问每个节的子元素。 (每个请求发送的数据并不大,所以我认为将每个节作为一个整体阅读是有意义的。)

在 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()

【问题讨论】:

    标签: python xml stream xmpp network-protocols


    【解决方案1】:

    我们为Skates 所做的是,我们使用 Sax 解析器来构建流,但使用这个解析器为接收到的每个节构建一个完整的文档。

    【讨论】:

      【解决方案2】:

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

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

      为每个节构建一个完整的文档非常昂贵。可以使用单个解析器实例来实现这一点,而不是不断为每个节创建新的文档解析器。

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

      【讨论】:

      • 另一个技巧是使用单个元素指针作为当前位置的堆栈。当你得到一个新的元素事件时,你会在你的 dom 中创建一个元素。如果堆栈不为空,则将此元素作为子元素添加到堆栈元素,并将堆栈指针设置为新元素。当你得到一个结束元素事件时,你将堆栈指针设置为当前堆栈指针的父级。如果在此操作结束时堆栈指针为 nil,则您有一个节。注意:这就是上面链接到的杰克的代码或多或少的作用。
      • 以防万一有人需要 Python 解决方案:stackoverflow.com/questions/1459648/…(标记为已接受答案的帖子)。
      • @JoeHildebrand 你怎么会得到一个零堆栈指针? xmpp xml 流以<stream:stream> 开头,直到断开连接时才会关闭;您将永远以您的节结束,因为您永远不会到达元素的末尾。也许用堆栈扩展你的意思;它是一堆 XmlDomElement 对象吗? (关于 XMPP 最糟糕的部分是必须从头开始重新发明一个完整的 XML 解析器......)
      • 是的,一堆 DOM 元素。这需要相对特定于 XMPP,因为您在启动时跟踪文档的状态,并确保没有任何节实际上是 stream:stream 根的子节。
      猜你喜欢
      • 2010-12-07
      • 2018-01-17
      • 1970-01-01
      • 2011-05-03
      • 1970-01-01
      • 2014-09-02
      • 2015-08-21
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多