xmerl exporting with namespace?

Fredrik Thulin <>
Wed Jun 14 11:35:26 CEST 2006


Hi

I am most unfortunate, I have to not only parse XML documents, but also 
try to merge XML documents ;(.

I think the easiest way to explain my problem is with the attached 
module.

The problem is that x:output_tuples() (which uses 
xmerl:export_simple_content(Tuples, xmerl_xml) produces the following :

<pr:tuple id="sd04cf079">
    <pr:status><pr:basic>open</pr:basic></pr:status>
    <pr:note>Idle</pr:note>
    <rpid:user-input 
      last-input="2006-06-13T21:40:17Z">idle</rpid:user-input>
    <pr:timestamp>2006-06-13T21:40:17Z</pr:timestamp>
  </pr:tuple>

To put that into another XML document, I need the namespace information 
that _was_ available in the xmlElement record outputted, something like

<pr:tuple xmlns:pr="urn:ietf:params:xml:ns:pidf" id="sd04cf079">
    <pr:status><pr:basic>open</pr:basic></pr:status>
    <pr:note>Idle</pr:note>
    <rpid:user-input xmlns:rpid="urn:ietf:params:xml:ns:pidf:rpid"
      last-input="2006-06-13T21:40:17Z">idle</rpid:user-input>
    <pr:timestamp>2006-06-13T21:40:17Z</pr:timestamp>
  </pr:tuple>

(I'm no XML expert, far from). Is that possible somehow?

/Fredrik
-------------- next part --------------
-module(x).
-compile(export_all).

-include_lib("xmerl/include/xmerl.hrl").

%% example SIP/SIMPLE Presence PIDF XML document
in() ->
    "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\" ?>\n"
        "<pr:presence xmlns:pr=\"urn:ietf:params:xml:ns:pidf\" entity=\"sip:\""
        "       xmlns:caps=\"urn:ietf:params:xml:ns:pidf:caps\""
        "       xmlns:cipid=\"urn:ietf:params:xml:ns:pidf:cipid\""
        "       xmlns:counterpath=\"www.counterpath.com/presence/ext\""
        "       xmlns:dm=\"urn:ietf:params:xml:ns:pidf:data-model\""
        "       xmlns:rpid=\"urn:ietf:params:xml:ns:pidf:rpid\">\n"
        "  <pr:tuple id=\"sd04cf079\">\n"
        "    <pr:status><pr:basic>open</pr:basic></pr:status>\n"
        "    <pr:note>Idle</pr:note>\n"
        "    <rpid:user-input last-input=\"2006-06-13T21:40:17Z\">idle</rpid:user-input>\n"
        "    <pr:timestamp>2006-06-13T21:40:17Z</pr:timestamp>\n"
        "  </pr:tuple>\n"
        "  <dm:person id=\"p8652f666\">\n"
        "    <dm:note>Idle</dm:note>\n"
        "  </dm:person>\n"
        "</pr:presence>\n".

%% parse the example XML document, namespace_conformant
parse() ->
    parse( in() ).

parse(Src) when is_list(Src) ->
    try xmerl_scan:string(Src, [{namespace_conformant, true}]) of
        {XML, []} ->
	    XML;
        _ ->
            {error, bad_xml}
    catch
        _: _ ->
            {error, failed_parsing}
    end.

%% get the PIDF tuples (<pr:tuple ...> in the XML source)
get_tuples() ->
    XML = parse(),
    get_tuples(XML).

get_tuples(XML) when is_record(XML, xmlElement) ->
     get_xml_elements(tuple, XML#xmlElement.content).


get_xml_elements(Name, In) when is_atom(Name), is_list(In) ->
    get_xml_elements2(Name, In, []).

get_xml_elements2(Name, [#xmlElement{name = Name} = H | T], Res) ->
    get_xml_elements2(Name, T, [H | Res]);
get_xml_elements2(Name, [#xmlElement{expanded_name = {_URI, Name}} = H | T], Res) ->
    get_xml_elements2(Name, T, [H | Res]);
get_xml_elements2(Name, [_H | T], Res) ->
    get_xml_elements2(Name, T, Res);
get_xml_elements2(_Name, [], Res) ->
    lists:reverse(Res).

%% Output only the PIDF tuple(s), this is where I am missing the namespace information
output_tuples() ->
    Tuples = get_tuples(),
    output_tuples(Tuples).

output_tuples(Tuples) when is_list(Tuples) ->
    Out = xmerl:export_simple_content(Tuples, xmerl_xml),
    io:format("~s~n~n", [lists:flatten(Out)]),
    ok.


More information about the erlang-questions mailing list