phizzy phizzy - 7 months ago 11
Ruby Question

Parsing out contents of XML tag in Ruby

I have an XML, that as I understand it has already been parsed by tags. My goal is to parse all the information that is in the

<GetResidentsContactInfoResult>
tag. In this tag of the sample xml below there are two records in here which begin each with the
Lease PropertyId
key. How can I iterate over the
<GetResidentsContactInfoResult>
tag and print out the key/value pairs for each record? I'm new to Ruby and working with XML files, is this something I can do with Nokogiri?

<?xml version="1.0" encoding="UTF-8"?>
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soap:Body>
<GetResidentsContactInfoResponse xmlns="http://tempuri.org/">
<GetResidentsContactInfoResult>&lt;PropertyResidents&gt;&lt;Lease PropertyId="21M" BldgID="00" UnitID="0903" ResiID="3" occustatuscode="P" occustatuscodedescription="Previous" MoveInDate="2016-01-07T00:00:00" MoveOutDate="2016-02-06T00:00:00" LeaseBeginDate="2016-01-07T00:00:00" LeaseEndDate="2017-01-31T00:00:00" MktgSource="DBY" PrimaryEmail="noemail1@fake.com"&gt;&lt;Occupant PropertyId="21M" BldgID="00" UnitID="0903" ResiID="3" OccuSeqNo="3444755" OccuFirstName="Efren" OccuLastName="Cerda" Phone2No="(832) 693-9448" ResponsibleFlag="Responsible" /&gt;&lt;/Lease&gt;&lt;Lease PropertyId="21M" BldgID="00" UnitID="0908" ResiID="2" occustatuscode="P" occustatuscodedescription="Previous" MoveInDate="2016-02-20T00:00:00" MoveOutDate="2016-04-25T00:00:00" LeaseBeginDate="2016-02-20T00:00:00" LeaseEndDate="2017-02-28T00:00:00" MktgSource="PW" PrimaryEmail="noemail1@fake.com"&gt;&lt;Occupant PropertyId="21M" BldgID="00" UnitID="0908" ResiID="2" OccuSeqNo="3451301" OccuFirstName="Donna" OccuLastName="Mclean" Phone2No="(713) 785-4240" ResponsibleFlag="Responsible" /&gt;&lt;/Lease&gt;&lt;/PropertyResidents&gt;</GetResidentsContactInfoResult>
</GetResidentsContactInfoResponse>
</soap:Body>
</soap:Envelope>

Answer

This uses Nokogiri to find all the GetResidentsContactInfoResponse elements, and then Active Support to convert the inner text to a hash of key-value pairs.

I assume you're fine with Nokogiri as you mentioned it in your question.

If you don't want to use Active Support, consider looking into "Convert a Nokogiri document to a Ruby Hash" as an alternative to the line Hash.from_xml(elm.text):

# Needed in order to use the `Hash.from_xml`
require 'active_support/core_ext/hash/conversions'

def find_key_values(str)
  doc = Nokogiri::XML(str)

  # Ignore namespaces for easier traversal
  doc.remove_namespaces!
  doc.css('GetResidentsContactInfoResponse').map do |elm|
    Hash.from_xml(elm.text)
  end
end

Usage:

# Option 1: if your XML above is stored in a variable called `string`
find_key_values string

# Option 2: if your XML above is stored in a file
find_key_values File.open('/path/to/file')

Which returns:

[{"PropertyResidents"=>
   {"Lease"=>
     [{"PropertyId"=>"21M",
       "BldgID"=>"00",
       "UnitID"=>"0903",
       "ResiID"=>"3",
       "occustatuscode"=>"P",
       "occustatuscodedescription"=>"Previous",
       "MoveInDate"=>"2016-01-07T00:00:00",
       "MoveOutDate"=>"2016-02-06T00:00:00",
       "LeaseBeginDate"=>"2016-01-07T00:00:00",
       "LeaseEndDate"=>"2017-01-31T00:00:00",
       "MktgSource"=>"DBY",
       "PrimaryEmail"=>"noemail1@fake.com",
       "Occupant"=>
        {"PropertyId"=>"21M",
         "BldgID"=>"00",
         "UnitID"=>"0903",
         "ResiID"=>"3",
         "OccuSeqNo"=>"3444755",
         "OccuFirstName"=>"Efren",
         "OccuLastName"=>"Cerda",
         "Phone2No"=>"(832) 693-9448",
         "ResponsibleFlag"=>"Responsible"}},
      {"PropertyId"=>"21M",
       "BldgID"=>"00",
       "UnitID"=>"0908",
       "ResiID"=>"2",
       "occustatuscode"=>"P",
       "occustatuscodedescription"=>"Previous",
       "MoveInDate"=>"2016-02-20T00:00:00",
       "MoveOutDate"=>"2016-04-25T00:00:00",
       "LeaseBeginDate"=>"2016-02-20T00:00:00",
       "LeaseEndDate"=>"2017-02-28T00:00:00",
       "MktgSource"=>"PW",
       "PrimaryEmail"=>"noemail1@fake.com",
       "Occupant"=>
        {"PropertyId"=>"21M",
         "BldgID"=>"00",
         "UnitID"=>"0908",
         "ResiID"=>"2",
         "OccuSeqNo"=>"3451301",
         "OccuFirstName"=>"Donna",
         "OccuLastName"=>"Mclean",
         "Phone2No"=>"(713) 785-4240",
         "ResponsibleFlag"=>"Responsible"}}]}}]
Comments