XML-->XML在Delphi中运用---Xml精要(转载)

Xml 精要(转载)

一)    XML优点

  XML属于SGML(Standard Greneralized Markup Language 标准通用标记语言)的一个子集, 它是一种采用标记来描述文档(数据)的种类和方法.  XML是由W3C下属的XML小组在JonBosak 的领导下于1996年完成的规范, 1998年正是成为一种W3C推荐的标准.  使用过HTML的开发人员都知道, HTML是属于树状结构, 并且使用<…> 和 <…./>作为节点的起始和结束标识.  XML的结构也是类似. 但它却比HTML有更多的灵活性, 你可以自己定义自己的节点名称和内容.

使用XML的主要优点是:

1.       它是基于文本的, 可以广泛的在局域网/互联网上传输

2.       能被各种平台上的应用程序(脚本)所理解, 前提是开发者知道这个文档的机构

3.       可以描述各种信息, 比如 客户/服务器的状态, 数据记录集合, 程序控制/配置信息.

4.       良好的可读性, 这不仅使程序能理解XML所描述的信息, 也易于开发人员理解其意义.

   它在B/S系统中广泛运用, 典型的一个就是用于描述从服务器上返回的数据集.

 

    下面我们再来看看另外和XML相关的几个名词:

        DTD(Document Type Definitions) 文档类型定义, 用于描述XML的约束条件, 即描述那些信息可用, 这些信息又是什么意思.   其可以使用 XML模式(XML Schema 我更喜欢叫它为XML 架构)来代替, 比如 用Delphi的TQuery.SaveToFile 时保存的XML文档就是用的XML模式.

        XSL(Extensible Stylesheet Language) 扩展的样式语言, 用于描述XML文档如何再图形媒介上显示.  常去CSDN的开发者应该都知道, 它就使用的这个来格式化XML在浏览器页面的输出.       

二)    XML的结构

上面提到XML为一个树形结构, 所以其必须要有一个唯一的根节点, 就像HTML中的<html>…</html>标识一样.  下面我们通过一个小的XML来描述XML常用到的结构.

1<?xml version="1.0" encoding="gb2312"?> <!--文档版本信息, 注释格式同HTML-->

2<XMLPackage>  

3  <clinetinfo ip=”10.28.65.21” handler=”si” unit=”安徽马鞍山社会养老保处”/>

<data>

5     <row id=”1” name="子蓝" sex=”男” age="24" duty="软件工程师"/>

6     <row id=”2” name="天使蓝" sex=”女” age="25" duty="商务经理"/>

7<!--data中包含了元素 row的两个实例,通过属性id予以区分 -->

</data>

9    <memo length=”16” color=” $0034494B”>Hello! I am nth! </memo> <!-- 这个元素中间包含的内容成为Text,而且也含有两个属性 length, color, 当然也可以没有属性 -- >

10   <Actions acition=”update/insert”/> <!—该元素描述了一动作控制信息-->

11</XMLPackage>

(注意: 前面的数值标号, 只是我这里方便讲解自己加的, 正规的文档是没有的.)

 

 

 

 

 

 

 

 

 

 

 

 

 

 

   下面以此为例了解一下这个文档的意义和格式要求.

    第1行为XML 头说明, version 标识这个文档格式的版本号, encoding 标识文档使用的语系. 为什么要使用verision 呢? 这是因为在分布的应用系统中, 可能存在版本升级的问题. 比如现在新出了一个2.0的版本, 服务器已经更新为2.0的版本了, 但客户端还使用的是原来1.0的版本, 这样通过这个版本号服务器端就能方便的识别哪些是可以接受的版本,哪些是该拒绝的版本.第2行到第12行描述的是name为XMLPackage的根节点, 根节点只允许有一个注意节点结束时使用</…>标识的.

    一个节点又叫做一个元素,由< nodename > text </ nodename >或者< nodename… />来封装. 前者一般用来封装比较大的文本对象(如一个文本文件或者图像),当然在<nodename 和 >之间也可以包含有属性(如9行,注意属性不能包含在元素结束位置</nodename>中) ; 后者则主要通过属性来描述对象, 如用来描述一条记录或者状态信息(比如2, 5, 6, 10行)。元素的属性之间使用空格分割 

    节点(元素)是可以嵌套使用的,但不能交叉嵌套,这和For语句的嵌套规则是类似的。每个节点(属性)之间可以包含任意的空格,tab,回车和换行符号,这些都会被XML解析器自动忽略。但要注意< nodename > text </ nodename >格式的节点内部(就是text部分)包含的空格和回车符号会被XML解析器作为该节点的Text读出。所以一般我们会采用如第9行一样的格式。

 

