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);