簡體   English   中英

如何使用Nokogiri替換XML節點內容

[英]How to replace XML node contents using Nokogiri

我正在使用Ruby來讀取XML文檔並使用新值更新單個節點(如果存在)。

http://www.nokogiri.org/tutorials/modifying_an_html_xml_document.html對我來說並不是很明顯如何更改節點數據,更不用說如何將其保存回文件。

def ammend_parent_xml(folder, target_file, new_file)
  # open parent XML file that contains file reference
  get_xml_files = Dir.glob("#{@target_folder}/#{folder}/*.xml").sort.select {|f| !File.directory? f}
  get_xml_files.each { |xml|

    f       = File.open(xml)

    # Use Nokgiri to read the file into an XML object
    doc     = Nokogiri::XML(f)
    filename  = doc.xpath('//Route//To//Node//FileName')

    filename.each_with_index {
      |fl, i|
      if target_file == fl.text
        # we found the file, now rename it to new_file
        # ???????
      end

    }

  }

end

這是一些示例XML:

<?xml version="1.0" encoding="utf-8">
    <my_id>123</my_id>
    <Route>
      <To>
        <Node>
          <Filename>file1.txt</Filename>
          <Filename>file2.mp3</Filename>
          <Filename>file3.doc</Filename>
          <Filename>file4.php</Filename>
          <Filename>file5.jpg</Filename>
        </Node>
      </To>
    </Route>
</xml>

我想將“file3.doc”更改為“file3_new.html”。

我打電話給:

def ammend_parent_xml("folder_location", "file3.doc", "file3_new.html")
def amend_parent_xml(folder, target_file, new_file)
  Dir["#{@target_folder}/#{folder}/*.xml"]
  .sort.select{|f| !File.directory? f }
  .each do |xml_file|
    doc = Nokogiri.XML( File.read(xml_file) )
    if file = doc.at("//Route//To//Node//Filename[.='#{target_file}']")
      file.content = new_file # set the text of the node
      File.open(xml_file,'w'){ |f| f<<doc }
      break
    end
  end
end

改進:

  • 使用File.read而不是File.open這樣就不會打開文件句柄。
  • 使用XPath表達式通過查找具有正確文本值的節點來查找SINGLE匹配節點。
    • 或者,您可以找到所有文件,然后找到if file=files.find{ |f| f.text==target_file } if file=files.find{ |f| f.text==target_file }
  • 演示如何將Nokogiri::XML::Document序列化回磁盤。
  • 一旦找到匹配的XML文件,就不會處理文件。

要更改XML中的元素:

@doc = Nokogiri::XML::DocumentFragment.parse <<-EOXML
<body>
  <h1>OLD_CONTENT</h1>
  <div>blah</div>
</body>
EOXML


h1 = @doc.at_xpath "body/h1"
h1.content = "NEW_CONTENT"

puts @doc.to_xml   #h1 will be NEW_CONTENT

要保存XML:

file = File.new("xml_file.xml", "wb")
file.write(@doc)
file.close

您的示例XML存在一些問題。

  • my_idRoute有兩個根元素
  • 有一個失蹤? 在第一個標簽中
  • 你需要最后一行</xml>嗎?

在修復樣本后,我可以通過使用Phrogz的示例來獲取元素:

element = @doc.xpath("Route//To//Node//Filename[.='#{target_file}']").first 

需要注意.first ,因為它會返回一個節點集。

然后我會用以下內容更新內容:

element.content = "foobar"

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM