Reputation: 1580
I'm using Ruby, Norkigiri and Nori. I would like some thoughts about how I should go about parsing this XML file.
In this schema, an entity can include multiple contacts.
I need to return a hash of the following:
I thought about using xpath to try return the preferred email contact.
entities = doc.xpath("/entity_list/entity").each do |entity|
puts entity.xpath("contact_list/contact[contains(type,'Email') and contains(preferred, '1')]")
end
<entity>
<id>21925</id>
<last_name>Smith</last_name>
<first_name>John</first_name>
<preferred_name>Johnny</preferred_name>
<manager>Timmy</manager>
<dob>1970-01-01</dob>
<type>individual</type>
<contact_list>
<contact>
<type>Mobile Phone</type>
<preferred>0</preferred>
<value>563478653478</value>
</contact>
<contact>
<type>Pager</type>
<preferred>0</preferred>
<value>7354635345</value>
</contact>
<contact>
<notes>None</notes>
<type>Home Email</type>
<preferred>1</preferred>
<value>johhny@smith.com</value>
<comments>None</comments>
</contact>
<contact>
<notes>None</notes>
<type>Work Email</type>
<preferred>0</preferred>
<value>johhny@gmail.com</value>
<comments>None</comments>
</contact>
<contact>
<type>Home Phone</type>
<preferred>1</preferred>
<value>56537646365</value>
</contact>
</contact_list>
</entity>
What would be the best way to approach this problem?
Thanks
Upvotes: 0
Views: 197
Reputation: 7561
Here is one way of doing it (off the top of my head, based on your initial solution):
entities = doc.xpath("/entity_list/entity").map do |entity|
{
:id => entity.at_xpath("id").content.to_i,
:first_name => entity.at_xpath("first_name").content,
:last_name => entity.at_xpath("last_name").content,
:preferred_email => entity.at_xpath("contact_list/contact[contains(type,'Email') and contains(preferred, '1')]/value").content,
:manager => entity.at_xpath("manager").content
}
end
EDIT
To rescue from missing nodes you could use ActiveSupport's try
method, or just tack a rescue nil
onto the end of each line, e.g.:
:first_name => (entity.at_xpath("first_name").content rescue nil),
But it would be better to use a helper method, something like:
def get_node_content(entity, xpath)
node = entity.send(:at_xpath, xpath)
node ? node.content : nil
end
Then you could use it like:
:first_name => get_node_content(entity, "first_name"),
Upvotes: 1