我写的一个xml文件类,封装了 IXMLDocument(c++builder).

/*
    这是我写的一个xml文件类,封装了 IXMLDocument,用于在c++builder程序中
    建立、读写xml文件,经过一年多的修改和使用,感觉还行。

作者:lao-hong
  */
//下面是"my_xml.h"的内容:    (用到了STL)
//---------------------------------------------------------------------------
//2003-1-26

#ifndef my_xmlH
#define my_xmlH

#include <XMLDoc.hpp>

#include <map.h>
#include <vector.h>
//---------------------------------------------------------------------------
      class xmlNode; //表征xml节点的类,
                     //因为与 myXML 有交叉引用,所以在此预先定义一下。
//---------------------------------------------------------------------------
class myXML   //xml文件类.
{
   private:
      int SavePause;  //用来控制防止频繁的存盘,提高效率。
   private:
        AnsiString _fpath;        //xml文件名,包含路径。
        _di_IXMLDocument XmlDoc;     //cb中的xml文档类。
        _di_IXMLNode Root;       //根节点,只有一个。
    public:
        myXML();                 //构造函数
        myXML(AnsiString fpath);   //构造函数
        void init(AnsiString fpath);  //初始化
        bool isNull()const;      //是否有效
        void save()const;       //存盘
        xmlNode root()const;    //获得根节点
        void disable_save();  //该函数使后面的save()操作无效。
        void enable_save();   //执行save()操作。
                  //这两个函数总是成对出现,用于使两个函数之间的大量
                  //零碎的存盘操作(如果有的话)被跳过,以提高系统效率。
                  //这两个函数是我后来加的,与XML文档没有关系,
                  //如果你觉得没有必要,可以去掉。

        void save_to( AnsiString fpath_ )const;  //保存到另外的文件
};
//---------------------------------------------------------------------------
   typedef map<AnsiString,AnsiString>  attrMap; //用来表示节点的一组属性
                                                //定义这个可以少打好多字。
//---------------------------------------------------------------------------
class xmlNode         //表征xml节点的类,   
{
    private:
        _di_IXMLNode _node;
    public:
        xmlNode();
        xmlNode(_di_IXMLNode node);
        void init(_di_IXMLNode node);
        bool isNull()const;
        xmlNode & operator = ( const xmlNode & node_ ); 
    public:
        AnsiString name()const;  //返回节点的名字。
        AnsiString attribute(AnsiString name)const;
                        //返回一个属性值。name表示属性名称。

        AnsiString value()const;   //获得该节点的字符串值。

        AnsiString child_value(AnsiString name)const;
                     //返回该节点的一个子节点的值。name是子节点的节点名字。

        void set_value( AnsiString value_ )const; //设置本节点的值。

        void set_attribute(AnsiString name,AnsiString value)const;
                              //设置本节点的一个属性值。形如:name="value"

        void set_child_value(AnsiString name,AnsiString value)const;
                         //设置本节点的一个子节点的值。形如:<name>value<name/>

        xmlNode find_child_node(AnsiString name)const;
                         //返回名字是name的子节点,如果有的话。

        xmlNode get_child_node(AnsiString name)const;
                      //返回一个名字是name的子节点,如果没有,创建一个。

        void get_attrs( map<AnsiString,AnsiString> & attrs )const ;
                                          //一次获得本节点所有的属性。

        void set_attrs( const map<AnsiString,AnsiString> & attrs )const ;
               //先将旧的属性全部删除,新属性作为一个整体增加。

      void find_child_nodes(vector<xmlNode> & nodes)const;  //获得所有子节点。
      void del_child_nodes()const;     //删除所有子节点。
      void add_child_node( AnsiString child_name )const; //增加一个子节点
      void del_child_node( AnsiString child_name )const; //删除一个子节点。
};
//---------------------------------------------------------------------------
#endif

//下面是"my_xml.cpp"的内容:
//---------------------------------------------------------------------------
//2003-1-26
#pragma hdrstop

#include "my_xml.h"

