Mercurial > hg > ltpda
diff m-toolbox/classes/+utils/@xml/xmlread.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/xmlread.m Wed Nov 23 19:22:13 2011 +0100 @@ -0,0 +1,770 @@ +% XMLREAD Reads a XML object +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% DESCRIPTION: XMLREAD Reads a XML object. +% +% CALL: obj = xmlread(node); +% obj = xmlread(node ,'class'); +% obj = xmlread(node ,'ao'); +% obj = xmlread(node ,'time'); +% +% XML HIERARCHY: ---------------------- 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: xmlread.m,v 1.8 2011/03/28 17:04:27 ingo Exp $ +% +% HISTORY: 31-01-2008 Diepholz +% Creation +% +% SEE ALSO: utils.xml.xmlwrite +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function values = xmlread(rootNode, obj_name) + +% if nargin == 1 +% node_name = mchar(rootNode.getNodeName); +% +% switch node_name +% case 'ltpda_object' +% +% % Get the xml version from the document node +% % node.getOwnerDocument.item(0).hasAttribute('ltpda_version') +% if rootNode.hasAttribute('ltpda_version') +% xml_ver = strtok(mchar(rootNode.getAttribute('ltpda_version'))); +% else +% xml_ver = '1.0'; +% end +% +% tbx_ver = strtok(getappdata(0, 'ltpda_version')); +% +% % set the application data 'xml_ver' if the xml version is lower than the +% % toolbox version. +% % This application data is nedded in the function xml_read_object to +% % update the object string. +% if utils.helper.ver2num(xml_ver) < utils.helper.ver2num(tbx_ver) +% update = xml_ver; +% else +% update = ''; +% end +% +% values = xml_read_ltpda_object(rootNode, update); +% case 'object' +% values = xml_read_object(rootNode, false); +% case 'property' +% values = xml_read_property_cell(rootNode, false); +% case 'cell' +% values = xml_read_property_cell(rootNode, false); +% case 'real_data' +% values = xml_read_real_imag_data(rootNode); +% case 'imag_data' +% values = xml_read_real_imag_data(rootNode); +% case 'matrix' +% %%%%% row vector +% values = sscanf(mchar(child_node.getTextContent), '%g ', [1,inf]); +% case 'vector' +% %%%%% column vector +% values = sscanf(mchar(child_node.getTextContent), '%g '); +% otherwise +% %%%%% Search for the next valid node name. +% for ii = 1:rootNode.getLength +% item = rootNode.item(ii-1); +% if item.hasChildNodes +% values = utils.xml.xmlread(item); +% end +% end +% end + if nargin >= 1 + + values = []; + valuesShape = []; + h = history.initObjectWithSize(1,0); + + queryNode = rootNode.getElementsByTagName('ltpda_object'); + + for ii= 1:queryNode.getLength + + LTPDANode = queryNode.item(ii-1); + if LTPDANode.getNodeType == LTPDANode.ELEMENT_NODE + + if LTPDANode.hasAttribute('ltpda_version') + ltpda_version = strtok(utils.xml.mchar(LTPDANode.getAttribute('ltpda_version'))); + else + ltpda_version = '1.0'; + end + + if (utils.helper.ver2num(ltpda_version) > utils.helper.ver2num('2.3')) || ... + (strcmp(strtok(ltpda_version), '2.3')) + %%%%%%%%%%%%%%%%%% reading of a new XML file %%%%%%%%%%%%%%%%%% + + for jj = 1:LTPDANode.getLength + + objNode = LTPDANode.item(jj-1); + if objNode.getNodeType == objNode.ELEMENT_NODE + + className = utils.xml.mchar(objNode.getNodeName()); + + if strcmp(className, 'historyRoot') + + h = history(objNode, history.initObjectWithSize(1,0)); + + else + valuesShape = utils.xml.getShape(objNode); + val = feval(className, objNode, h); + if ~exist('obj_name', 'var') || strcmp(class(val), obj_name) + values = [values val]; + else + error('### Skip the read object because it is from the class [%s] and not from the class [%s].', class(val), obj_name); + end + end + + end + end + values = reshape(values, valuesShape); + + else + %%%%%%%%%%%%%%%%%% reading of a old XML file %%%%%%%%%%%%%%%%%% + + for jj = 1:LTPDANode.getLength + objNode = LTPDANode.item(jj-1); + if objNode.hasChildNodes + % Get node name + node_name = utils.xml.mchar(objNode.getNodeName); + switch node_name + case 'object' + val = xml_read_object(objNode, ltpda_version); + if isempty(valuesShape), valuesShape = getShape(objNode); end + if ~exist('obj_name', 'var') || strcmp(class(val), obj_name) + values = [values val]; + else + error('### Skip the read object because it is from the class [%s] and not from the class [%s].', class(val), obj_name); + end + otherwise + end + end + end % over all childs + + if ~isempty(valuesShape) + values = reshape(values, valuesShape); + end + end + + end % LTPDANode.ELEMENT_NODE + + end % ii= 1:queryNode.getLength + + else + error('### Invalid command of this function'); + end + + +end + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% DESCRIPTION: XML_READ_LTPDA_OBJECT Reads a ltoda_object element with the form: +% +% <ltpda_object> +% +% --> <object> ... +% --> <cell> ... +% +% </ltpda_object> +% +% SYMBOLS: --> Marks a choice between alternatives. +% ... Indicate that an element may be repeated. +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function values = xml_read_ltpda_object(node, update) + + values = []; + for ii = 1:node.getLength + child_node = node.item(ii-1); + if child_node.hasChildNodes + % Get Node name + node_name = mchar(child_node.getNodeName); + switch node_name + case 'object' + values = [values xml_read_object(child_node, update)]; + case 'cell' + values{end+1} = xml_read_property_cell(child_node, update); + otherwise + error('### The ''ltpda_object'' element can not contain a [%s] element.', node_name); + end + end + end +end + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% DESCRIPTION: XML_READ_OBJECT Reads a object element with the form: +% +% <object> ('type' - attribute) +% +% <property> ... +% +% </object> +% +% SYMBOLS: ... Indicate that an element may be repeated. +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function obj = xml_read_object(node, update) + + obj_type = mchar(node.getAttribute('type')); + obj = []; + + % Set some properties which are stored in the attributes of the 'object' node + obj = getSpecialObjectAttributes(obj, node, update); + + for ii = 1:node.getLength + child_node = node.item(ii-1); + %%% Read only the property if the node is a ELEMENT_NODE. + if child_node.getNodeType == child_node.ELEMENT_NODE + % Get node name + node_name = mchar(child_node.getNodeName); + % get property name from the attribute 'prop_name' + prop_name = mchar(child_node.getAttribute('prop_name')); + switch node_name + case 'property' + prop_value = xml_read_property_cell(child_node, update); + + try + obj.(prop_name) = prop_value; + catch + warning('\n\n### Skip the unknown property [%s] in the object [%s]\n', prop_name, class(obj)); + disp([char(10) 'Code me up to convert me into the new structure !!!' char(10) ]); + end + + otherwise + error('### The ''object'' element can not contain a [%s] element.', node_name); + end + end + end + + if isempty(update) + % Make sure that the version we want to update to is far in the future. + % In other words, we don't do an update if it's not necessary. + update = '1000000000000000'; + else + old_c = {'timeformat', 'pole', 'zero'}; + new_c = {'', 'pz', 'pz'}; + + idx = strmatch(obj_type, char(old_c), 'exact'); + if ~isempty(idx) + obj_type = new_c{idx}; + end + + % if ~isempty(obj_type) + % % Update the structure to the current ltpda_version + % update_fcn = [obj_type '.update_struct']; + % obj = feval(update_fcn, obj, update); + % end + end + + if ~isempty(obj_type) && ~strcmp(obj_type, 'struct') + obj.class = obj_type; + obj.tbxver = update; + obj = feval(obj_type, obj); + elseif isempty(obj) && strcmp(obj_type, 'struct') + obj = struct(); + end +end + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% DESCRIPTION: XML_READ_PROPERTY_CELL Reads a property element or a cell element +% with the form: +% +% <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> +% +% SYMBOLS: --> Marks a choice between alternatives. +% ... Indicate that an element may be repeated. +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function prop_value = xml_read_property_cell(node, update) + + prop_value = []; + real_value = []; + imag_value = []; + shape = []; + + %%% Is the length of the node is equal 1 or zero + %%% then is the property a atomic element + if node.getLength == 0 || node.getLength == 1 + prop_value = xml_read_atomic_element(node); + return + end + + for ii = 1:node.getLength + child_node = node.item(ii-1); + if child_node.getNodeType == child_node.ELEMENT_NODE + %%% Get the node name + node_name = mchar(child_node.getNodeName); + switch node_name + case 'cell' + if isempty(shape), shape = getShape(node); end + prop_value{end+1} = xml_read_property_cell(child_node, update); + case 'object' + if isempty(shape), shape = getShape(child_node); end + prop_value = [prop_value xml_read_object(child_node, update)]; + case 'real_data' + real_value = xml_read_real_imag_data(child_node); + case 'imag_data' + imag_value = xml_read_real_imag_data(child_node); + otherwise + error('### The ''property'' or ''cell'' element can not contain a [%s] element.', node_name); + end + + %%% Is real_value and imag_value filled then return the complex value + if ~isempty(real_value) && ~isempty(imag_value) + prop_value = complex(real_value, imag_value); + %%% Is real_value filled then return the read value + elseif ~isempty(real_value) + prop_value = real_value; + end + end + end + + %%% Reshape the prop_value if necessary + if ~isempty(shape) + prop_value = reshape(prop_value, shape); + end + +end + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% DESCRIPTION: XML_READ_REAL_IMAG_DATA Reads a real_data element or a +% imag_data element with the form: +% +% <real_data> ('type' -attribute) <imag_data> ('type' -attribute) +% ('shape'-attribute) ('shape'-attribute) +% +% --> <matrix> ... --> <matrix> ... +% --> <vector> ... --> <vector> ... +% +% </real_data> </imag_data> +% +% <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. +% +% REMARK: The matrix elements will be read as a row vector. +% The vector elements will be read as a column vector. +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function value = xml_read_real_imag_data(node) + + value = []; + header_displayed = true; + + %%% Get the shape of the matrix/vector + shape = getShape(node); + + % value = zeros(shape); + % idx = 1; + + node_name = ''; + for ii = 1:node.getLength + child_node = node.item(ii-1); + if child_node.hasChildNodes + %%% Get node name + node_name = mchar(child_node.getNodeName); + %%% Get type + node_type = mchar(child_node.getAttribute('type')); + switch node_name + case 'matrix' + %%% row vector + if strcmp(node_type, 'sym') + matrix_row = sym(mchar(child_node.getTextContent)); + else + matrix_row = sscanf(mchar(child_node.getTextContent), '%g ', [1,inf]); + end + value = [value; matrix_row]; + % value(idx,:) = matrix_row; + % idx = idx + 1; + case 'vector' + %%% column vector + if strcmp(node_type, 'sym') + vector_column = sym(mchar(child_node.getTextContent)); + else + vector_column = sscanf(mchar(child_node.getTextContent), '%g '); + end + value = [value; vector_column]; + % value(idx:idx + length(vector_column) - 1) = vector_column; + % idx = idx + length(vector_column); + header_displayed = TerminalOutput(node, header_displayed, node_name, length(value)); + otherwise + error('### The ''real_data'' or ''imag_data'' element can not contain a [%s] element.', node_name); + end + end + end + + if strcmp(node_name, 'matrix') + header_displayed = true; + TerminalOutput(node, header_displayed, node_name, size(value,1)); + end + value = reshape(value, shape); + +end + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% DESCRIPTION: xml_read_atomic_element Reads a atomic element. +% This function identify the following types: +% --> atomic element +% - empty cell +% - empty double +% - empty char +% - char +% - double +% - logical +% - java (necessary for timezone) +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function values = xml_read_atomic_element(node) + + values = ''; + + type = mchar(node.getAttribute('type')); + switch type + case {'', 'char'} + shape = getShape(node); + if (any(shape==1)) + values = mchar(node.getTextContent); + else + values = reshape(mchar(node.getTextContent), shape); + end + values = strrep(values, '<NEW_LINE>', '\n'); + values = strrep(values, 'CVS_TAG', '$'); + %%% Special case if 'values' is empty because + %%% there are more than an one empty char fields. + %%% For example: '' AND char('', '') AND char('', '', '') AND ... + if isempty(values) + if any(shape) + char_str = 'char('; + for ii = 1:max(shape) + char_str = [char_str, ''''', ']; + end + char_str = char_str(1:end-2); + cmd = strcat('values = ', char_str, ');'); + eval(cmd); + else + values = ''; + end + end + + case {'double', 'uint64', 'uint32', 'int32', 'int64'} + number = mchar(node.getTextContent); + + %%% Special case if 'values' is empty because + %%% there are more than an one empty double fields. + %%% For example: [] AND zeros(1,0) AND zeros(0,1) AND zeros(2,0) AND ... + if isempty(number) + shape = getShape(node); + values = zeros(shape); + else + values = str2double(number); + end + + % cast to other number type + if strcmp(type, 'uint64') + values = uint64(values); + elseif strcmp(type, 'uint32') + values = uint32(values); + elseif strcmp(type, 'int64') + values = int64(values); + elseif strcmp(type, 'int32') + values = int32(values); + end + + case 'sym' + number = mchar(node.getTextContent); + + %%% Special case if 'values' is empty because + %%% there are more than an one empty double fields. + %%% For example: [] AND zeros(1,0) AND zeros(0,1) AND zeros(2,0) AND ... + if isempty(number) + shape = getShape(node); + values = sym(shape); + else + values = sym(number); + end + + case 'cell' + cell_str = mchar(node.getTextContent); + + %%% Special case if 'values' is empty because + %%% there are more than an one empty cell fields. + %%% For example: {} AND cell(1,0) AND cell(0,1) AND cell(2,0) AND ... + if isempty(cell_str) + shape = getShape(node); + values = cell(shape); + else + error('### Should not happen because a not empty ''cell'' node have several child nodes.'); + end + + case 'logical' + cmd = ['logical(' mchar(node.getTextContent) ');']; + values = eval(cmd); + + case 'sun.util.calendar.ZoneInfo' + values = java.util.TimeZone.getTimeZone(mchar(node.getTextContent)); + + otherwise + + if any(strcmp(utils.helper.ltpda_non_abstract_classes, type)) + %%% Special case for reading an object with the size Nx0 or 0xN + shape = getShape(node); + cmd = sprintf('%s.initObjectWithSize', type); + values = feval(cmd, shape(1), shape(2)); + else + error('### Unknown type attribute [%s].', type'); + end + end +end + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% FUNCTION: shape = getShape(node) +% +% INPUTS: node - A DOM node with an attribute 'shape' +% +% DESCRIPTION: getShape Helper function to get the shape from the +% attribute 'shape' as a set of double. +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function shape = getShape(node) + shape = [NaN NaN]; + if node.hasAttribute('shape') + shape_str = mchar(node.getAttribute('shape')); + x_idx = strfind(shape_str, 'x'); + shape = [str2double(shape_str(1:x_idx-1)) str2double(shape_str(x_idx+1:end))]; + end +end + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% FUNCTION: obj = getSpecialObjectAttributes(obj, node) +% +% INPUTS: obj - a object structure or empty array +% node - A DOM node with the node name 'object' +% +% DESCRIPTION: +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function obj = getSpecialObjectAttributes(obj, node, update) + + if strcmp(mchar(node.getNodeName), 'object') + + if strcmp(mchar(node.getAttribute('type')), 'time') + + % Get attributes for a time object + % Check if the attribute exist (necessary for backwards compability) + if (node.hasAttribute('utc')) + obj.utc_epoch_milli = str2double(mchar(node.getAttribute('utc'))); + obj.timezone = java.util.TimeZone.getTimeZone(mchar(node.getAttribute('timezone'))); + obj.timeformat = mchar(node.getAttribute('timeformat')); + end + + elseif strcmp(mchar(node.getAttribute('type')), 'provenance') + + % Get attributes for a provenance object + % Check if the attribute exist (necessary for backwards compability) + if (node.hasAttribute('info')) + objStr = mchar(node.getAttribute('info')); + obj = provenance.setFromEncodedInfo(obj, objStr); + end + + elseif strcmp(mchar(node.getAttribute('type')), 'minfo') + + % Get attributes for a minfo object + % Check if the attribute exist (necessary for backwards compability) + if (node.hasAttribute('info')) + objStr = mchar(node.getAttribute('info')); + obj = minfo.setFromEncodedInfo(obj, objStr); + end + + elseif strcmp(mchar(node.getAttribute('type')), 'param') + + % Get attributes for a param object + % Check if the attribute exist (necessary for backwards compability) + if (node.hasAttribute('key')) + obj.key = mchar(node.getAttribute('key')); + + for ii = 1:node.getLength + childNode = node.item(ii-1); + %%% Read only the property if the node is a ELEMENT_NODE. + if childNode.getNodeType == childNode.ELEMENT_NODE + obj.val = xml_read_property_cell(childNode, update); + end + end + end + + else + % Get general attributes. + if node.hasAttribute('name') + obj.name = mchar(node.getAttribute('name')); + end + if node.hasAttribute('description') + obj.description = mchar(node.getAttribute('description')); + end + if node.hasAttribute('UUID') + obj.UUID = mchar(node.getAttribute('UUID')); + end + if node.hasAttribute('created') + obj.created = str2double(mchar(node.getAttribute('created'))); + end + if node.hasAttribute('proctime') + obj.proctime = str2double(mchar(node.getAttribute('proctime'))); + end + end + + + end +end + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% FUNCTION: header_displayed = TerminalOutput(node, header_displayed, node_name, number) +% +% DESCRIPTION: Displays the terminal output. +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function header_displayed = TerminalOutput(node, header_displayed, node_name, number) + + import utils.const.* + + THRESHOLD_DISP_MATRIX = 10; + THRESHOLD_DISP_VECTOR = 1000; + + showing = false; + + if strcmp(node_name, 'matrix') + if number >= THRESHOLD_DISP_MATRIX + showing = true; + add_text = 'matrix lines'; + end + else + if number >= THRESHOLD_DISP_VECTOR + showing = true; + add_text = 'data samples'; + end + end + + if showing == true + + parent = node.getParentNode; % The parent node have the 'property name' information + + if header_displayed == true + if parent.hasAttribute('prop_name') + disp_prop_name = mchar(parent.getAttribute('prop_name')); + else + disp_prop_name = 'Unknown Property Name'; + end + utils.helper.msg(msg.PROC2, 'Reading property: %s', disp_prop_name); + + if strcmp(mchar(node.getNodeName), 'real_data') + utils.helper.msg(msg.PROC2, 'Reading real data'); + else + utils.helper.msg(msg.PROC2, 'Reading imag data'); + end + header_displayed = false; + end + + utils.helper.msg(msg.PROC2, 'Read %d %s', number, add_text); + end +end + +function c = mchar(s) + c = cell(s); + c = c{1}; +end + + +