Nokogiri用于阅读和编辑Plist

时间:2020-08-23 06:14:20

标签: ruby xml nokogiri plist

我需要阅读和编辑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\"]")

如果我想在下获取一个由哈希组成的哈希数组(在Ruby中),该怎么办?

谢谢!

2 个答案:

答案 0 :(得分: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

答案 1 :(得分:0)

您可以使用 Ruby gems,例如 plist_lite

回答您的问题:

<块引用>

如果我想获取“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))