随笔 - 181  文章 - 15  trackbacks - 0
<2009年4月>
2930311234
567891011
12131415161718
19202122232425
262728293012
3456789

常用链接

留言簿(1)

随笔分类

随笔档案

My Tech blog

搜索

  •  

最新评论

阅读排行榜

评论排行榜

         目录
        com方式调用matlab(一)
        com方式调用matlab(二) 
        com方式调用matlab(三)
        com方式调用matlab(四) 
        com方式调用matlab(五)
        com方式调用matlab(六)
        com方式调用matlab(附:运行结果及代码)
        相信看了上一部分的介绍,已经有人不需要往下继续看了.因为技术方面就是如此.况且代码写得也不是很严谨.当然,前面也说过,这里只是为大家提供一种思路,给没有用过这种方式的人提供一种参考意见,给很少用到过组件的人提供一点组件方面的知识,当然,有些东西也许不是合理合法的,具体的一些,您可以去看一下MSDN.
         好了,闲话就说到这里,上一部分的代码所涉及的一些知识,在以后会介绍到.本部分先说一说前面提到的几个工具类.

        首先组件的相关信息是放在xml配置文件里面的.要想使用这个配置文件,就不得不用到xml的parser,当然我们在windows底下写程序,微软已经提供了一个封装好的强有力的工具——XmlDom。其中提供了很多有用的类和接口。用这些东西操作xml是非常简单的。不过对于目前我们调用matlab组件的程序来讲,并不一定都能够用到。另外,我还希望能够在我的配置文件里面进行遍历的操作。所以我自行把感兴趣的一些操作按照自己的调用方式封装了一下。下面是关于这个类的定义情况:

class  CMyXml  
{
    
// 本函数可以访问任意CMyXml类对象的私有变量
    friend CMyXml::AppendChild(CMyXml xml);
public :
    BOOL AppendChild(CMyXml xml);
// 将xml指定节点附加为子节点
    _bstr_t GetDocXml(); // 获取xml文档内容
    BOOL GetChildNodes(); // 获取当前节点所有子节点
    BOOL DeleteNode(); // 删除当前节点
    BOOL CreateNewNode(LPTSTR NodeName); // 从当前节点创建子节点
    BOOL AddAttrbuteDefinition(LPTSTR AttrbuteName); // 为当前节点增加属性
    BOOL DeleteAttrbuteDefinition(LPTSTR AttrbuteName); // 为当前节点删除属性
    _bstr_t GetAttrbuteValue(LPTSTR AttrbuteName); // 获取节点值
    BOOL SetAttrbuteValue(LPTSTR AttrbuteName,LPTSTR AttrbuteValue); // 设置节点值
    _bstr_t GetCurrentNodeValue(); // 获取当前节点的值
    BOOL SetCurrentNodeValue(LPTSTR NodeValue); // 设置当前节点的值
    BOOL MoveToParent(); // 移动当前节点到父节点
    BOOL MoveCurrentTo( long  nIndex); // 移动当前节点到节点列中指定位置
    BOOL LoadXmlFromFile(LPTSTR XmlFileName); // 从文件读入xml
    BOOL LoadXmlFromString(LPTSTR XmlDocSTR); // 从字符串读入xml
    BOOL GetMatchedSubElementList(LPTSTR ElementName); // 从当前指向元素的子元素当中获取和所给名字匹配的元素列
    BOOL GetMatchedParentElementList(LPTSTR ElementName); // 从当前节点的父节点的所有子节点中获取和所给名字所匹配的元素列
    BOOL GetMatchedRootElementList(LPTSTR ElementName); // 从根节点中获取匹配的节点列
    CString GetCurrentNodeName(); // 获取当前节点的名称
     long  GetCurrentIndex(); // 获取当前节点的位置
     long  GetCurrentListLength(); // 获取当前节点列元素个数
    BOOL Save(); // 保存xml
    BOOL SaveAs(LPTSTR Filename); // 另存为
    CMyXml();
    
virtual   ~ CMyXml();
    
private :
    
// 私有方法
    BOOL AssertDocument(); // 判断当前文档是否有效
    BOOL AssertNode(); // 判断当前文档是否有效
private :
    CString m_sXmlFile;
// xml文件路径
    IXMLDOMDocumentPtr m_xmlDocument; // xml文本
    IXMLDOMNodePtr m_xmlCurrentNode;
    IXMLDOMNamedNodeMapPtr m_xmlAttrbuteMaps;
// 节点属性列表
    IXMLDOMNodeListPtr m_xmlMatchedList;
    
long  m_Index; // 当前节点位置
    CString m_sCurrentNodeName; // 当前节点的名称



}
;
这个类的主要思路就是遍历xml文档。所以你想要得到任何节点的值、属性之类的东西的话,都要首先从根节点开始找起。也许对于大多数的xml配置文件来说,这样操作比较不变。但是对于本程序来讲,要从大量的相同结构的子节点中找到需要的信息,也只能如此。另外,这样做的可编程性比较强,你可以把这些操作放到任何的循环、判断、递归中,以方便对于一系列信息的提取。
        下面从这个类中挑选一些方法进行进一步的说明。
        首先是构造函数:
        
CMyXml::CMyXml()//构造函数
{
    
//初始化组件
    HRESULT hr;
    hr
=CoInitialize(NULL);//初始化组件
    if(FAILED(hr))
    {
        
throw new CMyErrors("创建COM组件时调用CoInitialize失败");
    }
    
else
    {
        hr
=m_xmlDocument.CreateInstance(_T("Msxml.DOMDocument"));
        
if(FAILED(hr))//判断创建DOM对象失败
        {
            
throw new CMyErrors("创建XmlDocument失败");
        }
    }
    
}
        CMyErrors是一个从CException继承的类,用这个类可以自定义异常信息。
        而我们的Dom对象就使用“m_xmlDocument.CreateInstance(_T("Msxml.DOMDocument"))”这句话来进行创建。当然,别忘了,在创建之前还要使用“CoInitialize(NULL)”进行初始化。关于细节方面的东西,还是go to MSDN吧。
         然后我们需要把xml内容从文件读入内存。在这里是这样操作的:
