尝试使用Nokogiri从缓冲区解析多个可能不完整的XML片段

时间:2011-04-08 23:58:42

标签: ruby xml regex string nokogiri

通过tcp套接字接收XML格式的消息,并尝试使用Nokogiri解析它们。如果我可以在缓冲区中依赖单个完整的根标记,那么一切都会很简单。

琐碎的例子:

<doc><a>some long text ....</a><b>more text</b></doc>

=> #<Nokogiri::XML::Document:0x1326a30 name="document" children=[#<Nokogiri::XML::Element:0x1325fcc name="doc" children=[#<Nokogiri::XML::Element:0x1325aa4 name="a" children=[#<Nokogiri::XML::Text:0x13255f4 "some long text ....">]>, #<Nokogiri::XML::Element:0x1324f3c name="b" children=[#<Nokogiri::XML::Text:0x1324b68 "more text">]>]>]>

一切都如预期一样。

长消息可能会在数据包之间分割,使缓冲区保留不完整的标记:

<doc><a>exceptionally long text ....

=> #<Nokogiri::XML::Document:0x12c45ec name="document" children=[#<Nokogiri::XML::Element:0x12c2968 name="doc" children=[#<Nokogiri::XML::Element:0x12c210c name="a" children=[#<Nokogiri::XML::Text:0x12c1cc0 "exceptionally long text">]>]>]>

仍然如预期的那样,Nokogiri :: XML :: SyntaxError:标签doc line 1中的数据过早结束,我们可以等待缓冲区中的更多数据。

但是,短消息可能聚集在一个数据包中并立即到达:

<doc><a>text</a></doc><doc><a>other text</a></doc>

=> #<Nokogiri::XML::Document:0x1312cd8 name="document" children=[#<Nokogiri::XML::Element:0x1312814 name="doc" children=[#<Nokogiri::XML::Element:0x1312594 name="a" children=[#<Nokogiri::XML::Text:0x1312288 "text">]>]>]>

第二条消息未解析,Nokogiri :: XML :: SyntaxError:文档末尾的额外内容。

我看不出任何方法让Nokogiri向我回复额外的内容,所以我可以尝试继续解析。这可能是底层libxml2或Nokogiri与库的接口的限制。 String.scan不提供字符串索引(拆分消息并保留额外的文本),Regexp.match不会全局匹配。关于如何最好地从缓冲区中提取所有完整消息并留下尾随不完整消息的任何想法?

2 个答案:

答案 0 :(得分:0)

Nokogiri期待一个IO流或字符串。来自Nokogiri::HTML::Document.parseNokogiri::XML::Document.parse的文档。

parse(string_or_io, url = nil, encoding = nil, options = XML::ParseOptions::DEFAULT_HTML)
  

解析HTML。 thing可以是String,也可以是响应读取和关闭的任何对象,例如IO或StringIO。

“thing”实际上应该是“string_or_io”,以匹配他们的例子,但你明白了。

如果您可以添加有关如何检索内容并解析内容的更多信息,我们可能会提供更多帮助。

答案 1 :(得分:0)

您可能想尝试Nokogiri::XML::SAX::PushParser来完成此任务。

请参阅http://www.rubydoc.info/github/sparklemotion/nokogiri/Nokogiri/XML/SAX/PushParser