我正在尝试使用Nokogiri编辑大型XML文件。目前,我能够找到我正在寻找的NodeSet使用.css
我可以创建新的NodeSet我想设置为替换,但通过使用Nokogiri::XML::NodeSet#push
我无法更改xml文档对象的内容。
xml = Nokogiri::XML(File.read('/Users/Desktop/metadata.xml')
keywords = xml.css('version').first.css('keywords keyword') ## node set I want to edit
keywords.delete(keywords[0]) ## one less element in the node set
xml.css('version').first.css('keywords keyword').remove ## destructively modifies xml object and erases all elements
## this is where things get interesting:
## this call returns a new node set with keywords[0] inside of it,
## but does NOT mutate the xml object
xml.css('version').first.css('keywords keyword').push(keywords[0])
puts xml.css('version').first.css('keywords keyword') ## puts an empty array
编辑:示例XML
<version>
<locale name="en-US">
<title>This is the Title</title>
<description>this is the description</description>
<keywords>
<keyword>this</keyword>
<keyword>that</keyword>
<keyword>the other</keyword>
</keywords>
</locale>
</version>
编辑:目标XML
<version>
<locale name="en-US">
<title>This is the Title</title>
<description>this is the description</description>
<keywords>
<keyword>that</keyword>
<keyword>the other</keyword>
</keywords>
</locale>
</version>
或 的
<version>
<locale name="en-US">
<title>This is the Title</title>
<description>this is the description</description>
<keywords>
<keyword>different keyword</keyword>
</keywords>
</locale>
</version>
答案 0 :(得分:0)
如果没有XML示例,我就会试图诊断问题,但是代码写得不好。这些似乎是有效的替换/更改:
keywords = xml.css('version').first
可以简化为:
xml.at('version')
xml.css('version').first.css('keywords keyword')
可能缩写为:
xml.css('version 'keywords keyword')
但没有XML我无法确认。
Nokogiri的at('some_selector')
相当于search('some_selector').first
。同样,at_css
和at_xpath
相当于css
和xpath
次搜索,后跟first
。
以下是我写的方式:
require 'nokogiri'
xml = Nokogiri::XML(<<EOT)
<xml>
<version>
<locale name="en-US">
<title>This is the Title</title>
<description>this is the description</description>
<keywords>
<keyword>this</keyword>
<keyword>that</keyword>
<keyword>the other</keyword>
</keywords>
</locale>
</version>
</xml>
EOT
keywords = xml.css('version keywords keyword')
xml.at('version keywords').children = keywords[1..-1]
puts xml.to_xml
哪个输出:
<?xml version="1.0"?>
<xml>
<version>
<locale name="en-US">
<title>This is the Title</title>
<description>this is the description</description>
<keywords><keyword>that</keyword><keyword>the other</keyword></keywords>
</locale>
</version>
</xml>
为了使XML正确<version>
需要包装“root”标记,这就是我添加<xml>
的原因。我确信你原来的XML有类似的东西。
您可以通过切片<keyword>
NodeSet来控制允许剩余的keywords
个节点的数量。
这并没有以足够通用的方式解决这个问题,我可以添加和修改现有的孩子。
require 'nokogiri'
xml = Nokogiri::XML(<<EOT)
<xml>
<version>
<locale name="en-US">
<title>This is the Title</title>
<description>this is the description</description>
<keywords>
<keyword>this</keyword>
<keyword>that</keyword>
<keyword>the other</keyword>
</keywords>
</locale>
</version>
</xml>
EOT
version_keywords = xml.at('version keywords')
keywords = version_keywords.css('keyword')
version_keywords.children = keywords[1..-1]
version_keywords.add_child('<keyword>And now for something entirely different</keyword>')
puts xml.to_xml
<?xml version="1.0"?>
<xml>
<version>
<locale name="en-US">
<title>This is the Title</title>
<description>this is the description</description>
<keywords><keyword>that</keyword><keyword>the other</keyword><keyword>And now for something entirely different</keyword></keywords>
</locale>
</version>
</xml>
您可以通过识别节点的位置来添加节点,然后使用众多方法之一插入新节点。您甚至可以操纵keywords
并传递整个NodeSet。您可以使用字符串,也可以创建新的Node实例。 Nokogiri对任何一个都很满意。
这些是查找和更改节点或其子节点所需的一些工具。您需要花些时间阅读Nokogiri's XML::Node documentation以了解其他可用内容以及哪些内容符合您的需求。你可以变得更复杂,但通常这是一个非常简单的过程来替换节点或移动它。