图片等Bin 数据如何封装呢?  我的做法是使用MIME格式把bin数据转换为字符数据, 然后封装到XML文档中. 常用的编码为 BASE64, 当然你也可以用其他的编码格式, 比如16进制, 原则是要把Bin数据变成字符数据封装.像上面的这个文档也可以加入DTD文档或者XML模式元素, 来描述每个Row中每个属性的意义和约束.

 

三)    使用Delphi解析XML 文档

对于XML的解析主要有 即DOM(文档对象模型) 和SAX(Simple API for XML)。DOM是通过构建内存对象来完成XML的解析, 后者则是将解析过程转换为事件驱动。  

Delphi提供了三种DOM解析程序:MSXML, Open XML,Xerces XML。MSXML是微软提供的解析程序,被实现为一系列的COM对象, 主要包括 msxml3.dll, msxml3a.dll, msxml3r.dll 三个动态链接库。这里我只说一下通过IXMLDocument来完成XML的解析, 这里你只需要关心节点Node和节点集合NodeList 接口(Interface)既完成XML对象的获取 ,这也是我们通常会使用的方法。 

首先我们来看一种通过遍历节点的方法,先来熟悉几个属性:

  Version :WideString 文档的版本号。

  DocumentElement :IXMLNode  根节点, 比如上面实例的<XMLPackage>对象。通过根节点您就能开始遍历整个XML节点数.

  ChildNodes :IXMLNodeList 当前节点的子节点集合。

  Node[ Nodeindex or NodeName ] :IXMLNode  XML的节点。 通过节点,您可以通过它的Text ,attribute 属性来获取节点的内容和属性。也可以使用GetNode、Get方法来获取节点。 

通过下面的示范程序您可以了解如何通过这几个属性来从XML中获取我们想要的信息。

Var XMLDocument :IXMLDocument;

   XMLNode :IXMLNode;

begin

  XMLDocument := TXMLDocument.Create( ‘d:\test.xml’ );

  XMLDocument.Active := True; 

  XMLNode := XMLDocumen.Document.Element;  //根结点

  Memo1.Line.Add( ‘根节点的名字为:’ + XMLNode.Name );

  Memo1.Line.Add( ‘根节点下的子节点数目为: ‘ +  IntToStr( XMLNode.ChildNodes.Count ));

  XMLNode := XMLNode.ChildNodes.Node[2];  // 将当前访问的节点的第三个子节点置为要访问的节点memo.

  Memo1.Line.Add( ‘根节点下的第三个子节点的名字’ + XMLNode.Name  ); 

  if  XMLNode.HasAttribute( ‘color’ )  then

     Memo1.Line.Add( ‘该节点的属性color:’ + XMLNode.Attribute[‘color’] )

  Else

       Memo1.Line.Add( ‘该节点没有属性 color, 或者大小写不正确!’ ); 

If  XMLNode.IsTextElement t hen

   Memo1.Line.Add( ‘该节点包含有内容Text: ‘ + XMLNode.Text )

Else

   Memo1.Line.Add(‘该节点为非叶子节点, 不能包含内容Text!’ ); 

XMLNode := nil;

XMLDocument.Free;

XMLDocument := nil;

  End; 

