www.gusucode.com > mbcview 工具箱matlab源码程序 > mbcview/@cgddnode/import.m
function [DDobj, OK, msg] = import(DDobj, filename, force) %IMPORT Imports a Data Dictionary from an XML file. % % [DD, OK, msg] = IMPORT(DD) % [DD, OK, msg] = IMPORT(DD, filename) % [DD, OK, msg] = IMPORT(DD, filename, force) % % If no filename is supplied, the user is prompted for one. If parameter % force is non-zero, the process will run without user interaction, and % will fail if there are name clashes. Otherwise, the user will be % prompted for input. % % Return value DDobj is the data dictionary itself. % Return value OK is non-zero if the import completed successfully. % Return value msg a string describing the problem is the import failed. % % This method uses ./private/dd2m.xsl and MATLAB XSLT functionality to % import XML datadictionary files into Cage. % Copyright 2000-2014 The MathWorks, Inc. and Ford Global Technologies, Inc. msg = []; OK=1; % initialise return values % initialise input values if necessary if nargin<3 force=0; if nargin<2 filename=[]; end end % Keep a persistent copy of the XSL file. This speeds up later imports. persistent XSLFile; if isempty(XSLFile) XSLFile = fullfile(fileparts(mfilename('fullpath')), 'private','dd2m.xsl'); end % create the EntityResolver, and turn off the messages. entityResolver = com.mathworks.xml.EntityResolverMW; entityResolver.setResolverMessages(false); % create the ErrorHandler - this means that fatal errors in the xml parse % just throw an Exception rather than putting a message on STDOUT. errorHandler = com.mathworks.xml.ErrorHandlerMW; % If we haven't been given a filename. if isempty(filename) % Select data dictionary file using file chooser [filename, pathname] = uigetfile({'*.xml', 'MBC Data Dictionary Files (*.xml)'}, ... 'Select a Data Dictionary', mbcGetPath('cage', 'Data')); if ~ischar(filename) msg = []; % the user has cancelled. not really an error return end dictionaryURL = fullfile(pathname, filename); else dictionaryURL = filename; if ~exist(dictionaryURL,'file') OK = 0; % No message required. The user clicked "cancel" return end end % Set default namespaces entityResolver.setLocalNamespace(['file:///', xregrespath, filesep, 'namespace']); entityResolver.setWorldNamespace('http://www.mathworks.com/namespace'); % do the xslt transform try % read in the xmlfile into a DOM object % setting the '-validating' flag means the DD is checked against the % DTD dom = xmlread(dictionaryURL, entityResolver, errorHandler, '-validating'); % lets check this is a datadictionary document; doctype = dom.getDoctype.getName; if ~strcmp(doctype, 'datadictionary') OK = 0; return end % Transform the DOM representation of the XML into MATLAB code, and % store the parsed stylesheet in our persistent variable. [mcode, XSLFile] = xslt(dom, XSLFile, '-tostring'); % The XML has been converted into MATLAB code which initialises the members % of a structure called importedDD, which we must create first. importedDD = struct; eval(mcode); catch ME OK = 0; err = ME.message ; msg = sprintf('Couldn''t import %s.\n%s', filename, err); return end num_constants = length(importedDD.constant); num_vars = length(importedDD.value); entries = [ num2cell(importedDD.constant(:));... num2cell(importedDD.value(:));... num2cell(importedDD.symvalue(:)) ]; num_entries = length(entries); % if the XML file was empty we can stop now if num_entries==0 OK = 0; msg = 'No valid data was found in the file'; return end pDDobj = address(DDobj); % pointer to the current data dictionary % extract all new entry names newvarnames = cell(1, num_entries); for n = 1:num_entries newvarnames{n} = entries{n}.name; end % Set up item pointer list ready for putting items in as they are made pNewItems = mbcpointer(1, num_entries); % identify any name clashes Proj = project(DDobj); [altname, clashed] = uniquename(Proj, newvarnames); if any(clashed~=0) if force OK = 0; msg = char([{['The following names occur in both the XML file and ',... 'the project or occur twice in the XML file:']}, ... unique(newvarnames(clashed~=0))]); return elseif ~force % Clashes with existing variable Cidx = find(clashed==-1); if ~isempty(Cidx) % Find the existing pointers ready for re-use. It is quicker to do % this in one operation ahead of time. pVars = find(DDobj, newvarnames(Cidx)); pNewItems(Cidx) = [pVars{:}]; applytoall = false; choice = 'no'; for n = Cidx if ~applytoall % If we haven't got an 'apply to all' answer - ask again % This returns string yes, no or cancel [choice, applytoall] = i_overwrite_gui(newvarnames{n}, 1); end switch choice case 'yes' % Re-use existing pointers. These have already been % found case 'no' % Remove the entry from the import list entries{n} = []; otherwise OK = 0; % no message required here return end end end % Clashes with other items Cidx = find(clashed>0); if ~isempty(Cidx) applytoall = false; choice = 'ok'; for n = Cidx if ~applytoall % If we haven't got an 'apply to all' answer - ask again % This returns string ok or cancel [choice, applytoall] = i_overwrite_gui(newvarnames{n}, 2); end switch choice case 'ok' % Use new name entries{n}.name = altname{n}; case 'cancel' OK = 0; % no message required here return end end end % Clashes within the import process Cidx = find(clashed==-2); if ~isempty(Cidx) applytoall = false; choice = 'no'; for n = Cidx if ~applytoall % If we haven't got an 'apply to all' answer - ask again % This returns string yes, no or cancel [choice, applytoall] = i_overwrite_gui(newvarnames{n}, 3); end switch choice case 'yes' % Use this entry and remove earlier one previdx = find( strcmp( newvarnames{ n },newvarnames( 1:n - 1 ) ) ); if ~isempty(previdx) entries{previdx} = []; end case 'no' % Remove this entry from the import list entries{n} = []; case 'cancel' OK = 0; % no message required here return end end end end end % add constants, variables and functions to the DataDictionary for n = 1:num_entries if ~isempty(entries{n}) if (n>num_constants+num_vars) i_struct2Formula(entries{n}, pDDobj, pNewItems(n)); elseif (n>num_constants) i_struct2Variable(entries{n}, pDDobj, pNewItems(n)); else i_struct2Constant(entries{n}, pDDobj, pNewItems(n)); end end end DDobj = pDDobj.info; %--------------------------------- % converts a struct to a cgconstvalue function i_struct2Constant(cstruct, pdd, location) if isempty(cstruct) return end const = cgconstvalue; const = setname(const, cstruct.name); const = setnomvalue(const, cstruct.val); const = setdescription(const, cstruct.description); const = i_addAlias(const, cstruct.alias, pdd); if isnull( location ) pdd.add(xregpointer(const)); else const = setaddress(const,location); location.info = const; end %--------------------------------- % converts a struct to a cgvalue function i_struct2Variable(vstruct,pdd, location) if isempty(vstruct) return end var = cgvalue(vstruct.name, [vstruct.min, vstruct.max]); var.info = var.setdescription(vstruct.description); if ~isempty(vstruct.setpoint) var.info = var.setnomvalue(vstruct.setpoint); end var.info = i_addAlias(var.info, vstruct.alias, pdd); if isnull( location ) pdd.add(var); else location.info = var.info; location.info = setaddress(location.info,location); freeptr( var ) end %--------------------------------- % converts a struct to a cgsymvalue function i_struct2Formula(fstruct, pdd, location) if isempty(fstruct) return end symobj = cgsymvalue(fstruct.name); symobj = setdescription(symobj, fstruct.description); symobj = i_addAlias(symobj, fstruct.alias, pdd); symobj = setequation(symobj, fstruct.definition, pdd); symobj = setrange(symobj, [fstruct.min, fstruct.max]); if isnull( location ) pdd.add(xregpointer(symobj)); else location.info = symobj; location.info = setaddress(location.info,location); end %---------------------------------------- function item = i_addAlias(item, alias, pdd) for n = 1:length(alias) % Remove any leading and trailing spaces from alias string str = strtrim(alias{n}); % Only add if it does not exist already existing_ptr = pdd.find(str); if isempty(existing_ptr) item = addalias(item, str); end end % ------------------------------------------------- function [choice, applytoall] = i_overwrite_gui(name, dlgopt) if nargin<2 dlgopt = 1; end switch dlgopt case 1 question = sprintf(['An entry named "%s" already exists in the Variable Dictionary.', ... ' Do you want to replace it?'], name); opts = {'Yes', 'No', 'Cancel'}; defopt = 2; case 2 question = sprintf(['An item named "%s" already exists in the project.', ... ' The new variable will be renamed.'], name); opts = {'OK', 'Cancel'}; defopt = 1; case 3 question = sprintf(['There is a duplicate entry named "%s" in the imported ', ... 'Variable Dictionary.', ... ' Do you want to replace the earlier occurrence with this later one?'], name); opts = {'Yes', 'No', 'Cancel'}; defopt = 2; end d = xregdialog(... 'name', 'Import Variable Dictionary',... 'tag', 'cancel',... 'resize', 'off',... 'Position', [10 10 350 100]); xregcenterfigure( d ); text = uicontrol(... 'Parent', d,... 'Style', 'text',... 'String', question,... 'HorizontalAlignment', 'left'); applytoall = uicontrol(... 'Parent', d,... 'Style', 'checkbox',... 'String', 'Apply to all'); but = cell(1,length(opts)); for n = 1:length(opts) but{n} = i_makeButton( d, opts{n} ); end main = xreggridbaglayout(d, ... 'packstatus', 'off', ... 'dimension', [2, length(but)+2], ... 'rowsizes', [-1 25], ... 'colsizes', [100 -1 repmat(65, 1, length(but))], ... 'gap', 7, ... 'border', [7 7 7 15], ... 'mergeblock', {[1 1], [1 length(but)+2]}, ... 'elements', [[{text} repmat({[]}, 1, length(but)+1)]; ... [{applytoall, []}, but]]); set(d, 'LayoutManager', main); set(main, 'packstatus', 'on'); d.showDialog(but{defopt}); applytoall = logical( get( applytoall, 'Value' ) ); choice = get( d, 'Tag' ); delete(d); % --------------------------------- function i_close(src, ~) fig = get( src, 'Parent' ); tag = get( src, 'Tag' ); set( fig, 'Visible', 'off', 'Tag', tag ); % --------------------------------- function b = i_makeButton( parent, str ) b = uicontrol(... 'Parent', parent,... 'Style', 'pushbutton',... 'Tag', lower(str),... 'Callback', @i_close,... 'String', str);