[英]How to get child node of an XML page using Ruby and REXML
我正在使用Ruby 1.9.3版。 這是我想從中獲取信息的實際XML頁面的簡單版本。 我需要從需要登錄憑據的安全網站訪問它。 我無法使用Nokogiri,因為我無法使用它登錄該網站。
<root>
<person>
<name>Jack</name>
<age>10</age>
</person>
<person>
<name>Jones</name>
</person>
<person>
<name>Jon</name>
<age>16</age>
</person>
</root>
如您所見,有時標記age
不會出現。 結合使用REXML和Ruby,我使用以下代碼:
agent = Mechanize.new
xml = agent.get("https://securewebsite.com/page.xml")
document = REXML::Document.new(xml.body)
name = XPath.match(document, "//person/name").map {|x| x.text}
# => ["Jack", "Jones", "Jon"]
age = XPath.match(document, "//person/age").map {|x| x.text}
# => ["10", "16"]
問題是我無法將age
與正確的name
相關聯,因為索引現在不正常了。 例如,在索引1處,名稱[1]是Jones,而age [1]是16。但這不是正確的,因為Jones的person
標簽沒有年齡標簽。
有什么方法可以獲取age
數組來輸出: # => ["10", nil ,"16"]
以便可以將正確的名稱與其相應的年齡相關聯?
或者,還有更好的方法? 讓我知道是否需要進一步說明。
問題在於我們將年齡和姓名視為完全獨立的信息集合。 我們需要做的是從個人那里收集信息。
xml = "<your xml here />"
doc = Nokogiri::XML(xml)
persons = doc.xpath("//person")
persons_data = persons.map {|person|
{
name: person.xpath("./name").text,
age: person.xpath("./age").text
}
}
這將獲取人員節點,然后從其獲取相關信息以給出結果:
puts persons_data.inspect #=> [
{:name=>"Jack", :age=>"10"},
{:name=>"Jones", :age=>""},
{:name=>"Jon", :age=>"16"}
]
因此,要獲取第一人稱呼的姓名和年齡
persons_data[0]["name"] #=> "Jack"
persons_data[0]["age"] #=> "10"
我會做這樣的事情:
require 'nokogiri'
doc = Nokogiri::XML(<<EOT)
<root>
<person>
<name>Jack</name>
<age>10</age>
</person>
<person>
<name>Jones</name>
</person>
<person>
<name>Jon</name>
<age>16</age>
</person>
</root>
EOT
people = doc.search('person').each_with_object({}){ |person, h|
age = person.at('age')
h[person.at('name').text] = age ? age.text : nil
}
people # => {"Jack"=>"10", "Jones"=>nil, "Jon"=>"16"}
在這一點上,如果我只想歲,我會使用values
:
people.values # => ["10", nil, "16"]
那么,獲取一個人的年齡很簡單:
people['Jon'] # => "16"
people['Jack'] # => "10"
我在使用.to_h方法時收到此錯誤:``在':中阻止:未定義的方法to_h'
我的錯。 to_h
不在較舊的to_h
中,但是由於我如何生成返回的哈希,因此不需要它。 我調整了上面的代碼,該代碼將在實現each_with_object
任何Ruby中each_with_object
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.