Section numbering using xmerl:export

Mikael Karlsson <>
Fri Sep 13 21:31:20 CEST 2002


Hi Vlad,

thanks for your routine. If I understand it right it is a map function
of the "RoseTree" like structure of xmlElements. The problem was
that I needed to now where in the tree I was in order to set the
chapter numbers correctly. With a slight modification, adding
accumulator and folding top->down as well as left right I could
get things in place.

/Mikael

%% mapfoldxml
%% Fun is fun(Old#xmlElement, OldAccu) -> {New#xmlElement, NewAccu}

mapfoldxml(Fun, Accu0, #xmlElement{}=E) ->
    {C1,Accu1} = Fun(E, Accu0),
    {C2,Accu2} = mapfoldxml(Fun, Accu1, lists:flatten(C1#xmlElement.content)),
    {C1#xmlElement{content=C2},Accu2};
mapfoldxml(Fun, Accu, List) when list(List) ->
    AFun = fun(E,A) -> mapfoldxml(Fun, A, E) end,
    lists:mapfoldl(AFun, Accu, List);
mapfoldxml(_Fun, Accu, E) ->
    {E,Accu}.

changetitle(A) ->
	       Afun = fun changecount/2,
	       {E, Acc} = mapfoldxml(Afun, {0,0,0}, A),
	       E.

changecount(#xmlElement{name=title}=E, {A,B,C})->
    case E#xmlElement.parents of
     [{section,_},{section,_},{section,_},{article,_} |_] -> 
	addheader(E,{A,B,C+1}); 
     [{section,_},{section,_},{article,_} |_] -> 
        addheader(E,{A,B+1,0}); 
     [{section,_},{article,_} |_] -> 
        addheader(E,{A+1,0,0}); 
     _ -> 
        {E,{A,B,C}}
     end;
changecount(E, Acc)->{E,Acc}.

addheader(#xmlElement{name=title,content=[#xmlText{}=T1|_]}= E, Chapters)->
    NewHeader = chapterstring(Chapters)++ " " ++ T1#xmlText.value,
    NewAtts = addid(E#xmlElement.attributes, Chapters),
    {E#xmlElement{content=[T1#xmlText{value=NewHeader}],
		 attributes = NewAtts},Chapters}.

chapterstring({A,0,0})->integer_to_list(A);
chapterstring({A,B,0})->integer_to_list(A)++"."++ integer_to_list(B);
chapterstring({A,B,C})->integer_to_list(A) ++ "." ++
			  integer_to_list(B) ++ "." ++
			  integer_to_list(C).


torsdag 29 augusti 2002 12:09 skrev Vlad Dumitrescu:
> Hi,
>
> I don't know about the xmerl details, but I think it might be risky to rely
> on a implementation dependent feature... Of course, this depends on your
> application's use.
>
> The safe way would be going through the tree and numbering the nodes along
> the path. I have written a small routine that will traverse a xml tree and
> call a fun with every node. I think it might help you too (or others).
>
> best regards,
> Vlad
>
> %%% File    : xmerl_util.erl
> %%% Author  :  <>
> %%% Description :
> %%% Created : 14 Aug 2002 by  <>
>
> -module(xmerl_util).
> -export([traverse/2]).
> -include("xmerl.hrl").
>
> %% convert an xml doc into another
> %%
> %% Fun should return a xmlXXX record, or a list of such records
>
> traverse(#xmlElement{content=C}=E, Fun) ->
>     C1 = lists:flatten(traverse(C, Fun)),
>     Fun(E#xmlElement{content=C1});
> traverse(List, Fun) when list(List) ->
>     AFun = fun(E) -> traverse(E, Fun) end,
>     lists:map(AFun, List);
> traverse(E, _Fun) ->
>     E.




More information about the erlang-questions mailing list