Reputation:
Folks,
I am using REXML for a sample XML file:
<Accounts title="This is the test title">
<Account name="frenchcustomer">
<username name = "frencu"/>
<password pw = "hello34"/>
<accountdn dn = "https://frenchcu.com/"/>
<exporttest name="basic">
<exportname name = "basicexport"/>
<exportterm term = "oldschool"/>
</exporttest>
</Account>
<Account name="britishcustomer">
<username name = "britishcu"/>
<password pw = "mellow34"/>
<accountdn dn = "https://britishcu.com/"/>
<exporttest name="existingsearch">
<exportname name = "largexpo"/>
<exportterm term = "greatschool"/>
</exporttest>
</Account>
</Accounts>
I am reading the XML like this:
@data = (REXML::Document.new file).root
@dataarr = @@testdata.elements.to_a("//Account")
Now I want to get the username of the frenchcustomer, so I tried this:
@dataarr[@name=fenchcustomer].elements["username"].attributes["name"]
this fails, I do not want to use the array index, for example
@dataarr[1].elements["username"].attributes["name"]
will work, but I don't want to do that, is there something that i m missing here. I want to use the array and get the username of the french user using the Account name.
Thanks a lot.
Upvotes: 1
Views: 6848
Reputation: 10726
I recommend you to use XPath
.
For the first match, you can use first
method, for an array, just use match
.
The code above returns the username for the Account "frenchcustomer" :
REXML::XPath.first(yourREXMLDocument, "//Account[@name='frenchcustomer']/username/@name").value
If you really want to use the array created with @@testdata.elements.to_a("//Account")
, you could use find
method :
french_cust_elt = the_array.find { |elt| elt.attributes['name'].eql?('frenchcustomer') }
french_username = french_cust_elt.elements["username"].attributes["name"]
Upvotes: 3
Reputation: 160191
puts @data.elements["//Account[@name='frenchcustomer']"]
.elements["username"]
.attributes["name"]
If you want to iterate over multiple identical names:
@data.elements.each("//Account[@name='frenchcustomer']") do |fc|
puts fc.elements["username"].attributes["name"]
end
Upvotes: 1
Reputation: 27855
I don't know what your @@testdata
are, I tried with the following testcode:
require "rexml/document"
@data = (REXML::Document.new DATA).root
@dataarr = @data.elements.to_a("//Account")
# Works
p @dataarr[1].elements["username"].attributes["name"]
#Works not
#~ p @dataarr[@name='fenchcustomer'].elements["username"].attributes["name"]
#@dataarr is an array
@dataarr.each{|acc|
next unless acc.attributes['name'] =='frenchcustomer'
p acc.elements["username"].attributes["name"]
}
#@dataarr is an array
puts "===Array#each"
@dataarr.each{|acc|
next unless acc.attributes['name'] =='frenchcustomer'
p acc.elements["username"].attributes["name"]
}
puts "===XPATH"
@data.elements.to_a("//Account[@name='frenchcustomer']").each{|acc|
p acc.elements["username"].attributes["name"]
}
__END__
<Accounts title="This is the test title">
<Account name="frenchcustomer">
<username name = "frencu"/>
<password pw = "hello34"/>
<accountdn dn = "https://frenchcu.com/"/>
<exporttest name="basic">
<exportname name = "basicexport"/>
<exportterm term = "oldschool"/>
</exporttest>
</Account>
<Account name="britishcustomer">
<username name = "britishcu"/>
<password pw = "mellow34"/>
<accountdn dn = "https://britishcu.com/"/>
<exporttest name="existingsearch">
<exportname name = "largexpo"/>
<exportterm term = "greatschool"/>
</exporttest>
</Account>
</Accounts>
I'm not very familiar with rexml, so I expect there is a better solution. But perhaps aomebody can take my code to build a better solution.
Upvotes: 0