//---------------------------------------------------------------------------
#pragma package(smart_init)
//--------------------------------------------------------------------------
//-----------------------------------------------------------------------
myXML::myXML():XmlDoc(NULL),Root(NULL),SavePause(0)
{
}
//-----------------------------------------------------------------------
myXML::myXML(AnsiString fpath) : XmlDoc(NULL),Root(NULL),SavePause(0)
{
   init(fpath);
}
//-----------------------------------------------------------------------
void myXML::init(AnsiString fpath)
{
    _fpath = fpath;
    if( NULL != XmlDoc )delete XmlDoc; //我对这行代码没有信心,还请高人指点。
    XmlDoc = NULL;
    if( fpath.Length() == 0 )
    {
    }
    else
    {
       if(FileExists(fpath))    //如果文件存在
       {
           try{ XmlDoc = LoadXMLDocument(fpath);}
           catch(...){ XmlDoc = NULL;}
       }
       else                  //如果文件不存在,
       {
          try{ XmlDoc = NewXMLDocument(L"1.0"); }   //创建, L""表示宽字符串。
          catch(...){ XmlDoc = NULL;}
          if( NULL == XmlDoc ){}
          else XmlDoc->FileName = fpath;
       }
    }
    if(XmlDoc == NULL){ Root = NULL; }
    else
    {
        XmlDoc->Encoding = AnsiString("UTF-16");
                             //编码方式还可以选择:
                             //"gb2312" 与一般中文文本兼容
                             //"utf-8"  适于全部是英文的情况。
                             //"big5"   台湾繁体中文

        Root = XmlDoc->DocumentElement;
        if( Root == NULL )
        {
            XmlDoc->AddChild("root");  //根节点,必须有一个。一般用"root"
            Root = XmlDoc->DocumentElement;
        }
    }
    SavePause = 0;
}
//---------------------------------------------------------------------
bool myXML :: isNull()const{  return (Root == NULL); }
//---------------------------------------------------------------------
void myXML :: save()const     //存盘
{
    if( Root == NULL )return;
    if( SavePause > 0 )return;
    if( _fpath.Length() == 0 )return;
    if( XmlDoc->Modified )   
    {
      try{ XmlDoc->SaveToFile( _fpath ); }catch(...){}
    }
}
//---------------------------------------------------------------------
xmlNode myXML :: root()const{   return xmlNode(Root);}
//---------------------------------------------------------------------
void myXML :: disable_save(){  ++SavePause; }
//---------------------------------------------------------------------
void myXML :: enable_save(){  --SavePause; save(); }
//---------------------------------------------------------------------
void myXML::save_to( AnsiString fpath_ )const  //保存到...
{
   if( Root == NULL )return;
   try{ XmlDoc->SaveToFile( fpath_ ); }catch(...){}
}
//---------------------------------------------------------------------
//===========================================================================


//---------------------------------------------------------------------
//本函数用于替换掉字符串中含有的非法字符,防止其写入xml文件中。
//这里简单的用空格替换,不一定合适。有待大家指正。

static AnsiString & Valid(AnsiString & str)
{
   const int Len = str.Length();
   for(int i=1;i<=Len;++i)
   {
      char & c = str[i];   if(c > 0x00 && c < 0x20)c = ' ';
   }
   return str;
}

