Nokogiri 用于阅读和编辑 Plist

Posted

技术标签:

【中文标题】Nokogiri 用于阅读和编辑 Plist【英文标题】:Nokogiri for reading and editing Plist 【发布时间】:2020-08-23 06:14:20 【问题描述】:

我需要读取和编辑 plist 文件的一部分,它看起来像:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>Bookstore</key>
    <dict>
        <key>Public</key>
        <dict>
            <key>Books</key>
            <array>
                <dict>
                    <key>Name</key>
                    <string>The Old Man and the Sea</string>
                    <key>Author</key>
                    <string>Hemingway</string>
                </dict>
                <dict>
                    <key>Name</key>
                    <string>A Brief History of Time</string>
                    <key>Author</key>
                    <string>Stephen Hawkin</string>
                </dict>
            </array>
        </dict>
    </dict>
</dict>
</plist>

到目前为止我做了什么:

require 'nokogiri'
doc = doc = Nokogiri::XML(File.open("books.plist"))
doc.xpath("//dict[key=\"Bookstore\"]/dict[key=\"Public\"]/dict[key=\"Books\"]")

如果我想获得 “Book”下元素的散列数组(在 Ruby 中),接下来我应该做什么?

谢谢!

【问题讨论】:

【参考方案1】:

我认为您可以扩展您的选择以准确获取您需要的元素:

require 'nokogiri'

doc = Nokogiri::XML(File.open("books.plist"))
books = doc.xpath("//dict[key='Bookstore']/dict[key='Public']/dict[key='Books']/array/dict")

然后你可以通过子选择,或者遍历,将这组书本元素转换成你想要的形状,但是子选择可能看起来像这样:


final = books.map do |book|
  keys = book.xpath("key/text()").map(&:to_s)
  values = book.xpath("string/text()").map(&:to_s)
  Hash[keys.zip(values)]
end

【讨论】:

谢谢,它有效!如果我更改任何值,比如书的 aurhor,我应该如何将其保存回原始 plist?【参考方案2】:

你可以使用像plist_lite这样的Ruby gems

回答你的问题:

如果我想获取“Book”下元素的散列数组(在 Ruby 中),下一步该怎么做?

ruby -rplist_lite -e 'pp PlistLite.load($stdin.read)["Bookstore"]["Public"]["Books"]' <<EOS
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>Bookstore</key>
    <dict>
        <key>Public</key>
        <dict>
            <key>Books</key>
            <array>
                <dict>
                    <key>Name</key>
                    <string>The Old Man and the Sea</string>
                    <key>Author</key>
                    <string>Hemingway</string>
                </dict>
                <dict>
                    <key>Name</key>
                    <string>A Brief History of Time</string>
                    <key>Author</key>
                    <string>Stephen Hawkin</string>
                </dict>
            </array>
        </dict>
    </dict>
</dict>
</plist>
EOS

输出

["Name"=>"The Old Man and the Sea", "Author"=>"Hemingway",
 "Name"=>"A Brief History of Time", "Author"=>"Stephen Hawkin"]

如果你不想额外依赖,你仍然可以参考它的源代码,plist_lite 也使用nokogiri 进行解析:

https://github.com/tonytonyjan/plist_lite/blob/master/lib/plist_lite.rb#L37-L57

要更新 plist 文件,请使用 PlistLite#dump:

obj = PlistLite.load(IO.read('test.plist'))
# modify obj...
IO.write('test.plist', PlistLite.dump(obj))

【讨论】:

以上是关于Nokogiri 用于阅读和编辑 Plist的主要内容,如果未能解决你的问题,请参考以下文章

创建“Nokogiri::XML”或“Nokogiri::HTML”对象时如何避免创建无意义的空白文本节点

Nokogiri:解析和更新 Plist 中的值

如何使用 Nokogiri 解析 HTML 表格?

在 OSX 10.10 Yosemite 上安装 Nokogiri

LoadError:库版本不兼容 - /home/ubuntu/.rvm/gems/ruby-2.3.1@lm5/gems/nokogiri-1.8.2/lib/nokogiri/nokogiri.s

使用 Nokogiri 和 Selenium,如果驱动程序无法执行命令,是不是可以跳过它?