Skip to content

Instantly share code, notes, and snippets.

@nkabardin
Created May 3, 2011 14:22
Show Gist options
  • Save nkabardin/953409 to your computer and use it in GitHub Desktop.
Save nkabardin/953409 to your computer and use it in GitHub Desktop.
Erlang xmerl-based simple xml parsing
# Example xml
<?xml version="1.0" encoding="UTF-8" ?>
<configuration>
<application id="test">
<platform id="vk">
<appId>123</appId>
<secretKey>secret</secretKey>
<packages>
<package id="vk0" price="100" points="3" />
<package id="vk1" price="500" points="20" />
<package id="vk2" price="1000" points="45" default="true" />
<package id="vk3" price="2500" points="130" />
<package id="vk4" price="5000" points="290" />
</packages>
</platform>
</application>
</configuration>
# Usage example
{Element, _} = xmerl_scan:string(binary_to_list(XmlData)),
Rules = {configuration, [],
[{application, [{id, to_atom}],
[{platform, [{id, to_atom}],
[
{appId, [], to_binary},
{secretKey, [], to_binary},
{packages, [], [
{package, [{id, to_atom},
{price, to_integer},
{points, to_integer},
{default, to_atom}], []}
]}
]
}]
}]
},
beenzaxml:process_xml(Element, Rules).
# Will return easy-to-use deep proplist:
[{application,
[{platform,
[{appId,<<"123">>},
{secretKey,<<"secret">>},
{packages,
[{package,[{points,3},{price,100},{id,vk0}]},
{package,[{points,20},{price,500},{id,vk1}]},
{package,
[{default,true},
{points,45},
{price,1000},
{id,vk2}]},
{package,[{points,130},{price,2500},{id,vk3}]},
{package,[{points,290},{price,5000},{id,vk4}]}]},
{id,vk}]},
{id,test}]}]
-module(beenzaxml).
-export([process_xml/2]).
-include_lib("xmerl/include/xmerl.hrl").
process_attributes(#xmlElement{attributes=Attributes}, Rules) ->
lists:foldl(fun (Attr, Acc) -> process_attribute(Attr, Acc, Rules) end, [], Attributes).
process_attribute(#xmlAttribute{} = Attribute, State, Rules) ->
Name = Attribute#xmlAttribute.name,
Value = Attribute#xmlAttribute.value,
ProcessedValue = process_value(Value, proplists:get_value(Name, Rules)),
[{Name, ProcessedValue}|State].
process_value(Value, Fun) when is_function(Fun ,1) -> Fun(Value);
process_value(Value, to_atom) -> list_to_atom(Value);
process_value(Value, to_integer) -> list_to_integer(Value);
process_value(Value, to_binary) -> list_to_binary(Value);
process_value(Value, _) -> Value.
element_text_content(#xmlElement{}=Element) ->
Content = Element#xmlElement.content,
ContentHead = hd(Content),
RawValue = ContentHead#xmlText.value,
iolist_to_binary(RawValue).
process_xml(Element, Rules) -> process_xml(Element, Rules, []).
process_xml(#xmlElement{name=TagName} = Element, {TagName, AttributesRules, ChildrenRules}, State) when is_list(ChildrenRules) ->
[{ElTag, process_xml(El, Rule, State)} ||
#xmlElement{name=ElTag} = El <- Element#xmlElement.content,
{RuleTag, _, _}=Rule <- ChildrenRules,
RuleTag==ElTag
] ++ process_attributes(Element, AttributesRules) ++ State;
process_xml(#xmlElement{} = Element, Rule, _State) ->
process_value(element_text_content(Element), Rule);
process_xml(_, _, State) -> State.
@jadeallenx
Copy link

Thanks for posting this - this looks like something I could use my project - what license is this code under?

@nkabardin
Copy link
Author

BSD, i think) Just use it if you want :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment