我在Ruby中有这个服务器项目,我想在XML文件中记录事件和用户会话。我对此非常陌生,经过几天的研究,我已经撞墙了。
这是我当前的示例代码,假设已经有一个名为" test.xml"的文件。包含一个名为
的根节点$ cat test.xml
<server></server>
和代码:
require 'nokogiri'
require 'securerandom'
logintime = Time.now
sessionid = SecureRandom.hex(10)
file = File.open("test.xml",'a+')
doc = Nokogiri::XML.parse file
session_node = Nokogiri::XML::Node.new("session",doc)
session_node['id'] = sessionid
logintime_node = Nokogiri::XML::Node.new("logintime",doc)
logintime_node.content = logintime
session_node << logintime_node
doc.root << session_node
file.print doc.to_xml
file.close
以及4次运行后的test.xml文件
<server></server>
<?xml version="1.0"?>
<server>
<session id="5ef27ade2afaf5c2162f">
<logintime>2015-07-07 17:27:20 +0200</logintime>
</session>
</server>
<?xml version="1.0"?>
<server>
<session id="637595bd0857c8af1cc0">
<logintime>2015-07-07 17:27:36 +0200</logintime>
</session>
</server>
<?xml version="1.0"?>
<?xml version="1.0"?>
<server>
<session id="41e6082c4db7d1dc8692">
<logintime>2015-07-07 17:27:37 +0200</logintime>
</session>
</server>
<?xml version="1.0"?>
<?xml version="1.0"?>
<server>
<session id="1cad6c3d38d4fb96632b">
<logintime>2015-07-07 17:27:38 +0200</logintime>
</session>
</server>
<?xml version="1.0"?>
所需的输出应该是这样的:
<?xml version="1.0"?>
<server>
<session id="5ef27ade2afaf5c2162f">
<logintime>2015-07-07 17:27:20 +0200</logintime>
</session>
<session id="637595bd0857c8af1cc0">
<logintime>2015-07-07 17:27:36 +0200</logintime>
</session>
<session id="41e6082c4db7d1dc8692">
<logintime>2015-07-07 17:27:37 +0200</logintime>
</session>
<session id="1cad6c3d38d4fb96632b">
<logintime>2015-07-07 17:27:38 +0200</logintime>
</session>
</server>
而且我真的不知道为什么要做到这一点。
首先,如果没有包含根节点的现有文件,该脚本只运行一次,然后在我尝试再次运行时抱怨已经有根节点:
/System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/ruby/gems/2.0.0/gems/nokogiri-1.5.6/lib/nokogiri/xml/document.rb:232:in `add_child': Document already has a root node (RuntimeError)
from /Users/xxx/nokogiri.rb:13:in `<top (required)>'
from -e:1:in `load'
from -e:1:in `<main>'
所以......我有点迷失在这里。有什么想法吗?
答案 0 :(得分:0)
问题是您是使用File.open('test.xml', 'a+')
以追加模式打开文件,然后使用file.print doc.to_xml
将整个XML文档写入其中。这就是为什么你最终将整个文档写入文件中的原因。
如果您单独读取和写入文件,XML文档将以您希望的方式替换文件。如果您还需要处理尚未存在的文件,您还可以检查它并使用<server>
根标记初始化数据。
require 'nokogiri'
require 'securerandom'
logintime = Time.now
sessionid = SecureRandom.hex(10)
# Read or initialize the data
if File.exist?('test.xml')
data = File.read("test.xml")
else
data = '<server></server>'
end
doc = Nokogiri::XML.parse data
session_node = Nokogiri::XML::Node.new("session",doc)
session_node['id'] = sessionid
logintime_node = Nokogiri::XML::Node.new("logintime",doc)
logintime_node.content = logintime
session_node << logintime_node
doc.root << session_node
# Write the document to disk
File.open('test.xml', 'w') do |file|
file.print doc.to_xml
end
我不建议长时间以这种方式记录会话。在任何重要的用户负载下,写入文件将变得非常昂贵。此外,如果您有多台服务器在运行,它们都会将文件从另一台服务器中删除。当你达到这一点时,你至少应该将存储转换为数据库,或者甚至更好地使用为此构建的ELK Stack之类的东西。