-
Notifications
You must be signed in to change notification settings - Fork 0
/
struct2xml.m
198 lines (175 loc) · 7.09 KB
/
struct2xml.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
function varargout = struct2xml( s, varargin )
%Convert a MATLAB structure into a xml file
% [ ] = struct2xml( s, file )
% xml = struct2xml( s )
%
% A structure containing:
% s.XMLname.Attributes.attrib1 = "Some value";
% s.XMLname.Element.Text = "Some text";
% s.XMLname.DifferentElement{1}.Attributes.attrib2 = "2";
% s.XMLname.DifferentElement{1}.Text = "Some more text";
% s.XMLname.DifferentElement{2}.Attributes.attrib3 = "2";
% s.XMLname.DifferentElement{2}.Attributes.attrib4 = "1";
% s.XMLname.DifferentElement{2}.Text = "Even more text";
%
% Will produce:
% <XMLname attrib1="Some value">
% <Element>Some text</Element>
% <DifferentElement attrib2="2">Some more text</Element>
% <DifferentElement attrib3="2" attrib4="1">Even more text</DifferentElement>
% </XMLname>
%
% Please note that the following strings are substituted
% '_dash_' by '-', '_colon_' by ':' and '_dot_' by '.'
%
% Written by W. Falkena, ASTI, TUDelft, 27-08-2010
% On-screen output functionality added by P. Orth, 01-12-2010
% Multiple space to single space conversion adapted for speed by T. Lohuis, 11-04-2011
% Val2str subfunction bugfix by H. Gsenger, 19-9-2011
if (nargin ~= 2)
if(nargout ~= 1 || nargin ~= 1)
error(['Supported function calls:' sprintf('\n')...
'[ ] = struct2xml( s, file )' sprintf('\n')...
'xml = struct2xml( s )']);
end
end
if(nargin == 2)
file = varargin{1};
if (isempty(file))
error('Filename can not be empty');
end
if (isempty(strfind(file,'.xml')))
file = [file '.xml'];
end
end
if (~isstruct(s))
error([inputname(1) ' is not a structure']);
end
if (length(fieldnames(s)) > 1)
error(['Error processing the structure:' sprintf('\n') 'There should be a single field in the main structure.']);
end
xmlname = fieldnames(s);
xmlname = xmlname{1};
%substitute special characters
xmlname_sc = xmlname;
xmlname_sc = strrep(xmlname_sc,'_dash_','-');
xmlname_sc = strrep(xmlname_sc,'_colon_',':');
xmlname_sc = strrep(xmlname_sc,'_dot_','.');
%create xml structure
docNode = com.mathworks.xml.XMLUtils.createDocument(xmlname_sc);
%process the rootnode
docRootNode = docNode.getDocumentElement;
%append childs
parseStruct(s.(xmlname),docNode,docRootNode,[inputname(1) '.' xmlname '.']);
if(nargout == 0)
%save xml file
xmlwrite(file,docNode);
else
varargout{1} = xmlwrite(docNode);
end
end
% ----- Subfunction parseStruct -----
function [] = parseStruct(s,docNode,curNode,pName)
fnames = fieldnames(s);
for i = 1:length(fnames)
curfield = fnames{i};
%substitute special characters
curfield_sc = curfield;
curfield_sc = strrep(curfield_sc,'_dash_','-');
curfield_sc = strrep(curfield_sc,'_colon_',':');
curfield_sc = strrep(curfield_sc,'_dot_','.');
if (strcmp(curfield,'Attributes'))
%Attribute data
if (isstruct(s.(curfield)))
attr_names = fieldnames(s.Attributes);
for a = 1:length(attr_names)
cur_attr = attr_names{a};
%substitute special characters
cur_attr_sc = cur_attr;
cur_attr_sc = strrep(cur_attr_sc,'_dash_','-');
cur_attr_sc = strrep(cur_attr_sc,'_colon_',':');
cur_attr_sc = strrep(cur_attr_sc,'_dot_','.');
[cur_str,succes] = val2str(s.Attributes.(cur_attr));
if (succes)
curNode.setAttribute(cur_attr_sc,cur_str);
else
disp(['Warning. The text in ' pName curfield '.' cur_attr ' could not be processed.']);
end
end
else
disp(['Warning. The attributes in ' pName curfield ' could not be processed.']);
disp(['The correct syntax is: ' pName curfield '.attribute_name = ''Some text''.']);
end
elseif (strcmp(curfield,'Text'))
%Text data
[txt,succes] = val2str(s.Text);
if (succes)
curNode.appendChild(docNode.createTextNode(txt));
else
disp(['Warning. The text in ' pName curfield ' could not be processed.']);
end
else
%Sub-element
if (isstruct(s.(curfield)))
%single element
curElement = docNode.createElement(curfield_sc);
curNode.appendChild(curElement);
parseStruct(s.(curfield),docNode,curElement,[pName curfield '.'])
elseif (iscell(s.(curfield)))
%multiple elements
for c = 1:length(s.(curfield))
curElement = docNode.createElement(curfield_sc);
curNode.appendChild(curElement);
if (isstruct(s.(curfield){c}))
parseStruct(s.(curfield){c},docNode,curElement,[pName curfield '{' num2str(c) '}.'])
else
disp(['Warning. The cell ' pName curfield '{' num2str(c) '} could not be processed, since it contains no structure.']);
end
end
else
%eventhough the fieldname is not text, the field could
%contain text. Create a new element and use this text
curElement = docNode.createElement(curfield_sc);
curNode.appendChild(curElement);
[txt,succes] = val2str(s.(curfield));
if (succes)
curElement.appendChild(docNode.createTextNode(txt));
else
disp(['Warning. The text in ' pName curfield ' could not be processed.']);
end
end
end
end
end
%----- Subfunction val2str -----
function [str,succes] = val2str(val)
succes = true;
str = [];
if (isempty(val))
return; %bugfix from H. Gsenger
elseif (ischar(val))
%do nothing
elseif (isnumeric(val))
val = num2str(val);
else
succes = false;
end
if (ischar(val))
%add line breaks to all lines except the last (for multiline strings)
lines = size(val,1);
val = [val char(sprintf('\n')*[ones(lines-1,1);0])];
%transpose is required since indexing (i.e., val(nonspace) or val(:)) produces a 1-D vector.
%This should be row based (line based) and not column based.
valt = val';
%remove_multiple_white_spaces = true;
%if (remove_multiple_white_spaces)
%remove multiple white spaces using isspace, suggestion of T. Lohuis
whitespace = isspace(val);
nonspace = (whitespace + [zeros(lines,1) whitespace(:,1:end-1)])~=2;
nonspace(:,end) = [ones(lines-1,1);0]; %make sure line breaks stay intact
str = valt(nonspace');
%else
% str = valt(:);
%end
end
end