source: trunk/src/xml2struct.m @ 685

Last change on this file since 685 was 685, checked in by sommeria, 11 years ago

error message improved for reading xml files

File size: 3.3 KB
Line 
1% 'xml2struct': read an xml file as a Matlab structure, converts numeric character strings into numbers
2%-----------------------------------------------------------------------
3% function s=xml2struct(filename)
4%
5% OUTPUT:
6% s= Matlab structure corresponding to the input xml file
7%
8% INPUT:
9% filename: name of the xml file
10% varargin: optional list of strings to restrict the reading to a selection of subtrees, for instance 'GeometryCalib' (save time)
11
12function [s,Heading,errormsg]=xml2struct(filename,varargin)
13s=[];
14Heading='';
15errormsg='';
16try
17t=xmltree(filename);
18catch ME
19    errormsg=ME.message;
20    if regexp(ME.message,'xml_findstr')
21        errormsg=[errormsg ': xmltree not correctly installed, download from www.artefact.tk/software/matlab/xml'];
22    end
23    return
24end
25iline=0;
26
27while isempty(Heading)
28    iline=iline+1;
29    if strcmp(get(t,iline,'type'),'element')
30        Heading=get(t,iline,'name');
31    end
32end
33if nargin>1
34    for isub=1:nargin-1
35        uid_sub=find(t,['/' Heading '/' varargin{isub}]);
36        if isempty(uid_sub)
37            s.(varargin{isub})=[];
38        else
39        tsub=branch(t,uid_sub);
40        ss=convert(tsub);
41        s.(varargin{isub})=convert_string(ss);
42        end
43    end
44else
45    ss=convert(t);
46    s=convert_string(ss);
47end
48
49
50function out=convert_string(ss)
51info=whos('ss');
52switch info.class
53    case 'struct'
54        out=[];%default
55        names = fieldnames(ss);
56        for k=1:length(names)
57            out.(names{k})=convert_string(ss.(names{k}));
58        end
59    case 'char'
60        out=ss; %reproduce the input string
61        % try to convert to number if the char does not correspond to a function (otherwise str2num calls this function as it uses 'eval')
62        if ~isempty(regexp(ss,'^(-*\d+\.*\d*\ *)+$')) || ~isempty(regexp(ss,'\d+e(-|+)\d+')) % if the string corresponds to a set of numbers (with possible sign and decimal, or scientific notation) separated by blanks
63            out=str2num(ss);
64        else
65            sep_ind=regexp(ss,'\s&\s');% check for separator ' & ' which indicates column separation in tables
66            if ~isempty(sep_ind)
67                sep_ind=[-2 sep_ind length(ss)+1];
68                for icolumn=1:length(sep_ind)-1
69                    out{1,icolumn}=ss(sep_ind(icolumn)+3:sep_ind(icolumn+1)-1);
70                end
71            else
72                out=ss; %reproduce the input string
73            end
74        end
75    case 'cell'
76        out=[];%default
77        check_numeric=zeros(size(ss));
78        for ilist=1:numel(ss)
79            if ~strcmp(ss{ilist},'image') && ~isempty(str2num(ss{ilist}))
80                out{ilist,1}=str2num(ss{ilist});
81                check_numeric(ilist)=1;
82            else
83                sep_ind=regexp(ss{ilist},'\s&\s');% check for separator ' & ' which indicates column separation in tables
84                if ~isempty(sep_ind)
85                    sep_ind=[-2 sep_ind length(ss{ilist})+1];
86                    for icolumn=1:length(sep_ind)-1
87                        out{ilist,icolumn}=ss{ilist}(sep_ind(icolumn)+3:sep_ind(icolumn+1)-1);
88                    end
89                else
90                    out{ilist,1}=ss{ilist}; %reproduce the input string
91                end
92            end
93        end
94        if isequal(check_numeric,ones(size(ss)))
95            out=cell2mat(out);
96        end
97    otherwise
98        out=ss;
99end
100
101   
Note: See TracBrowser for help on using the repository browser.