Last active
December 13, 2015 17:29
-
-
Save knowtheory/4948333 to your computer and use it in GitHub Desktop.
To run this, download the gist, and from the commandline type `ruby [path/to/the/gist.rb]` You should make sure you have Ruby and nokogiri installed on your computer first. N.B. just realized that the download gist link saves a zipped file that you will have to unzip to get to the xml_transformation.rb file.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <state name="Alabama"> | |
| <city name="Abbeville" number="1"/> | |
| <city name="Adamsville" number="1"/> | |
| <city name="Addison" number="1"/> | |
| <city name="Akron" number="2"/> | |
| </state> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| require 'nokogiri' | |
| # note that the states are wrapped inside <doc> tags. | |
| # nokogiri prefers dealing with just one top level node. | |
| text = <<-XML | |
| <doc> | |
| <state> | |
| <name>Alabama</name> | |
| <city>Abbeville</city> | |
| <number>1</number> | |
| </state> | |
| <state> | |
| <name>Alabama</name> | |
| <city>Adamsville</city> | |
| <number>1</number> | |
| </state> | |
| <state> | |
| <name>Alabama</name> | |
| <city>Addison</city> | |
| <number>1</number> | |
| </state> | |
| <state> | |
| <name>Alabama</name> | |
| <city>Akron</city> | |
| <number>2</number> | |
| </state> | |
| </doc> | |
| XML | |
| # parse the text into XML | |
| xml = Nokogiri::XML(text) | |
| # this is where we're storing the states | |
| states = {} | |
| # find all of the state nodes, and loop over them | |
| xml.css('state').each do |state| | |
| # get all of the pieces of text we care about. | |
| state_name = state.css('name').text | |
| city_name = state.css('city').text | |
| number = state.css('number').text | |
| # ensure that each state_name is stored as a hash in `states` | |
| # this uses ruby's conditional operator. it'd be equivalent to saying | |
| # states[state_name] = states[state_name] || {} | |
| # or | |
| # states[state_name] = {} unless states[state_name] | |
| states[state_name] ||= {} | |
| states[state_name][city_name] = number # assign each city it's number. | |
| end | |
| # If you wanted to work with the states in ruby, you could just stop here. | |
| # The code below is just to output some XML. | |
| # In general, if you've parsed some XML and extracted the data you want | |
| # it's often easier just to work with the data you've extracted | |
| # rather than stuffing it back into XML format. | |
| # loop over all the states we have extracted | |
| output = states.map do |state_name, cities| | |
| # generate a list of xml strings for each city | |
| # and merge them all together into one string. | |
| city_string = cities.map do |city_name, number| | |
| " <city name=\"#{city_name}\" number=\"#{number}\"/>" | |
| end.join("\n") | |
| # stick the merged xml we made for the cities into | |
| # a state node. | |
| "<state name=\"#{state_name}\">\n#{city_string}\n</state>" | |
| end | |
| # print the output. | |
| puts output |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment