我有一个XML文件:
<One>
<Document Count="1">
<Customer Id="1" Type="0"/>
<Passengers>
<Passenger Seq="1" Id="13" Name="Test Name"/>
<Passenger Seq="2" Id="14" Name="Test Name4"/>
</Passengers>
</Document>
<Document Count="2">
<Customer Id="2" Type="0"/>
<Passengers>
<Passenger Seq="1" Id="16" Name="Test Name10"/>
<Passenger Seq="2" Id="18" Name="Test Name30"/>
</Passengers>
</Document>
</One>
...
<Two>
<Document Count="1">
<User Id="1" Type="0"/>
<Passengers>
<Passenger Seq="1" Id="123" Name="Test Name"/>
<Passenger Seq="2" Id="124" Name="Test Name2"/>
</Passengers>
</Document>
<Document Count="2">
<Customer Id="2" Type="0"/>
<Passengers>
<Passenger Seq="1" Id="1130" Name="Test Name123"/>
<Passenger Seq="2" Id="1131" Name="Test Name34342"/>
</Passengers>
</Document>
</Two>
我的步骤:
array = []
doc = Nokogiri::XML(File.open(file.xml))
doc_pass = doc.xpath("//Document//Passengers//Passenger")
doc_pass.each do |pass|
hash = {}
hash[:id] = pass['Name'] #???
array << hash
end
我希望从乘客那里获得所有属性,例如Id
,Name
,并为所有乘客创建哈希值。
例如:
[{ :id => '13', :name => "Test Name"}, { :id => '14', :name => "Test Name4"}, { :id => '16', :name => "Test Name10"}, { :id => '18', :name => "Test Name30"}, { :id => '123', :name => "Test Name"} ... ]
我该怎么做?
答案 0 :(得分:0)
只需替换
行 hash[:id] = pass['Name'] #???
带
hash[:id] = pass['Id']
hash[:name] = pass['Name']
只要您拥有有效的XML文件,它就能正常工作。
您问题中的XML片段无效,原因有两个:
...
和<One>
之间的<Two>
(我猜这是有意的,而不是您真实数据的问题)<One>
和<Two>
。如果这就是你的真实XML文件的组成方式,我认为Nokogiri只会读取第一个节点。答案 1 :(得分:0)
我发现您在代码中手动指定了属性。如果您想以您指定的格式获取所有属性,请尝试以下方法:
array = []
Nokogiri::XML(File.open(file.xml)).xpath("//Document//Passengers//Passenger").each do |x|
hash = {}
x.attributes.each do |attribute| # loop through all attributes in the matches found
hash[attribute[1].name.to_sym] = attribute[1].value
end
array << hash
end
array
应具有此值:
[{:Seq=>"1", :Id=>"13", :Name=>"Test Name"}, {:Seq=>"2", :Id=>"14", :Name=>"Test Name4"}, {:Seq=>"1", :Id=>"16", :Name=>"Test Name10"}, {:Seq=>"2", :Id=>"18", :Name=>"Test Name30"}]
答案 2 :(得分:0)
我这样做:
require 'nokogiri'
doc = Nokogiri::XML(<<EOT)
<xml>
<One>
<Document Count="1">
<Customer Id="1" Type="0"/>
<Passengers>
<Passenger Seq="1" Id="13" Name="Test Name"/>
<Passenger Seq="2" Id="14" Name="Test Name4"/>
</Passengers>
</Document>
<Document Count="2">
<Customer Id="2" Type="0"/>
<Passengers>
<Passenger Seq="1" Id="16" Name="Test Name10"/>
<Passenger Seq="2" Id="18" Name="Test Name30"/>
</Passengers>
</Document>
</One>
<Two>
<Document Count="1">
<User Id="1" Type="0"/>
<Passengers>
<Passenger Seq="1" Id="123" Name="Test Name"/>
<Passenger Seq="2" Id="124" Name="Test Name2"/>
</Passengers>
</Document>
<Document Count="2">
<Customer Id="2" Type="0"/>
<Passengers>
<Passenger Seq="1" Id="1130" Name="Test Name123"/>
<Passenger Seq="2" Id="1131" Name="Test Name34342"/>
</Passengers>
</Document>
</Two>
</xml>
EOT
以下是查找所有<Passenger>
个节点并获取其数据的方法:
array = doc.search('Passenger').map{ |node|
{
id: node['Id'],
name: node['Name']
}
}
这是array
的样子:
array
# => [{:id=>"13", :name=>"Test Name"},
# {:id=>"14", :name=>"Test Name4"},
# {:id=>"16", :name=>"Test Name10"},
# {:id=>"18", :name=>"Test Name30"},
# {:id=>"123", :name=>"Test Name"},
# {:id=>"124", :name=>"Test Name2"},
# {:id=>"1130", :name=>"Test Name123"},
# {:id=>"1131", :name=>"Test Name34342"}]
我正在使用CSS选择器。因为我想要所有的乘客&#34;节点,然后搜索变得容易,并且不需要向下钻取父节点链。
尽管使用/重用了哈希数组很难。如果:id
中没有碰撞的可能性,我建议使用常规哈希:
hash = doc.search('Passenger').map{ |node| [node['Id'], node['Name']] }.to_h
hash
# => {"13"=>"Test Name",
# "14"=>"Test Name4",
# "16"=>"Test Name10",
# "18"=>"Test Name30",
# "123"=>"Test Name",
# "124"=>"Test Name2",
# "1130"=>"Test Name123",
# "1131"=>"Test Name34342"}
如果您需要动态跟踪Passenger节点的所有参数,只要添加新的参数或删除旧的参数:
hash = doc.search('Passenger').map{ |node|
[
node['Id'],
node.attribute_nodes.map{ |a|
[a.name, a.value]
}.to_h
]
}.to_h
hash
# => {"13"=>{"Seq"=>"1", "Id"=>"13", "Name"=>"Test Name"},
# "14"=>{"Seq"=>"2", "Id"=>"14", "Name"=>"Test Name4"},
# "16"=>{"Seq"=>"1", "Id"=>"16", "Name"=>"Test Name10"},
# "18"=>{"Seq"=>"2", "Id"=>"18", "Name"=>"Test Name30"},
# "123"=>{"Seq"=>"1", "Id"=>"123", "Name"=>"Test Name"},
# "124"=>{"Seq"=>"2", "Id"=>"124", "Name"=>"Test Name2"},
# "1130"=>{"Seq"=>"1", "Id"=>"1130", "Name"=>"Test Name123"},
# "1131"=>{"Seq"=>"2", "Id"=>"1131", "Name"=>"Test Name34342"}}
基本上,&#l; ll会创建节点的哈希表示,这可能是好的,也可能是坏的,具体取决于您尝试对数据做什么。