节点内的属性读取还有个快捷方法。通过 IXMLNode 的AttributeNodes 属性,能将该Node 的属性以节点的方式映射出来。 这样通过 NodeName 和NodeValue 属性就能读出每个属性的值。AttributeNodes.Count 说明了该节点包含的属性个数。如下面的代码片断。

  // 获取指定的节点

  XMLNode := GetNode( strNodePath, intRowIndex, dep );

  Result := True; 

  if  not assigned( XMLNode ) then begin 

    Result := False;     // 无效的节点或者该节点不能包括单独的Text

    exit;

   end; 

  // 逐个获取该节点的属性和属性值

  for i := 0 to XMLNode.AttributeNodes.Count - 1 do begin 

    sltAttributeName.Add( XMLNode.AttributeNodes.Nodes[i].NodeName );

    sltAttributeValue.Add( XMLNode.AttributeNodes.Nodes[i].NodeValue );

  end; 

      另外对于一个有固定格式的文档, Delphi还提供了一种叫做数据绑定向导的方法来实现解析。 这样的优点是你根本就不要在去考虑什么节点子节点之类头疼的问题了,通过Delphi向导生成的XML文档接口,你可以像访问普通的对象一样来访问XML中的对象。 下面我们也来谈一下如何通过这种方法来实现解析。

   1. 准备好你要解析的XML文档典型实例。这至关重要,因为Delphi需要这个文档来生成一个xdt文档以及相应的对象接口。

  2. 窗体中加入TXMLDocument 组件(在Internet页面上),并将其FileName置为要解析的XML文档实例。

  3. 右击 TXMLDocument, 在弹出的菜单中选择 XML Data Binding Wizard… 

  4. 在弹出的向导中, 第一页中, 您可以看到Delphi已经帮您把XML文件中的各个节点对应到了接口,这里你可以展开每个节点,编辑每个节点的属性数据类型。单击Next到下一个配置页面,这里你可以看到Delphi生成了各个节点接口的框架代码。 单击 Finsh 完成向导, 这样Delphi将生成一个xdt 文件和与该XML文档结构对应的XML接口单元(默认是与实例文档同名)。 

5. 将Delphi生成的这个接口单元use到您要调用该XML文档的单元中, 以根节点的接口做为入口,你就可以轻松的访问与该XML类似结构的XML文档了。

一下是个小的示范。

  var xml :IXMLXMLPackageType;  // 通过向导生成的根接口

begin

     xml := LoadXMLPackage( 'D:\AppServ\www\xml\test.xml' ); // 这个方法也是由向导生成的。

     memo1.Lines.Add(xml.Data.Row[1].name);  // 比如我要取得data下的第2个row 中的name属性。

     Memo1.Lines.Add( xml.Memo.Color ); // 访问Memo节点中的属性 color

     Memo1.Lines.Add( xml.Memo.Text );  // 访问 Memo 节点中的属性 Text。

………………..

   end; 

这种方法很简单吧, 不过它有一个局限性, 就是一个接口单元只能对应的解释一种整体结构一致的XML文档。 但对于一般的小型应用, 也可以考虑使用这个简洁的方法, 这使我们可以不必取关心这些讨厌的Node对象, 毕竟我们软件中用使用的每个XML文档都总是有个自己的原生结构的。 

关于如何生成XML 文档, 有两种主要方法:

1。通过IXMLNode 对象的AddNode 或者 SetValue来动态的生成。

2.手工,以字符串的形式生成

我一般更愿意用第2种方法,这也有个小技巧, 你可以先准备好一个XML的框架,然和用字符串替代(format)的方法来填写里面的标记。

四)XML 封装类

    出于XML的树型特性,理论上只要是能遍历的树的方法就能用于遍历XML文档,典型的就是递归和回溯算法了。这里为了更好的说明和帮助大家通过IXMLDocument来完成解析,我临时封装了一个类库, 提供了几个比较快捷的函数,可以借用它解析一般不是很复杂的文档。本想把代码粘贴出来,但太长了,有需要的朋友可以到我网站下载

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值