我正在使用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"]]