Skip to content

Instantly share code, notes, and snippets.

@kcurtin
Created February 14, 2016 16:34
Show Gist options
  • Save kcurtin/259302e3d66a62b47563 to your computer and use it in GitHub Desktop.
Save kcurtin/259302e3d66a62b47563 to your computer and use it in GitHub Desktop.
Interfacing with the erlang xmerl library to parse xml data. Using xml files from weather.gov for sample data (http://w1.weather.gov/xml/current_obs/)
defmodule WeatherParser do
require Record
Record.defrecord :xmlElement, Record.extract(:xmlElement, from_lib: "xmerl/include/xmerl.hrl")
Record.defrecord :xmlText, Record.extract(:xmlText, from_lib: "xmerl/include/xmerl.hrl")
def parse(xml, attrs) do
xml
|> :binary.bin_to_list
|> :xmerl_scan.string
|> extract_values(attrs, [])
end
def extract_values(xml, [], res), do: Enum.reverse(res)
def extract_values({xml, _rest}, list, res), do: extract_values(xml, list, res)
def extract_values(xml, [h | tail], res) do
val = extract_element(xml, h)
|> extract_content
|> extract_value
extract_values(xml, tail, [val | res])
end
def extract_element(xml, name), do: :xmerl_xpath.string('/current_observation/#{name}', xml)
def extract_content([element]), do: xmlElement(element, :content)
def extract_value([content_element]), do: xmlText(content_element, :value)
end
defmodule WeatherParserTest do
use ExUnit.Case
test "returns the specified attributes" do
data = WeatherParser.parse(sample_xml, [:location, :temp_f, :temp_c])
assert data == ['Unknown Station', '39.2', '4.0']
end
def sample_xml do
"""
<?xml version="1.0" encoding="ISO-8859-1"?>
<?xml-stylesheet href="latest_ob.xsl" type="text/xsl"?>
<current_observation version="1.0"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://www.weather.gov/view/current_observation.xsd">
<credit>NOAA's National Weather Service</credit>
<credit_URL>http://weather.gov/</credit_URL>
<image>
<url>http://weather.gov/images/xml_logo.gif</url>
<title>NOAA's National Weather Service</title>
<link>http://weather.gov</link>
</image>
<suggested_pickup>15 minutes after the hour</suggested_pickup>
<suggested_pickup_period>60</suggested_pickup_period>
<location>Unknown Station</location>
<station_id>ALIA2</station_id>
<observation_time>Last Updated on Feb 13 2016, 2:30 pm AST</observation_time>
<observation_time_rfc822>Sat, 13 Feb 2016 14:30:00 -0400</observation_time_rfc822>
<temperature_string>39.2 F (4.0 C)</temperature_string>
<temp_f>39.2</temp_f>
<temp_c>4.0</temp_c>
<water_temp_f>40.3</water_temp_f>
<water_temp_c>4.6</water_temp_c>
<wind_string>Northeast at 9.2 MPH (7.97 KT)</wind_string>
<wind_dir>Northeast</wind_dir>
<wind_degrees>60</wind_degrees>
<wind_mph>9.2</wind_mph>
<wind_gust_mph>0.0</wind_gust_mph>
<wind_kt>7.97</wind_kt>
<pressure_string>988.5 mb</pressure_string>
<pressure_mb>988.5</pressure_mb>
<windchill_string>33 F (1 C)</windchill_string>
<windchill_f>33</windchill_f>
<windchill_c>1</windchill_c>
<mean_wave_dir>Northeast</mean_wave_dir>
<mean_wave_degrees></mean_wave_degrees>
<disclaimer_url>http://weather.gov/disclaimer.html</disclaimer_url>
<copyright_url>http://weather.gov/disclaimer.html</copyright_url>
<privacy_policy_url>http://weather.gov/notice.html</privacy_policy_url>
</current_observation>
"""
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment