【问题标题】:Searching XML doc for specific path using Nokogiri and changing it使用 Nokogiri 搜索特定路径的 XML 文档并更改它
【发布时间】:2014-05-23 05:04:23
【问题描述】:

使用 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 文件没有反映更改的代码时,想法?

【问题讨论】:

  • 您是在搜索空字符串,还是只是一个伪代码?
  • 艾哈迈德,这是一种类型,谢谢兄弟。搜索路径,见上面的代码。
  • 那么这个 XPath 有什么问题呢?它对我来说很好用;节点更改正确反映。您使用的是哪个版本的 nokogiri?
  • XML 中有多少个StorageDir 节点?一个,还是多个?如果只有一个,那么你就很难做到。
  • ^一,如何重构更容易?

标签: ruby xml cucumber nokogiri


【解决方案1】:

您需要给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 }

【讨论】:

  • 这行得通,终端中的输出显示了更改,但文件没有反映更改,我需要保存文件吗?
  • 添加了保存文件的示例。
  • 我刚试过: File.open(DATA['DATA_WOWZA1'],'w') {|f| xmldoc.write_xml_to f} 并看到了您的评论,谢谢 kardeiz!它有效:)
【解决方案2】:

如果只有一个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)

注意,我不是在覆盖原始文件,而是在写入一个新文件。如果代码出现问题,例如修改错误的节点,这将保留旧文件而不是破坏其内容。

在生产系统中,您可能希望写入一个新文件,然后将旧文件重命名为安全的名称,将新文件重命名为旧文件的名称,然后在完成后可选择删除旧文件确保一切正常。通过这样做,如果出现问题,您就可以了。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多