你的问题有多个问题,但我会尝试整理出来,以便你了解正在发生的事情以及将来如何写出更好的问题。
你的XML样本格式不正确:
xml = "<name>Married with Children</name>
<person age="20">Al Bundy</person>
<character age="20">Bud Bundy</character>
<character age="19">Marcy Darcy</character>
<person age="18">John Doe</person>"
-:3: syntax error, unexpected tINTEGER, expecting end-of-input
<person age="20">Al Bundy</person>
你得到这一点,因为你有外双引号和双引号包裹的参数。在询问问题时务必确保您的样本数据可用。它应该看起来像:
xml = '<name>Married with Children</name>
<person age="20">Al Bundy</person>
<character age="20">Bud Bundy</character>
<character age="19">Marcy Darcy</character>
<person age="18">John Doe</person>'
或可能:
xml = <<EOT
<name>Married with Children</name>
<person age="20">Al Bundy</person>
<character age="20">Bud Bundy</character>
<character age="19">Marcy Darcy</character>
<person age="18">John Doe</person>
EOT
此时红宝石将让你开始测试你的代码。
您的示例XML没有根节点。
require 'nokogiri'
xml = '<name>Married with Children</name>
<person age="20">Al Bundy</person>
<character age="20">Bud Bundy</character>
<character age="19">Marcy Darcy</character>
<person age="18">John Doe</person>'
doc = Nokogiri::XML(xml)
doc.to_xml # => "<?xml version=\"1.0\"?>\n<name>Married with Children</name>\n"
如果我使用doc.errors
引入nokogiri会告诉它为什么只有一个节点:
doc.errors # => [#<Nokogiri::XML::SyntaxError: Extra content at the end of the document>]
有固定两种方式XML有严格的定义,以便再次,它提供正确的数据是非常重要的此,添加一个包裹根节点,或者告诉引入nokogiri对待标记为文档的一个片段:
doc = Nokogiri::XML('<root>' + xml + '</root>')
doc.to_xml # => "<?xml version=\"1.0\"?>\n<root><name>Married with Children</name>\n<person age=\"20\">Al Bundy</person>\n<character age=\"20\">Bud Bundy</character>\n<character age=\"19\">Marcy Darcy</character>\n<person age=\"18\">John Doe</person></root>\n"
或:
doc = Nokogiri::XML::DocumentFragment.parse(xml)
doc.to_xml # => "<name>Married with Children</name>\n<person age=\"20\">Al Bundy</person>\n<character age=\"20\">Bud Bundy</character>\n<character age=\"19\">Marcy Darcy</character>\n<person age=\"18\">John Doe</person>"
注意解析后两个DOM之间的区别。第一个具有包含节点,第二个仅具有示例XML中的节点。
既然DOM没有错误,那么您可以安全地开始分析和收集数据。如果你不能确保你的DOM被正确解析,你可以发现Nokogiri做了修复并修改了DOM以使它在语法上正确,导致了与你预期不同的结构。处理这些往往会让你疯狂。
搜索时使用正确的标签名称。这是不言自明的,你会要么得到的结果或将获得零或空节点集([]
):
doc = Nokogiri::XML('<root>' + xml + '</root>')
data = doc.css('characters') # => []
data.class # => Nokogiri::XML::NodeSet
data = doc.at_css('characters') # => nil
,而我们想要的东西,如:
data = doc.css('character') # => [#<Nokogiri::XML::Element:0x3fc8c4c4d598 name="character" attributes=[#<Nokogiri::XML::Attr:0x3fc8c4c4d4bc name="age" value="20">] children=[#<Nokogiri::XML::Text:0x3fc8c4c4c544 "Bud Bundy">]>, #<Nokogiri::XML::Element:0x3fc8c4c49d44 name="character" attributes=[#<Nokogiri::XML::Attr:0x3fc8c4c49ce0 name="age" value="19">] children=[#<Nokogiri::XML::Text:0x3fc8c4c49830 "Marcy Darcy">]>]
data = doc.at_css('character') # => #<Nokogiri::XML::Element:0x3fc8c4c4d598 name="character" attributes=[#<Nokogiri::XML::Attr:0x3fc8c4c4d4bc name="age" value="20">] children=[#<Nokogiri::XML::Text:0x3fc8c4c4c544 "Bud Bundy">]>
或使用通用方法:
data = doc.search('character') # => [#<Nokogiri::XML::Element:0x3fe8fe0771d8 name="character" attributes=[#<Nokogiri::XML::Attr:0x3fe8fe076ff8 name="age" value="20">] children=[#<Nokogiri::XML::Text:0x3fe8fe07633c "Bud Bundy">]>, #<Nokogiri::XML::Element:0x3fe8fe07606c name="character" attributes=[#<Nokogiri::XML::Attr:0x3fe8fe073fd8 name="age" value="19">] children=[#<Nokogiri::XML::Text:0x3fe8fe073b50 "Marcy Darcy">]>]
data = doc.at('character') # => #<Nokogiri::XML::Element:0x3fe8fe0771d8 name="character" attributes=[#<Nokogiri::XML::Attr:0x3fe8fe076ff8 name="age" value="20">] children=[#<Nokogiri::XML::Text:0x3fe8fe07633c "Bud Bundy">]>
注意at
及其at_css
和at_xpath
兄弟姐妹是相当于。
移动到一个方法来获得数据,你想:你可以使用CSS的,
运营商,查找多个不同的节点:
data = doc.search('character, person') # => [#<Nokogiri::XML::Element:0x3fd7de018c7c name="person" attributes=[#<Nokogiri::XML::Attr:0x3fd7de018b8c name="age" value="20">] children=[#<Nokogiri::XML::Text:0x3fd7de015b80 "Al Bundy">]>, #<Nokogiri::XML::Element:0x3fd7de014fb4 name="character" attributes=[#<Nokogiri::XML::Attr:0x3fd7de014dd4 name="age" value="20">] children=[#<Nokogiri::XML::Text:0x3fd7de014550 "Bud Bundy">]>, #<Nokogiri::XML::Element:0x3fd7de014294 name="character" attributes=[#<Nokogiri::XML::Attr:0x3fd7de01421c name="age" value="19">] children=[#<Nokogiri::XML::Text:0x3fd7de011d00 "Marcy Darcy">]>, #<Nokogiri::XML::Element:0x3fd7de011a94 name="person" attributes=[#<Nokogiri::XML::Attr:0x3fd7de011a30 name="age" value="18">] children=[#<Nokogiri::XML::Text:0x3fd7de0112d8 "John Doe">]>]
data.map(&:to_xml) # => ["<person age=\"20\">Al Bundy</person>", "<character age=\"20\">Bud Bundy</character>", "<character age=\"19\">Marcy Darcy</character>", "<person age=\"18\">John Doe</person>"]
这样的作品,但是你没有总量控制的顺序你会得到结果节点,而不是他们在文件中出现的顺序。如果你想控制这个顺序,你可能会想要做两个单独的搜索,然后连接NodeSets。如何做到这一点,留给你弄清楚。
要解析XML或HTML,理解CSS和/或XPath选择器很重要。我建议专注于CSS选择器,因为它们通常更具可读性。另外,Nokogiri实现了许多jQuery的CSS扩展,以方便使用,从而增加了简单性。 XPath功能强大得多,但价格很高,视觉噪声很大。但是,您仍然需要熟悉它,以便在必要时从工具箱中取出该工具。
您可以使用简单的选择器,然后在Nokogiri中折叠/旋转/切割结果,但使用libXML的强大功能需要通过选择器给它提供信息,因此学习如何有效和正确地使用它们非常重要。制作Nokogiri或libXML之间的速度差异会让你很快相信这一点。
''''xml.css(“characters”)'''''''''''''''''''除了'['''''没有''标签以外。 'css。('character')'会找到两个节点。另外,您的XML在语法上不正确,因为它缺少一个根节点。请阅读“[问]”和“[mcve]”。你尝试了什么?我们需要看到你的努力的证据。没有它,看起来你希望我们为你写代码。 –