comparison m-toolbox/classes/+utils/@xml/xmlwrite.m @ 0:f0afece42f48

Import.
author Daniele Nicolodi <nicolodi@science.unitn.it>
date Wed, 23 Nov 2011 19:22:13 +0100
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:f0afece42f48
1 % XMLWRITE Add an object to a xml DOM project.
2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3 %
4 % DESCRIPTION: XMLWRITE Add an object to a xml DOM project.
5 %
6 % EXAMPLE: xml = com.mathworks.xml.XMLUtils.createDocument('ltpda_object');
7 % parent = xml.getDocumentElement;
8 %
9 % xmlwrite(a, xml, parent, '');
10 %
11 % xmlwrite('foo.xml', xml);
12 %
13 % FORMAT: This function writes the object into the following xml format:
14 %
15 % ---------------------- ltpda_object ----------------------
16 %
17 % <ltpda_object>
18 %
19 % --> <object> ...
20 % --> <cell> ...
21 %
22 % </ltpda_object>
23 %
24 % ------------------------- object -------------------------
25 %
26 % <object> ('type' - attribute)
27 %
28 % <property> ...
29 %
30 % </object>
31 %
32 % ------------------------ property ------------------------
33 % -------------------------- cell --------------------------
34 %
35 % <property> ('type', 'prop_name' -attributes)
36 % OR <cell> ('type' -attribute)
37 %
38 % --> atomic element
39 % - empty cell
40 % - empty double
41 % - empty char
42 % - char
43 % - double
44 % - logical
45 % - java (necessary for timezone)
46 % --> <cell> ...
47 % --> <object> ...
48 % --> <real_data> ...
49 % <imag_data> ...
50 %
51 % </property>
52 % OR </cell>
53 %
54 % ------- real_data --------|-------- imag_data --------
55 % |
56 % <real_data>('type'-attribute) | <imag_data> ('type' -attribute)
57 % ('shape'-attribute)| ('shape'-attribute)
58 % |
59 % --> <matrix> ... | --> <matrix> ...
60 % --> <vector> ... | --> <vector> ...
61 % |
62 % </real_data> | </imag_data>
63 % |
64 % --------- matrix -------------------- vector ---------
65 % |
66 % <matrix> ('type' -attribute) | <vector> ('type' -attribute)
67 % |
68 % row vector (double) | column vector (double)
69 % |
70 % </matrix> | </vector>
71 %
72 % SYMBOLS: --> Marks a choice between alternatives.
73 % ... Indicate that an element may be repeated.
74 %
75 % VERSION: $Id: xmlwrite.m,v 1.7 2011/03/28 17:04:27 ingo Exp $
76 %
77 % HISTORY: 31-01-2008 Diepholz
78 % Creation
79 %
80 % SEE ALSO: utils.xml.xmlread
81 %
82 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
83 function varargout = xmlwrite(objs, xml, parent, property_name)
84
85 %%%%%% Workaround for saving as the new XML format %%%%%%
86 ltpda_version = getappdata(0, 'ltpda_version');
87 if (utils.helper.ver2num(ltpda_version) > utils.helper.ver2num('2.3')) || ...
88 (strcmp(strtok(ltpda_version), '2.3'))
89 %%%%%%%%%%%%%%%%%% reading of a new XML file %%%%%%%%%%%%%%%%%%
90
91 % Create history root node
92 % The attachToDom methods will attach their histories to this node.
93 historyRootNode = xml.createElement('historyRoot');
94 parent.appendChild(historyRootNode);
95
96 % Write objects
97 collectedHist = objs.attachToDom(xml, parent, []);
98 return
99 end
100
101 %%%%%% If the property_name is filled then create a new property node %%%%%
102 if ~isempty(property_name)
103 shape = sprintf('%dx%d', size(objs,1), size(objs,2));
104 prop_node = xml.createElement('property');
105 prop_node.setAttribute('prop_name', property_name);
106 prop_node.setAttribute('shape', shape);
107 prop_node.setAttribute('type', class(objs));
108 parent.appendChild(prop_node);
109 parent = prop_node;
110 end
111
112 %%%%%%%%%%%%%%%% The object is a class object or a struct %%%%%%%%%%%%%%%%%
113 if (isobject(objs) || isstruct(objs)) && ~isa(objs, 'sym')
114
115 if isa(objs, 'ltpda_obj')
116 %%%%% Skip empty fields for unser objects %%%%%
117 for ii = 1:numel(objs)
118 obj = objs(ii);
119 shape = sprintf('%dx%d', size(objs,1), size(objs,2));
120 obj_node = xml.createElement('object');
121 obj_node.setAttribute('type', class(obj));
122 obj_node.setAttribute('shape', shape);
123 parent.appendChild(obj_node);
124 if isa(obj, 'minfo')
125
126 % we don't write all fields
127 info = obj.getEncodedString;
128 obj_node.setAttribute('info', info);
129
130 elseif isa(obj, 'provenance')
131
132 % write info
133 info = obj.getEncodedString;
134 obj_node.setAttribute('info', info);
135
136 elseif isa(obj, 'param')
137
138 obj_node.setAttribute('key', obj.key');
139 val = obj.getDefaultVal;
140 utils.xml.xmlwrite(val, xml, obj_node, 'value');
141
142 elseif isa(obj, 'time')
143
144 % write utc_epoch_milli
145 obj_node.setAttribute('utc', num2str(obj.utc_epoch_milli));
146 % write timezone
147 obj_node.setAttribute('timezone', char(obj.timezone.getID));
148 % write timeformat
149 obj_node.setAttribute('timeformat', obj.timeformat);
150
151 else
152 fields = getFieldnames(obj);
153 for jj = 1:length(fields)
154 if ~isempty(obj.(fields{jj})) || any(size(obj.(fields{jj})))
155 % handle some fields as attributes
156 if strcmp(fields{jj}, 'name')
157 obj_node.setAttribute('name', obj.name);
158 elseif strcmp(fields{jj}, 'description')
159 obj_node.setAttribute('description', obj.description);
160 elseif strcmp(fields{jj}, 'UUID')
161 obj_node.setAttribute('UUID', obj.UUID);
162 elseif strcmp(fields{jj}, 'created')
163 obj_node.setAttribute('created', num2str(obj.created));
164 elseif strcmp(fields{jj}, 'proctime')
165 obj_node.setAttribute('proctime', num2str(obj.proctime));
166 else
167 utils.xml.xmlwrite(obj.(fields{jj}), xml, obj_node, fields{jj});
168 end
169 end
170 end
171 end
172 end
173 else
174 %%%%% Don't skip empty fields for structures and other %%%%%
175 for ii = 1:numel(objs)
176 obj = objs(ii);
177 shape = sprintf('%dx%d', size(objs,1), size(objs,2));
178 obj_node = xml.createElement('object');
179 obj_node.setAttribute('type', class(obj));
180 obj_node.setAttribute('shape', shape);
181 parent.appendChild(obj_node);
182 fields = fieldnames(obj);
183 for jj = 1:length(fields)
184 utils.xml.xmlwrite(obj.(fields{jj}), xml, obj_node, fields{jj});
185 end
186 end
187 end
188
189 %%%%%%%%%%%%%%%%%%%%%%% The object is a java object %%%%%%%%%%%%%%%%%%%%%%%
190 elseif isjava(objs)
191 if strcmp(class(objs), 'sun.util.calendar.ZoneInfo')
192 content = xml.createTextNode(char(objs.getID));
193 parent.appendChild(content);
194 else
195 error('### Unknown Java');
196 end
197
198 %%%%%%%%%%%%%%%%%%%%%%% The object is a cell object %%%%%%%%%%%%%%%%%%%%%%%
199 elseif iscell(objs)
200
201 for ii = 1:numel(objs)
202 obj = objs{ii};
203 shape = sprintf('%dx%d', size(obj,1), size(obj,2));
204 cell_node = xml.createElement('cell');
205 cell_node.setAttribute('type', class(obj));
206 cell_node.setAttribute('prop_name', property_name);
207 cell_node.setAttribute('shape', shape);
208 parent.appendChild(cell_node);
209 utils.xml.xmlwrite(obj, xml, cell_node, '');
210 end
211
212 %%%%%%%%%%%%%%%%%%%% The object is a character string %%%%%%%%%%%%%%%%%%%%%
213 elseif ischar(objs)
214
215 % We mask the line break '\n' with a new identifier because we got
216 % problems with saving into the database.
217 objs_txt = objs;
218 objs_txt = strrep(objs_txt, '\n', '<NEW_LINE>');
219
220 % Replace the first and last DOLLAR $ of an version string with CVS_TAG
221 if ~isempty(objs_txt) && (objs_txt(1) == '$') && (objs_txt(end) == '$') && (strcmp(property_name, 'version') || strcmp(property_name, 'mversion'))
222 objs_txt = strrep(objs_txt, '$', 'CVS_TAG');
223 % objs_txt = ['CVS_TAG', objs_txt(2:end-1), 'CVS_TAG'];
224 end
225
226 % Set the shape of the node again because it is possible that we
227 % replaced '\n' with '<NEW_LINE>'.
228 parent.setAttribute('shape', sprintf('%dx%d', size(objs_txt,1), size(objs_txt,2)));
229
230 objs_txt = reshape(objs_txt, 1, []);
231 content = xml.createTextNode(objs_txt);
232 parent.appendChild(content);
233
234 %%%%%%%%%%%%%%%%%%%%%%%%% The object is a logical %%%%%%%%%%%%%%%%%%%%%%%%%
235 elseif islogical(objs)
236
237 content = xml.createTextNode(mat2str(objs));
238 parent.appendChild(content);
239
240 %%%%%%%%%%%%%%%%%%%%%%%%% The object is a number %%%%%%%%%%%%%%%%%%%%%%%%%%
241 elseif isnumeric(objs) || isa(objs, 'sym')
242
243 %%%%% objs is a singel value %%%%%
244 if (size(objs,1) == 1) && (size(objs,2) == 1) || size(objs,1) == 0 || size(objs,2) == 0
245 if strcmp(class(objs), 'sym')
246 number_str = char(objs, 20);
247 else
248 if isreal(objs)
249 number_str = sprintf('%.17g', objs);
250 else
251 number_str = num2str(objs, 20);
252 end
253 end
254 content = xml.createTextNode(number_str);
255 parent.appendChild(content);
256
257 %%%%% objs is a matrix %%%%%
258 elseif (size(objs,1) > 1) && (size(objs,2) > 1)
259
260 xml_addmatrix(objs, xml, parent);
261
262 %%%%% objs is a vector %%%%%
263 elseif (size(objs,1) > 1) || (size(objs,2) > 1)
264
265 xml_addvector(objs, xml, parent);
266
267 end
268
269 else
270 error('### unknown type [%s]', class(objs));
271 end
272 end
273
274 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
275 %
276 % DESCRIPTION: XML_ADDVECTOR Add a vector element to the xml node. The element
277 % have the form:
278 %
279 % REAL DATA: <real_data type="vector">
280 % <vector type="double"> 1 2 3 4 5 6 7 8 9 10</vector>
281 % <vector type="double">11 12 13 14 15 16 17 18 19 20</vector>
282 % </real_data>
283 %
284 % COMPLEX DATA:<real_data type="vector">
285 % <vector type="double"> 1 2 3 4 5 6 7 8 9 10</vector>
286 % <vector type="double">11 12 13 14 15 16 17 18 19 20</vector>
287 % </real_data>
288 %
289 % <imag_data type="vector">
290 % <vector type="double"> 1 2 3 4 5 6 7 8 9 10</vector>
291 % <vector type="double">11 12 13 14 15 16 17 18 19 20</vector>
292 % </imag_data>
293 %
294 % The vector objs will be split into several parts dependent from
295 % the maximum size in one vector element.
296 % Each part creates its own vectror element.
297 %
298 % HISTORY: 31-01-2008 Diepholz
299 % Creation
300 %
301 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
302 function xml_addvector(objs, xml, parent)
303
304 n_min = 50000;
305 header_displayed = true;
306
307 shape = sprintf('%dx%d', size(objs,1), size(objs,2));
308
309 %%%%% Real data %%%%%
310 node_real = xml.createElement('real_data');
311 node_real.setAttribute('type', 'vector');
312 node_real.setAttribute('shape', shape);
313 %%% Set the parent attribute 'type' to vector
314 parent.setAttribute('type', 'vector');
315 parent.appendChild(node_real);
316
317 idx = 1;
318 Ndata = length(objs);
319 n = min(n_min, Ndata);
320 while idx-1 <= Ndata
321 header_displayed = TerminalOutput(parent, header_displayed, true, 'vector', idx+n-1);
322 if isa(objs, 'sym')
323 number_str = strtrim(char(objs(idx:min(Ndata,idx+n-1))));
324 else
325 number_str = strtrim(utils.helper.num2str(real(objs(idx:min(Ndata,idx+n-1)))));
326 end
327 if ~isempty(number_str)
328 item = xml.createElement('vector');
329 item.setAttribute('type', class(objs));
330 content = xml.createTextNode(number_str);
331 node_real.appendChild(item);
332 item.appendChild(content);
333 end
334 idx = idx + n;
335 end
336
337 %%%%% Imaginary data %%%%%
338 if ~isreal(objs) && ~isa(objs, 'sym')
339 header_displayed = true;
340 node_imag = xml.createElement('imag_data');
341 node_imag.setAttribute('type', 'vector')
342 node_imag.setAttribute('shape', shape);
343 parent.appendChild(node_imag);
344
345 idx = 1;
346 while idx-1 <= Ndata
347 header_displayed = TerminalOutput(parent, header_displayed, false, 'vector', idx+n-1);
348 number_str = strtrim(utils.helper.num2str(imag(objs(idx:min(Ndata,idx+n-1)))));
349 if ~isempty(number_str)
350 item = xml.createElement('vector');
351 item.setAttribute('type', class(objs));
352 content = xml.createTextNode(number_str);
353 node_imag.appendChild(item);
354 item.appendChild(content);
355 end
356 idx = idx + n;
357 end
358 end
359 end
360
361 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
362 %
363 % DESCRIPTION: XML_ADDMATRIX Add a matrix element to the xml node. The element
364 % have the form:
365 %
366 % REAL DATA: <real_data type="matrix">
367 % <matrix type="double">1 2 3</matrix>
368 % <matrix type="double">4 5 6</matrix>
369 % <matrix type="double">7 8 9</matrix>
370 % </real_data>
371 %
372 % COMPLEX DATA:<real_data type="matrix">
373 % <matrix type="double">1 2 3</matrix>
374 % <matrix type="double">4 5 6</matrix>
375 % <matrix type="double">7 8 9</matrix>
376 % </real_data>
377 %
378 % <imag_data type="matrix">
379 % <matrix type="double">9 8 7</matrix>
380 % <matrix type="double">6 5 4</matrix>
381 % <matrix type="double">3 2 1</matrix>
382 % </imag_data>
383 %
384 % Each row in objs creates a matrix element.
385 %
386 % HISTORY: 31-01-2008 Diepholz
387 % Creation
388 %
389 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
390 function xml_addmatrix(objs, xml, parent)
391
392 shape = sprintf('%dx%d', size(objs,1), size(objs,2));
393 header_displayed = true;
394
395 %%% Get the property name only for displaying the property name
396
397 %%%%% Real data %%%%%
398 node_real = xml.createElement('real_data');
399 node_real.setAttribute('type', 'matrix');
400 node_real.setAttribute('shape', shape);
401 %%% Set the parent attribute 'type' to matrix
402 parent.setAttribute('type', 'matrix');
403 parent.appendChild(node_real);
404
405 for ii = 1:size(objs,1)
406 if strcmp(class(objs), 'sym')
407 number_str = strtrim(char(objs(ii,:)));
408 else
409 number_str = strtrim(utils.helper.num2str(real(objs(ii,:))));
410 end
411 if ~isempty(number_str)
412 item = xml.createElement('matrix');
413 item.setAttribute('type', class(objs));
414 content = xml.createTextNode(number_str);
415 node_real.appendChild(item);
416 item.appendChild(content);
417 end
418 end
419
420 TerminalOutput(parent, header_displayed, true, 'matrix', ii);
421
422 %%%%% Imaginary data %%%%%
423 if ~isreal(objs) && ~isa(objs, 'sym')
424 node_imag = xml.createElement('imag_data');
425 node_imag.setAttribute('type', 'matrix');
426 node_imag.setAttribute('shape', shape);
427 parent.appendChild(node_imag);
428 for ii = 1:size(objs,1)
429 number_str = strtrim(utils.helper.num2str(imag(objs(ii,:))));
430 if ~isempty(number_str)
431 item = xml.createElement('matrix');
432 item.setAttribute('type', class(objs));
433 content = xml.createTextNode(number_str);
434 node_imag.appendChild(item);
435 item.appendChild(content);
436 end
437 end
438 TerminalOutput(parent, header_displayed, false, 'matrix', ii);
439 end
440 end
441
442 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
443 %
444 % DESCRIPTION: Displays the terminal output.
445 %
446 % HISTORY: 31-01-2008 Diepholz
447 % Creation
448 %
449 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
450 function header_displayed = TerminalOutput(parent, header_displayed, isreal_num, obj_type, number)
451
452 import utils.const.*
453
454 THRESHOLD_DISP_MATRIX = 10;
455 THRESHOLD_DISP_VECTOR = 1000;
456
457 showing = false;
458
459 if strcmp(obj_type, 'matrix')
460 if number >= THRESHOLD_DISP_MATRIX
461 showing = true;
462 end
463 add_text = 'matrix lines';
464 else
465 if number >= THRESHOLD_DISP_VECTOR
466 showing = true;
467 end
468 add_text = 'data samples';
469 end
470
471 if showing
472
473 if header_displayed
474 if parent.hasAttribute('prop_name')
475 disp_prop_name = char(parent.getAttribute('prop_name'));
476 else
477 disp_prop_name = 'Unknown Property Name';
478 end
479 utils.helper.msg(msg.PROC2, 'Writing property: %s', disp_prop_name);
480 if isreal_num
481 utils.helper.msg(msg.PROC2, 'Writing real data');
482 else
483 utils.helper.msg(msg.PROC2, 'Writing imag data');
484 end
485
486 header_displayed = false;
487 end
488
489 utils.helper.msg(msg.PROC3, 'Writing %d %s', number, add_text);
490 end
491 end
492
493 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
494 %
495 % FUNCTION: getFieldnames
496 %
497 % DESCRIPTION: Retruns the field names which should be storred in a XML file.
498 %
499 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
500 function fields = getFieldnames(obj)
501 meta = eval(['?' class(obj)]);
502 metaProp = [meta.Properties{:}];
503 props = {metaProp(:).Name};
504 propGetAccess = strcmpi({metaProp(:).GetAccess}, 'public');
505 propDependent = [metaProp(:).Dependent];
506 fields = props(propGetAccess & ~propDependent);
507 end