在Python中从套接字流构建/解析XML文档
我遇到了一个问题,想要解析一个不断发送过来的多个 XML 文档,这些文档是通过一个网络连接(socket)由第三方发送的。下面是通过 socket 发送的 XML 流的一个示例:
<?xml version="1.0"?><event><user id="1098"/><viewpage>109958</viewpage></event>
<?xml version="1.0"?><event><user id="1482"/><actions><edit>102865</edit><commit>1592356</commit></actions></event>
etc.
这是我正在使用的代码:
import socket
import xml.etree.cElementTree as etree
from StringIO import StringIO
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
host = "IP.IP.IP.IP"
port = "8080"
addr = (host,port)
s.connect(addr)
def iparse(packet):
for _, element in etree.iterparse(packet):
print ("%s, %s" %(element.tag, element.text))
element.clear()
#if complete <event> node received, publish node
data = "<feeds>"
while 1:
chunk = s.recv(1024)
#replace the xml doc declarations as comments
data += (chunk.replace("<?","<!--")).replace("?>","-->")
iparse(StringIO(data))
一切运行得很好……不过,iparse
里的 for
循环每次都要遍历整个文档。有没有可能让 iparse
只处理一个完整的标签节点(事件),也就是在流中出现时就处理它?需要注意的是,我无法设置读取的块大小来获取一个完整的数据包。我可以使用一个缓冲区,等数据包完整后再发送给 iparse
,但这样可能会引入不必要的延迟?有没有更好的处理方法?
补充说明:
每个事件都是独立的,但在根节点 <event>
下包含任意节点。iparse
需要将最新的事件发布给任意数量的订阅者,这些订阅者是在一个实时分析图形系统中。
1 个回答
0
你可以看看 lxml.etree 里的 feed parsing
(数据流解析)。不过,你可能还是会遇到问题,因为你的文档会不断增大。
这些XML数据块是用换行符分开的么?如果是的话,我建议你先把数据缓存起来,等到遇到换行符再把每一行发送给XML解析器。就像 Twisted的LineReceiver那样。
其实如果是我,我可能会用 Twisted 来写这个应用。对我来说,把网络服务连接起来是它的一个常见用途。