XML Stream Parsing in Erlang, II

In my previous post, I complained a lot about trying to get XML stream parsing working. Ultimately, I just decided to rip the guts out of ejabberd, rather than reinvent the wheel. The relevant files are xml_stream.erl, xml.erl, and expat_erl.c. You can see how to use it in ejabberd_receiver.erl. Frankly, these guys seem to have it pretty well figured out. The way I went about it is this: using the tcp-client gen_fsm from here, I added init code to load up the library in start_link, with something like this:

case erl_ddll:load_driver(“ebin”, expat_erl) of
ok -> ok;
{error, already_loaded} -> ok;
{error, Reason} ->
error_logger:error_msg(“Could not load expat driver: ~p~n”,
erl_ddll:format_error(Reason))
end

I added a bit to the fsm state record to manage the xml state. When a client connects and the process gets started for it in the 'WAIT_FOR_SOCKET'({socket_ready, Socket}, State) when is_port(Socket) call, I initialize the xml parser xml_stream:new(self()) and store that in the record. Upon receiving data in 'WAIT_FOR_DATA'({data, Data},, I call NewXmlState = xml_stream:parse(XmlState, Data) and update the record with the new state. Then, messages just appear in the fsm queue and I handle them. What I do, specifically, is set up another fsm and send it messages that have been parsed, so that it essentially abstracts away the tcp and the xml. My plan is to add udp functionality that uses the same interface, so that datagrams look just like stanza’d messages and the process doesn’t need to know where the data came from.

Leave a Reply

You must be logged in to post a comment.