使用Nokogiri搜索XML文档中的特定路径并更改它(在前面使用Cucumber)
我想在XML文档中搜索特定路径,然后将其更改为其他内容。这是XML的一个相关部分:
<Root>
<Application>
<Connections>
<AutoAccept>true</AutoAccept>
<AllowDomains/>
</Connections>
<Streams>
<StreamType>default</StreamType>
<StorageDir>/C:/blah/flash/</StorageDir>
我想改变"/C:/blah/flash/"为另一个值。这是我的代码:
Given(/^Update the Apreso configuration file$/) do
xmldoc = Nokogiri::XML(DATA['DATA_WOWZA1'])
xmldoc.search("/Root/Application/Streams/StorageDir").each do |node|
node.content = "Newpath"
end
puts xmldoc.to_xml
end
"DATA_WOWZA1"是我通过YAML文件传递的XML文件的路径。当我运行代码时,它通过了,但XML文件没有反映更改,您认为呢?
您需要给Nokogiri::XML
一个XML字符串,而不是一个文件路径字符串。试一试:
xmldoc = Nokogiri::XML(File.read DATA['DATA_WOWZA1'])
但是,您得到的是原始XML输出,这是没有意义的。您确定您的测试正在输出XML吗?
如果您想将文件保存在适当的位置,您需要执行以下操作:
File.open(DATA['DATA_WOWZA1'], 'w') { |f| f.puts xmldoc.to_xml }
如果只有一个StorageDir
节点,那么您的工作太辛苦了:
require 'nokogiri'
doc = Nokogiri::XML(<<EOT)
<Root>
<Application>
<Connections>
<AutoAccept>true</AutoAccept>
<AllowDomains/>
</Connections>
<Streams>
<StreamType>default</StreamType>
<StorageDir>/C:/blah/flash/</StorageDir>
</Streams>
</Application>
</Root>
EOT
doc.at('StorageDir').content = 'd:/path/to/foo'
puts doc.to_xml
# >> <?xml version="1.0"?>
# >> <Root>
# >> <Application>
# >> <Connections>
# >> <AutoAccept>true</AutoAccept>
# >> <AllowDomains/>
# >> </Connections>
# >> <Streams>
# >> <StreamType>default</StreamType>
# >> <StorageDir>d:/path/to/foo</StorageDir>
# >> </Streams>
# >> </Application>
# >> </Root>
覆盖原始文件也很容易做到。这是未经测试的,但看起来是正确的:
XML_FILE = 'path/to/xml'
doc = Nokogiri::XML(open(XML_FILE, 'r'))
doc.at('StorageDir').content = 'd:/path/to/foo'
File.write("#{ XML_FILE }.new", doc.to_xml)
注意,我没有覆盖原来的文件,我正在写入一个新文件。如果代码出了问题,比如修改了错误的节点,这将保留旧文件,而不是破坏其内容。
在生产系统中,您可能希望写入一个新文件,然后将旧文件重命名为安全文件,将新文件重命名为旧文件的名称,然后在确定一切正常工作后,有选择地删除旧文件。