diff 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
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/m-toolbox/classes/+utils/@xml/xmlwrite.m	Wed Nov 23 19:22:13 2011 +0100
@@ -0,0 +1,507 @@
+% XMLWRITE Add an object to a xml DOM project.
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% DESCRIPTION:   XMLWRITE Add an object to a xml DOM project.
+%
+% EXAMPLE:       xml = com.mathworks.xml.XMLUtils.createDocument('ltpda_object');
+%                parent = xml.getDocumentElement;
+%
+%                xmlwrite(a, xml, parent, '');
+%
+%                xmlwrite('foo.xml', xml);
+%
+% FORMAT:        This function writes the object into the following xml format:
+%
+%                ----------------------   ltpda_object   ----------------------
+%
+%                <ltpda_object>
+%
+%                   --> <object> ...
+%                   --> <cell>   ...
+%
+%                </ltpda_object>
+%
+%                -------------------------   object   -------------------------
+%
+%                <object> ('type' - attribute)
+%
+%                   <property> ...
+%
+%                </object>
+%
+%                ------------------------   property   ------------------------
+%                --------------------------   cell   --------------------------
+%
+%                <property> ('type', 'prop_name' -attributes)
+%            OR  <cell>     ('type'              -attribute)
+%
+%                   --> atomic element
+%                         - empty cell
+%                         - empty double
+%                         - empty char
+%                         - char
+%                         - double
+%                         - logical
+%                         - java (necessary for timezone)
+%                   --> <cell>      ...
+%                   --> <object>    ...
+%                   --> <real_data> ...
+%                       <imag_data> ...
+%
+%                </property>
+%            OR  </cell>
+%
+%                -------   real_data   --------|--------   imag_data   --------
+%                                              |
+%                <real_data>('type'-attribute) | <imag_data> ('type' -attribute)
+%                           ('shape'-attribute)|             ('shape'-attribute)
+%                                              |
+%                   --> <matrix> ...           |    --> <matrix> ...
+%                   --> <vector> ...           |    --> <vector> ...
+%                                              |
+%                </real_data>                  | </imag_data>
+%                                              |
+%                ---------   matrix   --------------------   vector   ---------
+%                                              |
+%                <matrix> ('type' -attribute)  | <vector> ('type' -attribute)
+%                                              |
+%                   row vector (double)        |    column vector (double)
+%                                              |
+%                </matrix>                     | </vector>
+%
+% SYMBOLS:       --> Marks a choice between alternatives.
+%                ... Indicate that an element may be repeated.
+%
+% VERSION:       $Id: xmlwrite.m,v 1.7 2011/03/28 17:04:27 ingo Exp $
+%
+% HISTORY:       31-01-2008 Diepholz
+%                   Creation
+%
+% SEE ALSO:      utils.xml.xmlread
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+function varargout = xmlwrite(objs, xml, parent, property_name)
+  
+  %%%%%%   Workaround for saving as the new XML format   %%%%%%
+  ltpda_version = getappdata(0, 'ltpda_version');
+  if  (utils.helper.ver2num(ltpda_version) > utils.helper.ver2num('2.3')) || ...
+      (strcmp(strtok(ltpda_version), '2.3'))
+    %%%%%%%%%%%%%%%%%%   reading of a new XML file   %%%%%%%%%%%%%%%%%%
+    
+    % Create history root node
+    % The attachToDom methods will attach their histories to this node.
+    historyRootNode = xml.createElement('historyRoot');
+    parent.appendChild(historyRootNode);
+    
+    % Write objects
+    collectedHist = objs.attachToDom(xml, parent, []);
+    return
+  end
+  
+  %%%%%%   If the property_name is filled then create a new property node   %%%%%
+  if ~isempty(property_name)
+    shape = sprintf('%dx%d', size(objs,1), size(objs,2));
+    prop_node = xml.createElement('property');
+    prop_node.setAttribute('prop_name', property_name);
+    prop_node.setAttribute('shape', shape);
+    prop_node.setAttribute('type', class(objs));
+    parent.appendChild(prop_node);
+    parent = prop_node;
+  end
+  
+  %%%%%%%%%%%%%%%%   The object is a class object or a struct   %%%%%%%%%%%%%%%%%
+  if (isobject(objs) || isstruct(objs)) && ~isa(objs, 'sym')
+    
+    if isa(objs, 'ltpda_obj')
+      %%%%%   Skip empty fields for unser objects   %%%%%
+      for ii = 1:numel(objs)
+        obj = objs(ii);
+        shape = sprintf('%dx%d', size(objs,1), size(objs,2));
+        obj_node = xml.createElement('object');
+        obj_node.setAttribute('type', class(obj));
+        obj_node.setAttribute('shape', shape);
+        parent.appendChild(obj_node);
+        if isa(obj, 'minfo')
+          
+          % we don't write all fields
+          info = obj.getEncodedString;
+          obj_node.setAttribute('info', info);
+          
+        elseif isa(obj, 'provenance')
+          
+          % write info
+          info = obj.getEncodedString;
+          obj_node.setAttribute('info', info);
+          
+        elseif isa(obj, 'param')
+          
+          obj_node.setAttribute('key', obj.key');
+          val = obj.getDefaultVal;
+          utils.xml.xmlwrite(val, xml, obj_node, 'value');
+          
+        elseif isa(obj, 'time')
+          
+          % write utc_epoch_milli
+          obj_node.setAttribute('utc', num2str(obj.utc_epoch_milli));
+          % write timezone
+          obj_node.setAttribute('timezone', char(obj.timezone.getID));
+          % write timeformat
+          obj_node.setAttribute('timeformat', obj.timeformat);
+          
+        else
+          fields = getFieldnames(obj);
+          for jj = 1:length(fields)
+            if ~isempty(obj.(fields{jj})) || any(size(obj.(fields{jj})))
+              % handle some fields as attributes
+              if strcmp(fields{jj}, 'name')
+                obj_node.setAttribute('name', obj.name);
+              elseif strcmp(fields{jj}, 'description')
+                obj_node.setAttribute('description', obj.description);
+              elseif strcmp(fields{jj}, 'UUID')
+                obj_node.setAttribute('UUID', obj.UUID);
+              elseif strcmp(fields{jj}, 'created')
+                obj_node.setAttribute('created', num2str(obj.created));
+              elseif strcmp(fields{jj}, 'proctime')
+                obj_node.setAttribute('proctime', num2str(obj.proctime));
+              else
+                utils.xml.xmlwrite(obj.(fields{jj}), xml, obj_node, fields{jj});
+              end
+            end
+          end
+        end
+      end
+    else
+      %%%%%   Don't skip empty fields for structures and other   %%%%%
+      for ii = 1:numel(objs)
+        obj = objs(ii);
+        shape = sprintf('%dx%d', size(objs,1), size(objs,2));
+        obj_node = xml.createElement('object');
+        obj_node.setAttribute('type', class(obj));
+        obj_node.setAttribute('shape', shape);
+        parent.appendChild(obj_node);
+        fields = fieldnames(obj);
+        for jj = 1:length(fields)
+          utils.xml.xmlwrite(obj.(fields{jj}), xml, obj_node, fields{jj});
+        end
+      end
+    end
+    
+    %%%%%%%%%%%%%%%%%%%%%%%   The object is a java object   %%%%%%%%%%%%%%%%%%%%%%%
+  elseif isjava(objs)
+    if strcmp(class(objs), 'sun.util.calendar.ZoneInfo')
+      content = xml.createTextNode(char(objs.getID));
+      parent.appendChild(content);
+    else
+      error('### Unknown Java');
+    end
+    
+    %%%%%%%%%%%%%%%%%%%%%%%   The object is a cell object   %%%%%%%%%%%%%%%%%%%%%%%
+  elseif iscell(objs)
+    
+    for ii = 1:numel(objs)
+      obj = objs{ii};
+      shape = sprintf('%dx%d', size(obj,1), size(obj,2));
+      cell_node = xml.createElement('cell');
+      cell_node.setAttribute('type', class(obj));
+      cell_node.setAttribute('prop_name', property_name);
+      cell_node.setAttribute('shape', shape);
+      parent.appendChild(cell_node);
+      utils.xml.xmlwrite(obj, xml, cell_node, '');
+    end
+    
+    %%%%%%%%%%%%%%%%%%%%   The object is a character string   %%%%%%%%%%%%%%%%%%%%%
+  elseif ischar(objs)
+    
+    % We mask the line break '\n' with a new identifier because we got
+    % problems with saving into the database.
+    objs_txt = objs;
+    objs_txt = strrep(objs_txt, '\n', '<NEW_LINE>');
+    
+    % Replace the first and last DOLLAR $ of an version string with CVS_TAG
+    if ~isempty(objs_txt) && (objs_txt(1) == '$') && (objs_txt(end) == '$') && (strcmp(property_name, 'version') || strcmp(property_name, 'mversion'))
+      objs_txt = strrep(objs_txt, '$', 'CVS_TAG');
+      %       objs_txt = ['CVS_TAG', objs_txt(2:end-1), 'CVS_TAG'];
+    end
+    
+    % Set the shape of the node again because it is possible that we
+    % replaced '\n' with '<NEW_LINE>'.
+    parent.setAttribute('shape', sprintf('%dx%d', size(objs_txt,1), size(objs_txt,2)));
+    
+    objs_txt = reshape(objs_txt, 1, []);
+    content = xml.createTextNode(objs_txt);
+    parent.appendChild(content);
+    
+    %%%%%%%%%%%%%%%%%%%%%%%%%   The object is a logical   %%%%%%%%%%%%%%%%%%%%%%%%%
+  elseif islogical(objs)
+    
+    content = xml.createTextNode(mat2str(objs));
+    parent.appendChild(content);
+    
+    %%%%%%%%%%%%%%%%%%%%%%%%%   The object is a number   %%%%%%%%%%%%%%%%%%%%%%%%%%
+  elseif isnumeric(objs) || isa(objs, 'sym')
+    
+    %%%%%   objs is a singel value   %%%%%
+    if (size(objs,1) == 1) && (size(objs,2) == 1) || size(objs,1) == 0 || size(objs,2) == 0
+      if strcmp(class(objs), 'sym')
+        number_str = char(objs, 20);
+      else
+        if isreal(objs)
+          number_str = sprintf('%.17g', objs);
+        else
+          number_str = num2str(objs, 20);
+        end
+      end
+      content = xml.createTextNode(number_str);
+      parent.appendChild(content);
+      
+      %%%%%   objs is a matrix   %%%%%
+    elseif (size(objs,1) > 1) && (size(objs,2) > 1)
+      
+      xml_addmatrix(objs, xml, parent);
+      
+      %%%%%   objs is a vector   %%%%%
+    elseif (size(objs,1) > 1) || (size(objs,2) > 1)
+      
+      xml_addvector(objs, xml, parent);
+      
+    end
+    
+  else
+    error('### unknown type [%s]', class(objs));
+  end
+end
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% DESCRIPTION: XML_ADDVECTOR Add a vector element to the xml node. The element
+%              have the form:
+%
+% REAL DATA:   <real_data type="vector">
+%                 <vector type="double"> 1  2  3  4  5  6  7  8  9 10</vector>
+%                 <vector type="double">11 12 13 14 15 16 17 18 19 20</vector>
+%              </real_data>
+%
+% COMPLEX DATA:<real_data type="vector">
+%                 <vector type="double"> 1  2  3  4  5  6  7  8  9 10</vector>
+%                 <vector type="double">11 12 13 14 15 16 17 18 19 20</vector>
+%              </real_data>
+%
+%              <imag_data type="vector">
+%                 <vector type="double"> 1  2  3  4  5  6  7  8  9 10</vector>
+%                 <vector type="double">11 12 13 14 15 16 17 18 19 20</vector>
+%              </imag_data>
+%
+%              The vector objs will be split into several parts dependent from
+%              the maximum size in one vector element.
+%              Each part creates its own vectror element.
+%
+% HISTORY:     31-01-2008 Diepholz
+%                 Creation
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+function xml_addvector(objs, xml, parent)
+  
+  n_min            = 50000;
+  header_displayed = true;
+  
+  shape = sprintf('%dx%d', size(objs,1), size(objs,2));
+  
+  %%%%%   Real data   %%%%%
+  node_real = xml.createElement('real_data');
+  node_real.setAttribute('type', 'vector');
+  node_real.setAttribute('shape', shape);
+  %%% Set the parent attribute 'type' to vector
+  parent.setAttribute('type', 'vector');
+  parent.appendChild(node_real);
+  
+  idx = 1;
+  Ndata = length(objs);
+  n = min(n_min, Ndata);
+  while idx-1 <= Ndata
+    header_displayed = TerminalOutput(parent, header_displayed, true, 'vector', idx+n-1);
+    if isa(objs, 'sym')
+      number_str = strtrim(char(objs(idx:min(Ndata,idx+n-1))));
+    else
+      number_str = strtrim(utils.helper.num2str(real(objs(idx:min(Ndata,idx+n-1)))));
+    end
+    if ~isempty(number_str)
+      item = xml.createElement('vector');
+      item.setAttribute('type', class(objs));
+      content = xml.createTextNode(number_str);
+      node_real.appendChild(item);
+      item.appendChild(content);
+    end
+    idx = idx + n;
+  end
+  
+  %%%%%   Imaginary data   %%%%%
+  if ~isreal(objs) && ~isa(objs, 'sym')
+    header_displayed = true;
+    node_imag = xml.createElement('imag_data');
+    node_imag.setAttribute('type', 'vector')
+    node_imag.setAttribute('shape', shape);
+    parent.appendChild(node_imag);
+    
+    idx   = 1;
+    while idx-1 <= Ndata
+      header_displayed = TerminalOutput(parent, header_displayed, false, 'vector', idx+n-1);
+      number_str = strtrim(utils.helper.num2str(imag(objs(idx:min(Ndata,idx+n-1)))));
+      if ~isempty(number_str)
+        item = xml.createElement('vector');
+        item.setAttribute('type', class(objs));
+        content = xml.createTextNode(number_str);
+        node_imag.appendChild(item);
+        item.appendChild(content);
+      end
+      idx = idx + n;
+    end
+  end
+end
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% DESCRIPTION: XML_ADDMATRIX Add a matrix element to the xml node. The element
+%              have the form:
+%
+% REAL DATA:   <real_data type="matrix">
+%                 <matrix type="double">1 2 3</matrix>
+%                 <matrix type="double">4 5 6</matrix>
+%                 <matrix type="double">7 8 9</matrix>
+%              </real_data>
+%
+% COMPLEX DATA:<real_data type="matrix">
+%                 <matrix type="double">1 2 3</matrix>
+%                 <matrix type="double">4 5 6</matrix>
+%                 <matrix type="double">7 8 9</matrix>
+%              </real_data>
+%
+%              <imag_data type="matrix">
+%                 <matrix type="double">9 8 7</matrix>
+%                 <matrix type="double">6 5 4</matrix>
+%                 <matrix type="double">3 2 1</matrix>
+%              </imag_data>
+%
+%              Each row in objs creates a matrix element.
+%
+% HISTORY:     31-01-2008 Diepholz
+%                 Creation
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+function xml_addmatrix(objs, xml, parent)
+  
+  shape            = sprintf('%dx%d', size(objs,1), size(objs,2));
+  header_displayed = true;
+  
+  %%% Get the property name only for displaying the property name
+  
+  %%%%%   Real data   %%%%%
+  node_real = xml.createElement('real_data');
+  node_real.setAttribute('type', 'matrix');
+  node_real.setAttribute('shape', shape);
+  %%% Set the parent attribute 'type' to matrix
+  parent.setAttribute('type', 'matrix');
+  parent.appendChild(node_real);
+  
+  for ii = 1:size(objs,1)
+    if strcmp(class(objs), 'sym')
+      number_str = strtrim(char(objs(ii,:)));
+    else
+      number_str = strtrim(utils.helper.num2str(real(objs(ii,:))));
+    end
+    if ~isempty(number_str)
+      item = xml.createElement('matrix');
+      item.setAttribute('type', class(objs));
+      content = xml.createTextNode(number_str);
+      node_real.appendChild(item);
+      item.appendChild(content);
+    end
+  end
+  
+  TerminalOutput(parent, header_displayed, true, 'matrix', ii);
+  
+  %%%%%   Imaginary data   %%%%%
+  if ~isreal(objs) && ~isa(objs, 'sym')
+    node_imag = xml.createElement('imag_data');
+    node_imag.setAttribute('type', 'matrix');
+    node_imag.setAttribute('shape', shape);
+    parent.appendChild(node_imag);
+    for ii = 1:size(objs,1)
+      number_str = strtrim(utils.helper.num2str(imag(objs(ii,:))));
+      if ~isempty(number_str)
+        item = xml.createElement('matrix');
+        item.setAttribute('type', class(objs));
+        content = xml.createTextNode(number_str);
+        node_imag.appendChild(item);
+        item.appendChild(content);
+      end
+    end
+    TerminalOutput(parent, header_displayed, false, 'matrix', ii);
+  end
+end
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% DESCRIPTION: Displays the terminal output.
+%
+% HISTORY:     31-01-2008 Diepholz
+%                 Creation
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+function header_displayed = TerminalOutput(parent, header_displayed, isreal_num, obj_type, number)
+  
+  import utils.const.*
+  
+  THRESHOLD_DISP_MATRIX = 10;
+  THRESHOLD_DISP_VECTOR = 1000;
+  
+  showing = false;
+  
+  if strcmp(obj_type, 'matrix')
+    if number >= THRESHOLD_DISP_MATRIX
+      showing = true;
+    end
+    add_text = 'matrix lines';
+  else
+    if number >= THRESHOLD_DISP_VECTOR
+      showing = true;
+    end
+    add_text = 'data samples';
+  end
+  
+  if showing
+    
+    if header_displayed
+      if parent.hasAttribute('prop_name')
+        disp_prop_name = char(parent.getAttribute('prop_name'));
+      else
+        disp_prop_name = 'Unknown Property Name';
+      end
+      utils.helper.msg(msg.PROC2, 'Writing property: %s', disp_prop_name);
+      if isreal_num
+        utils.helper.msg(msg.PROC2, 'Writing real data');
+      else
+        utils.helper.msg(msg.PROC2, 'Writing imag data');
+      end
+      
+      header_displayed = false;
+    end
+    
+    utils.helper.msg(msg.PROC3, 'Writing %d %s', number, add_text);
+  end
+end
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% FUNCTION:    getFieldnames
+%
+% DESCRIPTION: Retruns the field names which should be storred in a XML file.
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+function fields = getFieldnames(obj)
+  meta = eval(['?' class(obj)]);
+  metaProp = [meta.Properties{:}];
+  props = {metaProp(:).Name};
+  propGetAccess = strcmpi({metaProp(:).GetAccess}, 'public');
+  propDependent = [metaProp(:).Dependent];
+  fields = props(propGetAccess & ~propDependent);
+end