source: trunk/src/@xmltree/convert.m @ 975

Last change on this file since 975 was 925, checked in by sommeria, 9 years ago

xmltree updated

File size: 5.6 KB
Line 
1function s = convert(tree,uid)
2% XMLTREE/CONVERT Converter an XML tree in a structure
3%
4% tree      - XMLTree object
5% uid       - uid of the root of the subtree, if provided.
6%             Default is root
7% s         - converted structure
8%__________________________________________________________________________
9%
10% Convert an XMLTree into a structure, when possible.
11% When several identical tags are present, a cell array is used.
12% The root tag is not saved in the structure.
13% If provided, only the structure corresponding to the subtree defined
14% by the uid UID is returned.
15%__________________________________________________________________________
16% Copyright (C) 2002-2015  http://www.artefact.tk/
17
18% Guillaume Flandin
19% $Id: convert.m 6480 2015-06-13 01:08:30Z guillaume $
20
21% Exemple:
22% tree = '<a><b>field1</b><c>field2</c><b>field3</b></a>';
23% toto = convert(xmltree(tree));
24% <=> toto = struct('b',{{'field1', 'field3'}},'c','field2')
25
26%error(nargchk(1,2,nargin));
27
28% Get the root uid of the output structure
29if nargin == 1
30    % Get the root uid of the XML tree
31    root_uid = root(tree);
32else
33    % Uid provided by user
34    root_uid = uid;
35end
36
37% Initialize the output structure
38% struct([]) should be used but this only works with Matlab 6
39% So we create a field that we delete at the end
40%s = struct(get(tree,root_uid,'name'),''); % struct([])
41s = struct('deletedummy','');
42
43%s = sub_convert(tree,s,root_uid,{get(tree,root_uid,'name')});
44s = sub_convert(tree,s,root_uid,{});
45
46s = rmfield(s,'deletedummy');
47
48%==========================================================================
49function s = sub_convert(tree,s,uid,arg)
50    type = get(tree,uid,'type');
51    switch type
52        case 'element'
53            child = children(tree,uid);
54            l = {};
55            ll = {};
56            for i=1:length(child)
57                if isfield(tree,child(i),'name')
58                    ll = { ll{:}, get(tree,child(i),'name') };
59                end
60            end
61            for i=1:length(child)
62                if isfield(tree,child(i),'name')
63                    name = get(tree,child(i),'name');
64                    nboccur = sum(ismember(l,name));
65                    nboccur2 = sum(ismember(ll,name));
66                    l = { l{:}, name };
67                    if nboccur || (nboccur2>1)
68                        arg2 = { arg{:}, name, {nboccur+1} };
69                    else
70                        arg2 = { arg{:}, name};
71                    end
72                else
73                    arg2 = arg;
74                end
75                s = sub_convert(tree,s,child(i),arg2);
76            end
77            if isempty(child)
78                s = sub_setfield(s,arg{:},'');
79            end
80            %- saving attributes : does not work with <a t='q'>b</a>
81            %- but ok with <a t='q'><c>b</c></a>
82%             attrb = attributes(tree,'get',uid);     %-
83%             if ~isempty(attrb)                      %-
84%                 arg2 = {arg{:} 'attributes'};       %-
85%                 s = sub_setfield(s,arg2{:},attrb);  %-
86%             end                                     %-
87        case 'chardata'
88            s = sub_setfield(s,arg{:},get(tree,uid,'value'));
89            %- convert strings into their numerical equivalent when possible
90            %- e.g. string '3.14159' becomes double scalar 3.14159
91%             v = get(tree,uid,'value');              %-
92%             cv = str2num(v);                        %-
93%             if isempty(cv)                          %-
94%                 s = sub_setfield(s,arg{:},v);       %-
95%             else                                    %-
96%                 s = sub_setfield(s,arg{:},cv);      %-
97%             end                                     %-
98        case 'cdata'
99            s = sub_setfield(s,arg{:},get(tree,uid,'value'));
100        case 'pi'
101            % Processing instructions are evaluated if possible
102            app = get(tree,uid,'target');
103            switch app
104                case {'matlab',''}
105                    s = sub_setfield(s,arg{:},eval(get(tree,uid,'value')));
106                case 'unix'
107                    s = sub_setfield(s,arg{:},unix(get(tree,uid,'value')));
108                case 'dos'
109                    s = sub_setfield(s,arg{:},dos(get(tree,uid,'value')));
110                case 'system'
111                    s = sub_setfield(s,arg{:},system(get(tree,uid,'value')));
112                otherwise
113                    try
114                        s = sub_setfield(s,arg{:},feval(app,get(tree,uid,'value')));
115                    catch
116                        warning('[XMLTree] Unknown target application');
117                    end
118            end
119        case 'comment'
120            % Comments are forgotten
121        otherwise
122            warning(sprintf('Type %s unknown : not saved',get(tree,uid,'type')));
123    end
124   
125%==========================================================================
126function s = sub_setfield(s,varargin)
127% Same as setfield but using '{}' rather than '()'
128%if (isempty(varargin) | length(varargin) < 2)
129%    error('Not enough input arguments.');
130%end
131
132subs = varargin(1:end-1);
133for i = 1:length(varargin)-1
134    if (isa(varargin{i}, 'cell'))
135        types{i} = '{}';
136    elseif ischar(varargin{i})
137        types{i} = '.';
138        subs{i} = varargin{i}; %strrep(varargin{i},' ',''); % deblank field name
139    else
140        error('Inputs must be either cell arrays or strings.');
141    end
142end
143
144% Perform assignment
145try
146   s = builtin('subsasgn', s, struct('type',types,'subs',subs), varargin{end});
147catch
148   error(lasterr)
149end
Note: See TracBrowser for help on using the repository browser.