如何使用 Ruby 和 REXML 获取 XML 页面的子节点
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 处,name[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"
I get this error when I'm using the .to_h method: ``block in ': undefined method to_h'
我的错误。 to_h
不在较旧的 Rubies 中,但由于我生成返回的哈希的方式,因此不需要它。我调整了上面的代码,它将在任何实现 each_with_object
.
的 Ruby 中工作
我正在使用 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 处,name[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"
I get this error when I'm using the .to_h method: ``block in ': undefined method to_h'
我的错误。 to_h
不在较旧的 Rubies 中,但由于我生成返回的哈希的方式,因此不需要它。我调整了上面的代码,它将在任何实现 each_with_object
.