BOOL CMyXml::LoadXmlFromFile(LPTSTR XmlFileName)//从xml文件读取信息
{
    
//从文件读入xml
    
//打开并读入xml文件
    _variant_t vt_Xmlpath(_T(XmlFileName));//xml文件的路径
    _variant_t vt_res(bool(TRUE));//读取情况的反应
    vt_res=m_xmlDocument->load(vt_Xmlpath);//将xml文件中的信息读取到DOM对象
    if(!bool(vt_res))
    {
        
throw new CMyErrors("打开xml文件失败");
        
return FALSE;
    }
    m_sXmlFile
=XmlFileName;
    
//当前节点列为根节点列
    m_xmlMatchedList=m_xmlDocument->childNodes;
    
//当前节点为根的第一个节点
    return this->MoveCurrentTo(0);
}
         这也很简单,除了使用封装好的union型VARIANT的_variant_t转换一下LPTSTR类型的传入参数(文件名)之外,就是使用IXMLDOMDocumentPtr->load这个方法装载xml文件到内存。具体内容在执行这步操作之后就被放到m_xmlDocument的成员中了。然后我们用IXMLDOMNodeListPtr 的实例m_xmlMatchedList读入m_xmlDocument中的根节点,使用CMyXml的方法MoveCurrentTo(0)来让当前节点指向m_xmlMatchedList这个节点列表中的第一个节点。
         下面说一下MoveCurrentTo这个方法。
        
BOOL CMyXml::MoveCurrentTo(long nIndex)//移动当前结点
{
    
//判断有效性
    if(!AssertDocument())
        
return FALSE;
    
//if(!AssertNode())
    
//    return FALSE;
    
//移动当前节点到节点列中指定位置
    if(nIndex>=m_xmlMatchedList->length)
    {
        
throw new CMyErrors("节点位置越界,执行函数MoveCurrentTo失败");
        
return FALSE;
    }
    m_Index
=nIndex;//判断当前结点的位置
    m_xmlMatchedList->get_item(nIndex,&m_xmlCurrentNode);
    
//获取该节点所有属性,把结点列表里面位置是nIndex的结点保存到当前结点
    m_xmlAttrbuteMaps=m_xmlCurrentNode->attributes;//保存结点属性到属性列表
    CString sName((char*)m_xmlCurrentNode->nodeName);//把当前结点的名字保存到当前结点名字
    m_sCurrentNodeName=sName;
    
return TRUE;
}

        该方法的作用就是从当前读入的节点列表中移动位置。其中参数nIndex是目标位置,这个位置是从0开始的。使用IXMLDOMNodeListPtr->get_item方法将对应位置的节点放入当前节点m_xmlCurrentNode。然后顺便再用IXMLDOMNamedNodeMapPtr的实例m_xmlAttrbuteMap通过属性attributes获取当前节点的所有属性。最后把当前节点的名字保存到m_sCurrentNodeName中。这样我们算是获取了所要移动到的目标节点的所有信息。

        假如想要从当前节点向上移动到它的父亲节点,在CMyXml中是这样实现的:

BOOL CMyXml::MoveToParent()//移动到父亲结点
{
    
//判断有效性
    if(!AssertDocument())
        
return FALSE;
    
if(!AssertNode())
        
return FALSE;
    
//移动当前节点到父节点
    IXMLDOMNodePtr XmlNode;
    XmlNode
=m_xmlCurrentNode->parentNode;
    
if(XmlNode==NULL)
    {
        
throw new CMyErrors("不能获得当前节点的父节点");
        
return FALSE;
    }
    m_xmlCurrentNode
=XmlNode;
    CString sName((
char*)m_xmlCurrentNode->nodeName);
    m_sCurrentNodeName
=sName;
    
//获取节点属性
    m_xmlAttrbuteMaps=m_xmlCurrentNode->attributes;
    
return TRUE;
}

        这和移动节点的方法没什么区别,只不过是采用了IXMLDOMNodePtr的parentNode这个属性。
        另外用以下方法获取当前节点的所有同名子节点:
BOOL CMyXml::GetMatchedSubElementList(LPTSTR ElementName)//创建匹配的元素序列
{
    
//从当前指向元素的子元素当中获取和所给名字匹配的元素列
    
//执行此操作以后,节点列表将会指向返回的节点列
    
//判断有效性
    if(!AssertDocument())
        
return FALSE;
    
if(!AssertNode())
        
return FALSE;
    m_xmlMatchedList
=m_xmlCurrentNode->selectNodes(_bstr_t(ElementName));
    
if(m_xmlMatchedList->length==0)//没取到任何根结点的子结点
    {
        
throw new CMyErrors("无法获取和当前节点匹配的节点列表,执行GetMatchedElementList()失败");
        
return FALSE;
    }
    
return TRUE;
}

       主要是使用了IXMLDOMNodePtr的selectNodes方法。
       以上是几个方法,在这里只是简单的描述一下。具体XmlDom中的方法,MSDN里面描述的非常清晰,这里不再多说。

       具体代码将会在稍后的时候给出。

posted on 2006-08-16 22:46 littlegai 阅读(1168) 评论(0)  编辑 收藏 引用 所属分类: 我的代码玩具

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理