65.9K
CodeProject 正在变化。 阅读更多。
Home

XML:在 C++ 应用程序中包含灵活的解析器

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.84/5 (132投票s)

2007年5月9日

CPOL

16分钟阅读

viewsIcon

1262710

downloadIcon

9324

免费、可移植、与编译器无关的 C++ XML 库

 

包含

  • XML 类源文件(XML.CPPXML.HMIME.H
  • 文档(XML.CHM
  • 测试项目 XMLTEST(cpp/sln/vcproj
  • 以下已编译的应用程序:Win32 的 TXML.EXE,Windows Mobile 5+ 设备的 XMLPPC.EXE
  • XDB.CPP,演示了 XML 库在创建配置对话框中的用法。
  • XML.JAVA,库在 Java 中的实验性实现。 

引言

您是否厌倦了市面上众多的非可移植 XML 解决方案?试试我的库吧。它可以在任何操作系统和任何编译器中运行。无 MFC、无 COM、无全局变量,纯粹的 C++!

特点

  • 可移植,基本功能可在任何环境中运行 - 我已在 Microsoft Visual C++ 2005、Borland、GCC、Codewarrior、Pocket PC 2003+ 中进行过测试,并支持 Windows、Linux、Windows Mobile 和 Symbian 操作系统
  • 基于类的操作或 INI 风格的包装器
  • UTF-8 和(Win32)UTF-16 读/写支持
  • 从文件、内存或(Win32)URL 导入
  • (Win32)读取/保存加密的 XML 文件;自定义加密
  • 导出到文件、内存或(Win32)注册表项
  • 数据库查询(Win32)
  • 允许 XML 内存压缩
  • 完整性测试
  • 允许“即时”创建变量和返回值
  • 元素/变量/注释/内容创建、删除、排序、移动、比较
  • 允许以文本形式在 Windows 剪贴板之间复制/粘贴 XML 元素
  • 能够通过 ADO(Win32)导入数据库
  • JSON 转换器
  • 支持 &vars
  • 在变量中保存/加载二进制数据(需要 mime.h
  • 支持 CDATA
  • 支持元素卸载和重新加载
  • XML 元素更新
  • 支持临时变量
  • 支持二进制输入/输出
  • HTML 帮助
  • Java 实现
  • 支持每个元素的加密/解密(在 Windows 下),支持对称密钥和非对称(证书)。
  • 支持每个元素的签名/验证(在 Windows 下)使用证书。
  • x64 兼容性
  • 实验性 JSON 支持。 
  • 2 个版本:带 STL / 不带 STL。

许可证

对于任何类型的免费、共享软件、商业软件或任何其他类型的项目,本库均免费使用,只要您

  • 在您的应用程序文档和/或关于框中注明我的署名
  • 在我的论坛(http://www.turboirc.com/forum)注册,以便您收到有关该库的更新和新闻
  • 通过论坛给我发送一条消息,告知您的应用程序名称(如果它将被发布),以便我可以链接到您。

无 STL 版本

STL 和异常处理在任何 C++ 实现中都还不可用 - 例如,Symbian OS SDK 中不存在 STL。因此,我决定使用我自己的 Z<> 类(在 xml.cpp 中定义)来操作缓冲区。

无 STL 版本,带 STL 扩展 

如果您使用非 STL 版本但仍启用 STL,可以在包含 xml.h 之前定义  XML_USE_STL_EXTENSIONS。这允许 XMLVariable 和 XMLContent 返回 std::string 作为其值(因此您无需先查询大小),并具有 GetValueS() 成员。

STL 版本

对于新代码,您可以在包含 xml.h 之前定义 XML_USE_STL 来使用 STL。这将生成更快、更安全的代码,但请注意,它与非 STL 版本不完全兼容,因此如果您将代码从非 STL 版本移植到 STL 版本,则需要进行一些更改。
STL 版本使用 std::vectorstd::string 和标准算法。

使用类操作 XML

共有 7 个类

  • XML 管理 XML 文件:打开、保存、导出等。
  • XMLHeader 管理 XML 头(XML 头可以包含注释)
  • XMLComment 管理 XML 注释
  • XMLContent 管理 XML 内容
  • XMLElement 管理 XML 元素
  • XMLVariable 管理 XML 变量
  • XMLCData 管理 XML 自定义数据

我将不详细描述这些类的所有成员函数,因为我的帮助文件中已经有了描述。在这里,我将演示它们的基本用法。请注意,该库不使用异常处理或 STL,因为这两者并非在所有 C++ 实现中都存在(例如 Symbian)。

下面的代码加载一个 XML 文件,然后检查完整性并压缩内存。test.xml 是我使用的示例文件。请注意,元素/变量名称区分大小写。

XML* a = new XML("f.xml");        // load from file

XML* a = new XML("<blah f="\">",1);    // load from memory from ASCIIZ string

XML* a = new XML("http://www.some.com/files.xml",2);    // load from URL(Win32)

ASSERT(a->IntegrityCheck() == true && a->ParseStatus() == 0);
a->CompressMemory();    
//Get 3rd element's name, and its variable "v" value.
//Also set new variable "tz" with normal and with 'on the fly' mode
char y[100] = {0};

a->GetRootElement()->GetChildren()[0]->GetElementName(y);
// now y == "Cfg"
a->GetRootElement()->GetChildren()[0]->FindVariableZ("v")->GetValue(y);
// now y == "Cfg"
// Create "tz" in the 'normal' mode
XMLElement* e = a->GetRootElement()->GetChildren()[0];
XMLVariable* v = new XMLVariable("tz","some value");
e->AddVariable(v);
// now do not delete v, it is owned by e
// Create "tz" on the fly
a->GetRootElement()->GetChildren()[0]->FindVariableZ(    "tz",true)->
    SetValue("some value");
// FindVariableZ(x,true) creates the var if doesn't exist!
// Create Comments and Contents in the same way.
// Use 0 instead of y to get the # of bytes required </blah>
// <blah f="\">for the returned string.
// Let's save/export:
if (a->IntegrityTest()) 
{ 
a->Save(); // Saves back to file 
a->Save("new.xml"); 
a->Export(fp,1,0,0);    // Save to a fp. You can also export to memory
// or save only one element by calling XMLElement :: Export. 
delete a;
// bye bye; </blah>
// <blah f="\">Note that the destructor doesn't save the file by default,
//unless you call XML :: SaveOnClose(). }</blah> 

使用 INI 风格的包装器操作 XML 文件

现在您可以使用一些 INI 风格的函数,而不是 WritePrivateProfileString

  • XMLSetString
  • XMLGetString
  • XMLSetInt
  • XMLGetInt
  • XMLSetBinaryData
  • XMLGetBinaryData
  • XMLSetFloat
  • XMLGetFloat

这些函数可以独立工作,也可以与已打开的 XML 对象一起工作。当将有效的 XML 对象传递给它们时,它们会修改该对象。当将文件名传递给它们时,它们会创建一个 XML 对象,加载文件,读/写该文件,然后将其保存回原样,这与 INI 文件函数非常相似。

由于这些函数接受它们的元素作为带有 \string(例如,Cfg\\Amplify),因此您只能操作具有唯一元素名称的 XML 文件。否则,将导致文件损坏。

现在让我们尝试获取/设置我们 XML 文件中的一些数据。

char y[1000] = {0};
XMLGetString("Cfg","v","",y,1000,"test.xml");    
    // This gets 'Bowlingy' to y.
XMLGetString("Cfg\\Amplify","V","not_found",y,1000,"test.xml");
        // This gets 'not_found' to y. Variables/Elements are case sensitive!
XMLSetString("A\\B\\C","v","hahaha","test.xml");    
    // Elements A B C are created!
Fread(y,1,100,some_file);
XMLSetBinaryData("A\\B\\C","v",y,100,"test.xml");    
    // Binary data can be saved/read, encoded with Base64 (mime.h)

请注意,所有这些 string 函数都需要 UTF-8 string。如果您在 Windows 下,您也可以使用 wchar_t 值调用 XMLSetString,库会通过使用 WideCharToMultiByte 自动将其转换为 UTF-8。

卸载和重新加载

使用 XMLElement::UnloadElementReloadElement 将元素临时保存到内存文件中(详情请参阅帮助文件)。这使您能够在不浪费 RAM 的情况下操作大型 XML 文件。

即将实现 XML::PartialLoad()

项目借用

使用 XMLElement::BorrowItem 从另一个 XMLElement* 添加一个 XMLElement* 镜像。这是一个高级功能,必须谨慎使用,否则您的应用程序将因严重的堆栈溢出而崩溃。请阅读帮助文件了解详情。

临时变量

临时元素是一个 XMLElement (或 XMLVariable),其“temporal”标志已设置。您可以通过调用 SetTemporalGetTemporal 成员函数来设置或查询此标志。默认情况下,元素和变量不是临时的。

您也可以通过构造函数标志创建临时元素或变量。此外,XMLElement::FindElementZ()XMLElement::FindVariableZ(可以即时创建元素/变量)也可以将其标记为临时。

当您调用 XMLElement::RemoveTemporalElements(bool Deep) 时,所有临时子元素都会被删除。如果 Deeptrue,则其所有子元素的临时元素也会被删除。如果一个元素是临时的并且被删除,那么它的所有子元素自然也会被删除,即使它们没有被标记为临时。因此,例如将根元素标记为临时,在调用 RemoveTemporalElements() 时将导致整个 XML 文件被销毁。

当您调用 XMLElement::RemoveTemporalVariables(bool Deep) 时,该元素的所有临时变量都会被删除。如果 Deep 设置为 true,则其所有子元素的临时变量也会被删除。

当您调用 XML::RemoveTemporalElements() 时,它会对根元素调用 XMLElement::RemoveTemporalElements(true)XMLElement::RemoveTemporalVariables(true)

请注意,除非您使用上述函数手动删除临时元素,否则它们不会被删除 - 它们被视为普通元素/变量,并正常保存或导出。

使用 Unicode 字符串与库

该库使用 UTF-8,这意味着传递和返回的 stringchar*。为了将 Unicode string 传递给该库,您必须手动将其转换为 WideCharToMultiByte(CP_UTF8,...);。我创建了一个非常简单的包装器,可以将其作为类来完成。

class W{public:W(const wchar_t* x){int y = wcslen(x);int wy = y*2 + 100;
we = new char[wy];memset(we,0,wy);WideCharToMultiByte(CP_UTF8,0,x,-1,we,wy,0,0);
}~W(){delete[] we;}operator char* (){return we;}};

因此,如果您有一个 Unicode string x 并想在我的库中使用它,您将使用 W(x),它将您的 Unicode string 转换为 UTF-8 string,通过运算符使用它,并在析构函数中释放它。

64 位兼容性

该库支持 64 位兼容性;您将能够在任何 64 位编译器下毫无问题地编译和使用它。

元素更新

有时您需要用另一个元素的元素和变量来更新一个 XMLElement

int UpdateElement(XMLElement* NewEl,bool UpdateVariableValues = false);

这将

  • 尝试 NewEl 的所有变量。如果其中任何一个在您的当前元素中也存在,那么如果 UpdateVariableValues == true,该函数将更新变量。如果 NewEl 的变量在您的元素中不存在,则将其复制。
  • 尝试 NewEl 的所有元素。如果当前元素中不存在 NewEl 的任何元素,则将其复制。如果存在,则该函数调用 UpdateElement 对该元素与其子元素 NewEl 进行操作,从而递归更新所有孙子元素和变量。

通过 ADO 导入数据库

使用 XML::ImportDB() 导入数据库。您需要处理两个结构。

struct IMPORTDBTABLEDATA   {   char name[256];   char itemname[100];   
int nVariables;   char** Variables;   char** ReplaceVariables;   };
struct IMPORTDBPARAMS   {   char* dbname;   char* provstr;   
int nTables;   IMPORTDBTABLEDATA* Tables;   };

您需要填写 IMPORTTDBPARAMS,其中包含名称(可选)、提供程序 string (有关详细信息,请参阅 ADO 文档)、要导入的表数,然后为每个表填写一个 IMPORTDBTABLEDATA 结构 - 其中包含表名、要存储的 XMLElement* 项名、要获取的变量数(表中的列数),以及指向变量名和要存储的变量名的双指针。例如,请参阅 xmltest.cpp

数据库查询

您可以使用 XMLElement::XMLQuery(),它接受一个要测试的表达式、搜索深度(如果需要查询所有子元素,则为 -1),以及指向返回的 XMLElement* 的指针(这些元素不会被复制,函数只是将它们的指针复制到您的数组中)。示例如下:

XMLElement* e = ... ; // get this from somewhere
int nC = e->GetAllChildrenNum();
XMLElement* a = new XMLElement*[nC];
memset(a,0,sizeof(XMLElement*)*nC);
int nR = e->XMLQuery("some_var == \"*5*\"",a,-1);

for(int i = 0 ; i < nR ; i++) 
{ ... 
    // use a 
}
delete[] a;

上面的代码返回所有具有名为“some_var”的变量的子元素的指针,该变量的值包含“5”(支持正则表达式)。有关更多信息,请参阅 XML.CHM

STL 模式对 XMLElement 的更改

  • 请注意,XMLHeaderXMLContentXMLCommentXMLCData 也有一些微小的更改,但它们对应用程序是透明的。如果您使用 STL 版本,您需要注意以下列表总结的更改。
  • 现在,复制构造函数和运算符 = 允许直接复制或以其他方式复制 XMLElement
     XMLElement(const XMLElement&);      XMLElement& operator =(const XMLElement&); 
  • 以下函数使用引用。
    XMLElement& operator[](int);
    XMLElement& AddElement(const char*,int p = -1,bool Temp = false);
    XMLElement& AddElement(const XMLElement&,int p = -1);int Compare(XMLElement&); 

    这些函数使用引用而不是指针。此外,AddElement 已扩展,增加了插入位置(或 -1 表示添加到末尾),并且 InsertElement 已被移除。

  • int RemoveElementAndKeep(unsigned int i,XMLElement* el);

    这将被移除的元素存储在传递的指针中。

  • 不支持项目卸载(UnloadElement/ReloadElement)。
  • 不支持项目借用。
  • 项目排序使用 std::sort
  • XMLElement* Duplicate(XMLElement* = 0) 仍然返回指针,而不是引用。
  • GetComments()GetContents()GetVariables()GetCDatas()GetChildren() 返回 std::vector<>。此外,函数 AddComment()AddCData()AddVariable()AddElement()AddContent() 返回对添加项的引用。
  • GetAllChildrenNum() 仍返回指针。

对称元素加密/解密

从 Windows 上的版本 0x158 开始,该库为元素提供了对称(基于密码)的加密/解密功能。XMLElement 提供了 4 个新函数,两个用于就地加密/解密子元素,两个用于自我复制为加密/解密形式。整个元素都被加密,包括所有子元素、变量、注释和内容。

加密的 XML 元素是一个普通的 XML 元素,其中包含 1 个内容,该内容以加密形式存储了元素的所有内容。您可以像处理普通 XML 文件一样处理加密的 XML 文件,无论其中是否包含加密元素。

  • XMLElement* XMLElement :: Encrypt(const char* pwd);
  • XMLElement* XMLElement :: Decrypt(const char* pwd); 

这两个函数会自行加密/解密到一个新返回的 XMLElement 中(请记住删除它或将其分配给另一个 XMLElement)。使用 AES-256 和 SHA-1 哈希。如果出于任何原因加密或解密失败,它们将返回 0

  • bool EncryptElement(unsigned int i,char* pwd);
  • bool DecryptElement(unsigned int i,char* pwd); 

这些函数就地加密指定的子元素,成功时返回 true,失败时返回 false

每个加密的 XML 元素都可以像普通 XMLElement 一样解析,只包含 1 个内容数据。请注意,密码未存储,因此如果您丢失了密码,XML 数据将无法访问。

该库使用 CryptoAPI 来加密/解密数据。

元素签名/验证

版本 0x15A 提供了 3 个用于签名/验证的成员函数。

  •  bool XMLElement::SignElement(unsigned int i,PCCERT_CONTEXT pCert);
  •  bool XMLElment::RemoveSignature(unsigned int i);
  •  bool XMLElement::VerifyDigitalSignature(unsigned int i,PCCERT_CONTEXT* ppCert);

SignElement 使用提供的证书为索引为 i 的元素签名。元素签名将作为名为 __signature__ 的二进制值添加到元素中。如果签名已存在,函数将失败。如果证书无效、没有 private 密钥或发生其他错误,函数将失败。

RemoveSignature 函数从元素中删除签名(仅删除名为 __signature__ 的变量)。

VerifyDigitalSignature 函数验证索引为 i 的元素,并返回与签名匹配的证书。证书不一定受信任;您必须实际检查证书链以验证其来源。

如果索引 i-1,则这些函数将应用于其自身元素。

非对称加密/解密

版本 0x15B 提供了 2 个用于非对称加密/解密的成员函数。

  • XMLElement* EncryptElement(unsigned int i,PCCERT_CONTEXT* pCert,int nCert);
  • XMLElement* DecryptElement(unsigned int i,PCCERT_CONTEXT* ppCert);

EncryptElement 使用提供的证书列表加密索引为 i 的元素(如果 i == -1,则为自身)。该函数返回一个 XMLElement*,其中包含整个 XMLElement 的加密表示,如果发生错误,则返回 0

DecryptElement 函数使用“个人”存储中的任何证书解密索引为 i 的元素(如果 i == -1,则为自身)。如果 ppCert 不为 null,则返回用于解密元素的证书。它返回一个 XMLElement*,即原始元素。

请注意,与基于密码的对称加密不同,非对称加密需要证书的 public 密钥进行加密,需要 private 密钥进行解密。因此,例如,如果您使用 PC 中的 CA 根证书之一加密一个元素,该元素将正常加密,但如果没有 private 密钥,您将永远无法解密它。

二进制输入/输出

XML 文件可能很大,加载可能需要一段时间。该库已针对速度进行了优化,但如果需要最大性能,您可以尝试 ImportFromBinaryExportToBinary 函数。XMLXMLElementXMLVariableXMLCommentXMLContentXMLCData XMLHeader 都提供了上述两个函数。

  XML* x = new XML("somefile.xml");
  BDC b = x->ExportToBinary();
  // BDC is just a data container with member .size() to get the 
  // size of the data and p() to get a pointer to the data.
  x->ImportFromBinary(b);

使用二进制输入和输出将导致您的二进制 XML 文件在库升级且二进制输入和输出发生更改时变得无用,但对于长期使用,您可以考虑使用它。

JSON 解析器

XML 很好,但一些数据仍以 JSON 格式显示。XML.CPP 现在包含一个实验性的 JSON 转换器。  

Java 实现

好的,C++ 很完美,但我现在正在为使用 Java 的 Android 编写代码。XML.JAVA(包含在 zip 文件中)提供了该库的 Java 实现,具有非常相似的类和方法。当然,并非所有 C++ 方法都受支持,但它仍然是满足您 Java 需求的快速解决方案。

iOS 兼容性 

该库在 iOS 和 XCode 中运行良好。 

其他特性

以下是一些其他当前功能:

  • 使用 XML::ImportDB() 将数据库(支持所有 ADO 数据库)导入 XML 元素(帮助文件中提供了示例)。
  • 使用 XML::Query() 查询数据库。

以下是一些我未来想实现的功能:

  • 不区分大小写的函数
  • 部分 XML 加载/保存
  • XML 压缩

请留下您的问题和评论!

示例项目

  • XMLTest:一个命令行演示,用于探索库的主要功能。
  • TXML:Win32 的完整数据库/XML 文件解决方案:利用了库的所有强大功能。特点:
    • MDI XML 加载器
    • 从文件、URL、加密文件(AES 256)、导入 ADO 数据库、加载剪贴板加载,待办:加载部分
    • 保存到文件、加密文件、导出文本、导出到注册表项
    • 复制/剪切/粘贴、复制/剪切/粘贴到 Windows 剪贴板、复制/剪切追加、重命名、删除
    • XML 完整性检查、XML 压缩
    • 查看菜单:尚未实现,除了“切换视图” F4,它会切换到
      • 纯 XML
      • 数据库 - 类型 XML(非常适合存储表等数据库类型项)。网格样式编辑器
      • 纯文本
    • 插入元素/变量/注释/内容
    • 执行查询,打开一个包含查询结果的新 XML 文件。
    • 从 Internet 自动更新
    • 支持二进制 I/O。
    • 支持元素加密/解密。
    • 注意:不自动保存加载的 XML 文件,并且在未检查是否已保存的情况下关闭它们。请手动按 Ctrl+S 保存文件。
    • 注意:无撤销功能。如果您弄乱了,我很抱歉 Smile | <img src= " />
  • XMLPPC:Windows Mobile 5+ 的精简 XML 编辑器。支持 TXML 的所有功能,但不支持多文件打开和数据库查询。
  • Turbo GPS:Android 的端口使用了新的 Java 实现。试试吧!

历史

  • 2014 年 6 月 26 日 - 更新 0x170 - 在 C++/Java 版本中添加了一些助手。
  • 2012 年 11 月 16 日 - 更新 0x16B
    • 为 XMLElement 添加了 Next() 和 Prev() 以获取兄弟节点。
    • 为 XMLVariable 和 XMLContent 添加了 GetValueS(),以便在启用了 XML_USE_STL_EXTENSIONS 时将其值作为 std::string 获取。
    • 完全支持 iOS。
    • 修复了 GetAllChildren() 中返回子节点在其父节点之前的错误。
    • 增加了与 XML 第二个头文件的兼容性。现在 XMLHeader 可以包含主头和其下的另一个头。
    • 将 %llu sprintfs 替换为标准 long-long 而不是 MS 兼容的 %I64 前缀。 
  • 2012 年 8 月 8 日 - 更新 0x169
    • 启用了 XML 头 <!data >。 
    • 将 JSON 添加到主 xml.cpp 中。 
    • 一些小错误修复。 
  • 2012 年 1 月 24 日 - 更新 0x165
    • STL 索引错误修复
    • STL 加载时内存泄漏错误修复
  • 2011 年 10 月 13 日 - 更新 0x164
    • 各种错误修复
    • 添加了 json 实验性转换器
  • 2010 年 12 月 30 日 - 更新 0x162
    • 添加了二进制输入/输出
    • 修复了一些 GCC 兼容性问题
    • 修复了一些 STL 问题
    • 添加了 Java 实现
  • 2010 年 3 月 9 日 - 更新 0x15B
    • 修复了 STL 错误
    • 基于 CryptoAPI 证书添加了非对称加密/解密(Win32)
  • 2010 年 3 月 7 日 - 更新 0x15A
    • 修复了二进制变量中的错误
    • 基于 CryptoAPI 证书添加了元素签名/验证(Win32)
  • 2009 年 11 月 30 日 - 更新 0x158
    • 元素加密、内容二进制项和 STL 增强
  • 2009 年 8 月 9 日 - 更新 0x156
    • 累积更新和修复
  • 2009 年 1 月 15 日 - 更新 0x150
    • __int64 转换为 long long
    • 修复了小型解析错误
    • 添加了 STL 模式
  • 2008 年 10 月 20 日 - 更新 0x143
    • 添加了可选命名空间 XMLPP
    • 将“Savemode”、“Loadmode”和“Targetmode”的常量转换为可读的 enums
    • 添加了额外的保护,以避免在格式错误的 XML 时崩溃。
    • 将许多“int”替换为“size_t”,允许进一步扩展到 X64 并消除 C4267
      向更多函数添加了“Const
  • 2008 年 7 月 23 日 - 更新 0x141
    • 添加了注释包含 <> 的能力
    • 修复了由于格式错误的 XML 文件导致的一些崩溃
    • 向一些函数添加了 const
    • 添加了 SetValueInt64 GetValueInt64
    • 修复了 SetValueInt,使用 %i 而不是 %u
    • 其他小修复
  • 2008 年 4 月 27 日 - 更新 0x140
    • 添加了 XML::SetUnicode()
    • 修复了元素更新中的错误
    • Item 参数更改为 64 位
    • 修复了 64 位 Z<> 中的一个小错误
    • 修复了 XMLElement::MoveElement 中的错误
    • 添加了临时元素
  • 2007 年 11 月 22 日 - 更新 0x139
    • 一些错误修复
    • 使用 XMLElement::UpdateElement 进行项目更新
  • 2007 年 10 月 31 日 - 更新 0x136
    • 添加了项目借用和镜像
  • 2007 年 10 月 22 日 - 更新 0x135
    • XML::XMLXML::Load()XML::Save() 接受 Unicode 文件名
  • 2007 年 10 月 13 日 - 更新 0x132
    • XML 现在兼容 x64
    • 添加了 XDB.CPP 来演示 XMLDialog() 的用法
  • 2007 年 9 月 4 日 - 更新 0x12F
    • 元素卸载/重新加载的实现
  • 2007 年 8 月 20 日 - 更新 0x12E
    • 更快地保存到内存
  • 2007 年 8 月 19 日 - 更新 0x12D
    • 修复了 XMLQuery 错误
    • 修复了格式错误的 XML 错误
    • 添加了 XMLElement::AddElementAddVariableAddCommentAddContentAddCData 的文本版本
  • 2007 年 8 月 7 日 - 更新 0x12B
    • 修复了 CData 错误
    • 修复了序列错误
  • 2007 年 6 月 22 日 - 更新 0x129
    • 修复了 CData 错误
    • UTF-16 写入支持
  • 2007 年 6 月 21 日 - 更新 0x128
    • 添加了 XMLCData
    • 修复了 gcc/utf-16 的一些次要错误
    • CHM 帮助文件格式
  • 2007 年 6 月 8 日
    • 添加了 TXML.EXE(用于 Win32),利用了库的所有功能(目前仅提供二进制文件,无源代码)。
  • 2007 年 6 月 1 日 - 更新 0x125
    • 修复了 Pocket PC 错误,更新了 XML::XMLQuery()
    • 修复了 AddBlankVariable 错误
    • XMLPPC.EXE Pocket PC 示例
  • 2007 年 5 月 18 日 - 更新 0x124
    • UTF-16 文件读取
    • 修复了 Linux 编译
    • 修复了 XML::ImportDB()
    • 其他问题
  • 2007 年 5 月 15 日 - 更新 0x123
    • XML.CPP 中包含格式化选项
  • 2007年5月9日
    • 发布了原始版本
© . All rights reserved.