用相邻节点解析一个简单的XML样字符串



我正在使用engtagger GEM根据语音的各个部分对句子进行分类。我得到的输出如下:

puts text
# => "<nnp>My</nnp> <nn>name</nn> <vbz>is</vbz> <nnp>Max</nnp>"

我本来希望宝石给我一个阵列,但我想我必须自己将其胁迫。

我最终要获得的是这样的嵌套数组:

[["My", "nnp"], ["name", "nn"], ["is", "vbz"], ["Max", "nnp"]]

但是,我不确定如何使用Nokogiri(或其他解析器库)处理。这是我尝试的:

(byebug) doc = Nokogiri::XML(text)
#<Nokogiri::XML::Document:0x3fd400286e78 name="document" children=[#<Nokogiri::XML::Element:0x3fd400286900 name="nnp" children=[#<Nokogiri::XML::Text:0x3fd400286464 "My">]>]>
(byebug) Nokogiri.parse(text)
#<Nokogiri::XML::Document:0x3fd40028cd50 name="document" children=[#<Nokogiri::XML::Element:0x3fd40028c7d8 name="nnp" children=[#<Nokogiri::XML::Text:0x3fd40028c378 "My">]>]>

所以我尝试了两种不同的诺科吉里方法,但两者仅显示第一个节点。我如何也能获得其余的相邻节点?

另外,如何获取engtagger调用以返回数组?在文档中,我没有找到如何使用 all tags 返回数组的示例,只有一种具有特定类型的标签的数组。

最主要的是,良好的XML应该具有根节点。您之所以收到第一个节点,是因为它被视为根部(即最上方)节点,并且在关闭时,诺科吉里(Nokogiri)被视为要结束的XML文档。

Nokogiri::XML("<root>#{text}</root>").
  children.first. # get root node
  children.map { |e| [e.text, e.name] }. # map to what’s needed
  reject { |e| e.last == 'text' } # filter out garbage

该滤波在语义上可能更正确:

Nokogiri::XML("<root>#{text}</root>").
  children.first.
  children.reject { |e| Nokogiri::XML::Text === e }.
  map { |e| [e.text, e.name] } 

问题是您错误地解析片段:

require 'nokogiri'
doc = Nokogiri::XML.fragment("<nnp>My</nnp> <nn>name</nn> <vbz>is</vbz> <nnp>Max</nnp>")
doc.to_xml # => "<nnp>My</nnp> <nn>name</nn> <vbz>is</vbz> <nnp>Max</nnp>"

Nokogiri想要有效的XML,但是您可以使用fragment接受部分XML块。

那时您可以做:

doc.children.each_with_object([]){ |n, a| a << [n.text, n.name] unless n.text? } 
# => [["My", "nnp"], ["name", "nn"], ["is", "vbz"], ["Max", "nnp"]]

相关内容

  • 没有找到相关文章

最新更新