使用相邻节点解析类似XML的简单字符串

时间:2016-06-26 17:27:55

标签: ruby nokogiri

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

所以我尝试了两种不同的Nokogiri方法,但两者都只显示了第一个节点。我怎样才能获得其余的相邻节点?

或者,我如何才能获得engtagger调用以返回数组?在文档中,我没有找到如何使用所有标记返回数组的示例,只有具有一种特定类型标记的数组。

2 个答案:

答案 0 :(得分:1)

最重要的是,格式良好的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] } 

答案 1 :(得分:1)

问题是您正在正确解析片段:

function mysite_woocommerce_order_status_completed( $order_id ) {
echo $order_id; exit; // you will get order ID here , when you are updating order status to completed.
}
add_action( 'woocommerce_order_status_completed','mysite_woocommerce_order_status_completed' );

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

此时你可以这样做:

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>"