//-----------------------------------------------------------------------
xmlNode :: xmlNode(){ _node = NULL; }
//-----------------------------------------------------------------------
xmlNode :: xmlNode(_di_IXMLNode node){    _node = node;}
//-----------------------------------------------------------------------
void xmlNode :: init(_di_IXMLNode node){    _node = node;}
//-----------------------------------------------------------------------
bool xmlNode :: isNull()const{  return (_node == NULL); }
//-----------------------------------------------------------------------
xmlNode & xmlNode::operator = ( const xmlNode & node_ )
{
   _node = node_._node;    return *this;
}
//-----------------------------------------------------------------------
//返回一个名字是name的子节点,如果没有,创建一个。
xmlNode xmlNode :: get_child_node(AnsiString name)const
{
    if(_node == NULL)return xmlNode(NULL);
    _di_IXMLNode node = _node->ChildNodes->FindNode(name);
    if(node == NULL)
    {
        return xmlNode(_node->AddChild(name));
    }
    else return xmlNode(node);
}
//-----------------------------------------------------------------------
//返回名字是name的子节点。
xmlNode xmlNode :: find_child_node(AnsiString name)const
{
    if(_node == NULL)return xmlNode(NULL);
    return xmlNode(_node->ChildNodes->FindNode(name));
}
//-----------------------------------------------------------------------
AnsiString xmlNode :: name()const
{
   if(_node == NULL)return AnsiString();
   return _node->NodeName;
}
//-----------------------------------------------------------------------
AnsiString xmlNode :: value()const  //获得该节点的字符串值。
{
    if(_node == NULL)return AnsiString();
    AnsiString S;
    try
    {
        OleVariant v = _node->Text;
        if(v.IsNull())S = AnsiString();
        else S = AnsiString(v);
    }
    catch(...){ S = AnsiString();}
    return S;
}
//-----------------------------------------------------------------------
AnsiString xmlNode :: child_value(AnsiString name)const //返回子节点的值。
{
    if(_node == NULL)return AnsiString();
    AnsiString S;
    try
    {
        OleVariant v = _node->ChildValues[name];
        if(v.IsNull())S = AnsiString();
        else S = AnsiString(v);
    }
    catch(...){ S = AnsiString();}
    return S;
}
//-----------------------------------------------------------------------
void xmlNode::set_value( AnsiString value_ )const 
{
    if(_node == NULL)return;    Valid( value_ );
    try{ _node->Text = value_; }catch(...){}
}
//-----------------------------------------------------------------------
void xmlNode :: set_child_value(AnsiString name,AnsiString value)const
{
    if(_node == NULL)return ;
    Valid(value);
    const _di_IXMLNode node = _node->ChildNodes->FindNode(name);
    if(node == NULL)
    {
        if(value.Length() == 0);
        else
        {
            try{ _node->AddChild(name)->Text = value;}catch(...){}
        }
    }
    else
    {
        if(value.Length() == 0)
        {
            try{ _node->ChildNodes->Remove(node);}catch(...){}
        }
        else
        {
            try{ _node->ChildValues[name] = value;}catch(...){}
        }
    }
}
//-----------------------------------------------------------------------
AnsiString xmlNode :: attribute(AnsiString name)const
{
    if(_node == NULL)return AnsiString();
    AnsiString S;
    try{
        OleVariant v = _node->Attributes[name];
        if(v.IsNull())S = AnsiString();
        else S = AnsiString(v);
    }
    catch(...){ S = AnsiString();}
    return S;
}
//-----------------------------------------------------------------------
void xmlNode :: set_attribute(AnsiString name,AnsiString value)const
{
    if(_node == NULL)return ;
    Valid(value);
    if(value.Length() == 0)
    {
        try{ _node->Attributes[name] = Null();}catch(...){}
    }
    else
    {
        try{ _node->Attributes[name] = value;}catch(...){}
    }
}
//-----------------------------------------------------------------------
void xmlNode :: find_child_nodes(vector<xmlNode> & nodes)const 
{
    if(_node == NULL)return ;
    _di_IXMLNodeList List = _node->ChildNodes;
    for(int i=0;i<List->Count;i++)
    {
      if( List->Nodes[i]->NodeType == ntElement )
      {
         nodes.push_back(List->Nodes[i]);
      }
    }
}
//-----------------------------------------------------------------------
//一次获得本节点所有的属性。
void xmlNode :: get_attrs(map<AnsiString,AnsiString> & attrs)const
{
   if(_node == NULL)return ;
   _di_IXMLNodeList List = _node->AttributeNodes ;
   for(int i=0;i<List->Count;i++)
   {
      AnsiString attr_name = List->Nodes[i]->NodeName;
      AnsiString attr_value;
      try{ attr_value = List->Nodes[i]->NodeValue; }
      catch(...){ attr_value = AnsiString(); }
      attrs.insert(make_pair(attr_name,attr_value));
   }
}
//-----------------------------------------------------------------------
//先将旧的属性全部删除,新属性作为一个整体增加。
void xmlNode :: set_attrs(const map<AnsiString,AnsiString> & attrs)const
{
   if(_node == NULL)return ;
   _node->AttributeNodes->Clear();
   map<AnsiString,AnsiString>::const_iterator p;
   for( p = attrs.begin(); p != attrs.end(); ++p )
   {
      set_attribute(p->first,p->second);
   }
}
//-----------------------------------------------------------------------
void xmlNode :: add_child_node(AnsiString child_name)const
{
   if(_node == NULL)return ;
   _node->AddChild(child_name);
}
//-----------------------------------------------------------------------
void xmlNode :: del_child_nodes()const
{
   if(_node == NULL)return ;
   if(_node->HasChildNodes)
   {
      _node->ChildNodes->Clear();
   }
}
//-----------------------------------------------------------------------
void xmlNode :: del_child_node(AnsiString child_name)const
{
   if(_node == NULL)return ;
   if(_node->HasChildNodes)
   {
      _node->ChildNodes->Delete( child_name );
   }
}
//-----------------------------------------------------------------------
//因为代码不是一次写成的,所以有点乱。
//---------------------------------------------------------------------
//=========================== END =========================================

//应用举例:下面的函数生成一个这样的XML文件。

<?xml version="1.0" encoding="UTF-16"?>
<root>
  <成绩单 语文="98" 数学="108" 英语="88"/>
  <体重>67</体重>
  <身长>180</身长>
</root>

//------------------------------------------

void func()
{
   myXML xml;
   xml.init("d://1.xml");
   xmlNode root = xml.root();
   xmlNode node = root.get_child_node("成绩单");
   node.set_attribute("语文","98");
   node.set_attribute("数学","108");
   node.set_attribute("英语","88");
   node = root.get_child_node("体重");
   node.set_value("67");
   root.set_child_value("身长","180");
   xml.save();
}
//---------------------------------------------------------------------
//---------------------------------------------------------------------
注意事项:
1,Build 以前,必须在程序中的某个Form上放一个 XMLDocument 控件(在Internet页),
然后完全编译(Project->Options->Linker->Use Dynamic RTL,Project->Options->
Packages->Build with runtime packages,两个对勾去掉),编译完成后,删掉这个
 XMLDocument 控件即可。
2,由于此处myXML的初始化依赖于程序底层的XML解析器,而解析器的初始化是在程序启动后
完成的(在WinMain函数启动后),所以 myXML(AnsiString)构造函数和myXML.init()函数
不能在 WinMain()前被调用。啰嗦这些只有一个意思,就是:
你不能这样定义一个全局的xml变量:
     myXML xml("d://test//tt.xml");  //这种情况下xml不能正确初始化。

//---------------------------------------------------------------------
//---------------------------------------------------------------------

 

阅读更多
下一篇软件开发的三个阶段。
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

关闭
关闭
关闭