如何使用Nokogiri添加新的兄弟元素?

时间:2016-08-19 20:30:03

标签: ruby xml nokogiri

我的目标是在此XML中输入新的category节点。

<<?xml version="1.0" encoding="UTF-8"?>
<categories xmlns="CategoryList.xsd" lastSavedTime="2014-05-02T20:07:40.5903428Z">
   <category renameOnFirstUse="1" name="Red category" color="0" keyboardShortcut="0" lastTimeUsedNotes="2014-05-02T20:07:40.5279436Z" lastTimeUsedJournal="2014-05-02T20:07:40.5279436Z" lastTimeUsedContacts="2014-05-02T20:07:40.5279436Z" lastTimeUsedTasks="2014-05-02T20:07:40.5279436Z" lastTimeUsedCalendar="2014-05-02T20:07:40.5279436Z" lastTimeUsedMail="2014-05-02T20:07:40.5279436Z" lastTimeUsed="2014-05-02T20:07:40.5279436Z" guid="{4f331f68-b735-4797-a0c4-9b02e13d079f}">
      <category renameOnFirstUse="0" name="test" color="10" keyboardShortcut="0" lastTimeUsedNotes="2014-05-02T20:07:40.5279436Z" lastTimeUsedJournal="2014-05-02T20:07:40.5279436Z" lastTimeUsedContacts="2014-05-02T20:07:40.5279436Z" lastTimeUsedTasks="2014-05-02T20:07:40.5279436Z" lastTimeUsedCalendar="2014-05-02T20:07:40.5279436Z" lastTimeUsedMail="2014-05-02T20:07:40.5279436Z" lastTimeUsed="2014-05-02T20:07:40.5279436Z" guid="{4452319c-0253-4764-a72f-065e5a4af017}" />
   </category>
   <category renameOnFirstUse="1" name="Orange category" color="1" keyboardShortcut="0" lastTimeUsedNotes="2014-05-02T20:07:40.5279436Z" lastTimeUsedJournal="2014-05-02T20:07:40.5279436Z" lastTimeUsedContacts="2014-05-02T20:07:40.5279436Z" lastTimeUsedTasks="2014-05-02T20:07:40.5279436Z" lastTimeUsedCalendar="2014-05-02T20:07:40.5279436Z" lastTimeUsedMail="2014-05-02T20:07:40.5279436Z" lastTimeUsed="2014-05-02T20:07:40.5279436Z" guid="{eb64b97a-d5a2-41ed-a0ed-dc60fe0601e2}" />
   <category renameOnFirstUse="1" name="Yellow category" color="3" keyboardShortcut="0" lastTimeUsedNotes="2014-05-02T20:07:40.5279436Z" lastTimeUsedJournal="2014-05-02T20:07:40.5279436Z" lastTimeUsedContacts="2014-05-02T20:07:40.5279436Z" lastTimeUsedTasks="2014-05-02T20:07:40.5279436Z" lastTimeUsedCalendar="2014-05-02T20:07:40.5279436Z" lastTimeUsedMail="2014-05-02T20:07:40.5279436Z" lastTimeUsed="2014-05-02T20:07:40.5279436Z" guid="{0010faba-dd02-44fb-afbe-3fd5ac2d4f6f}" />
   <category renameOnFirstUse="1" name="Green category" color="4" keyboardShortcut="0" lastTimeUsedNotes="2014-05-02T20:07:40.5279436Z" lastTimeUsedJournal="2014-05-02T20:07:40.5279436Z" lastTimeUsedContacts="2014-05-02T20:07:40.5279436Z" lastTimeUsedTasks="2014-05-02T20:07:40.5279436Z" lastTimeUsedCalendar="2014-05-02T20:07:40.5279436Z" lastTimeUsedMail="2014-05-02T20:07:40.5279436Z" lastTimeUsed="2014-05-02T20:07:40.5279436Z" guid="{38f5e37c-0fe7-41c4-b265-7b30b9a6fcfa}" />
   <category renameOnFirstUse="1" name="Blue category" color="7" keyboardShortcut="0" lastTimeUsedNotes="2014-05-02T20:07:40.5279436Z" lastTimeUsedJournal="2014-05-02T20:07:40.5279436Z" lastTimeUsedContacts="2014-05-02T20:07:40.5279436Z" lastTimeUsedTasks="2014-05-02T20:07:40.5279436Z" lastTimeUsedCalendar="2014-05-02T20:07:40.5279436Z" lastTimeUsedMail="2014-05-02T20:07:40.5279436Z" lastTimeUsed="2014-05-02T20:07:40.5279436Z" guid="{7fb0e73e-4193-4836-b9e9-c2017168418a}" />
   <category renameOnFirstUse="1" name="Purple category" color="8" keyboardShortcut="0" lastTimeUsedNotes="2014-05-02T20:07:40.5279436Z" lastTimeUsedJournal="2014-05-02T20:07:40.5279436Z" lastTimeUsedContacts="2014-05-02T20:07:40.5279436Z" lastTimeUsedTasks="2014-05-02T20:07:40.5279436Z" lastTimeUsedCalendar="2014-05-02T20:07:40.5279436Z" lastTimeUsedMail="2014-05-02T20:07:40.5279436Z" lastTimeUsed="2014-05-02T20:07:40.5279436Z" guid="{0ed51616-504f-4415-936c-a97658aa2458}" />
</categories>

但是当我尝试

categories = doc.css("category")
categories.after "<test></test>"

我得到:nokogiri/xml/node_set.rb:59:in 'after': undefined method 'after' for nil:NilClass (NoMethodError)

我知道所有类别都会被读入categories变量,因为我可以将它们打印出来。我还没有能够在XML文档中添加新类别。

我也试过doc.at('category').add_next_sibling("<AnotherNode>13</AnotherNode>")。这给出了同样的错误:undefined method 'add_next_sibling' for nil:NilClass (NoMethodError)。我做错了什么?

1 个答案:

答案 0 :(得分:1)

使用Nokogiri 1.6.8我无法复制问题:

require 'nokogiri'

doc = Nokogiri::XML('<root><node1/></root>')
doc.at('node1').after('<node2/>')
puts doc.to_xml

# >> <?xml version="1.0"?>
# >> <root>
# >>   <node1/>
# >>   <node2/>
# >> </root>

我建议检查你的XML。以下是我使用XML示例的内容:

doc.errors # => [#<Nokogiri::XML::SyntaxError: StartTag: invalid element name>, #<Nokogiri::XML::SyntaxError: XML declaration allowed only at the start of the document>, #<Nokogiri::XML::SyntaxError: Extra content at the end of the document>]

这是因为:

<<?xml version="1.0" encoding="UTF-8"?>

将XML简化为简单的大纲显示Nokogiri正被迫修改内容以使其可解析:

doc = Nokogiri::XML('<<?xml version="1.0" encoding="UTF-8"?>
<categories>
   <category>
      <category />
   </category>
</categories>')
doc.errors # => [#<Nokogiri::XML::SyntaxError: StartTag: invalid element name>, #<Nokogiri::XML::SyntaxError: XML declaration allowed only at the start of the document>, #<Nokogiri::XML::SyntaxError: Extra content at the end of the document>]
puts doc.to_xml

# >> <?xml version="1.0"?>
# >> <?xml version="1.0" encoding="UTF-8"?>

规则一:调试这些东西时,将问题减少到最小输入和代码,看看会发生什么。修复XML,你可能会有更好的结果。