如何使用 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")
要更改 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_id
和Route
- 第一个标签中缺少
?
- 是否需要最后一行
</xml>
?
修复示例后,我可以使用 Phrogz 的示例获取元素:
element = @doc.xpath("Route//To//Node//Filename[.='#{target_file}']").first
注意 .first
因为它将 return 一个节点集。
然后我会更新内容:
element.content = "foobar"
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 }
- 显示如何将
Nokogiri::XML::Document
序列化回磁盘。
- 一找到匹配的 XML 文件就停止处理文件。
我正在使用 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")
要更改 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_id
和Route
- 第一个标签中缺少
?
- 是否需要最后一行
</xml>
?
修复示例后,我可以使用 Phrogz 的示例获取元素:
element = @doc.xpath("Route//To//Node//Filename[.='#{target_file}']").first
注意 .first
因为它将 return 一个节点集。
然后我会更新内容:
element.content = "foobar"
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 }
- 或者您可以找到所有文件,然后
- 显示如何将
Nokogiri::XML::Document
序列化回磁盘。 - 一找到匹配的 XML 文件就停止处理文件。