信息发布软件,b2b软件,广告发布软件

标题: Delphi程序如何操作XML文档终于有一个好的门路 [打印本页]

作者: 群发软件    时间: 2017-8-6 23:02
标题: Delphi程序如何操作XML文档终于有一个好的门路
本帖最后由 群发软件 于 2017-8-6 23:07 编辑

Delphi程序如何操作XML文档终于有一个好的门路

 Delphi7 支持对XML文档的操作,可以通过TXMLDocument类来实现对XML文档的读写。可以利用TXMLDocument把XML文档读到内存中,从而可以进行编辑、保存操作。TXMLDocument类是通过DOM(文档对象模型)接口来访问XML文档中的各个元素的。对于DOM接口的实现有多种方式,Delphi支持的方式有:1)微软的MSXML SDK,这种方式是通过COM对象来实现;2) Apache 的Xerces的实现方式;3)另外一种是开源OpenXML实现方式。对于不同的接口实现方式可以通过设定TXMLDocument的DOMVender来进行控制。

  支持XML的Delphi单元主要存在与…BorlandDelphi7SourceXml目录下,主要包括:XMLIntf,XMLDoc,xmldom,msxmldom,xercesxmldom,xdom,oxmldom等单元。


l  XMLIntf――包括了Borland自己定义的XML文档的接口;

l  XMLDoc――是对XMLIntf中所定义接口的Borland实现;

l  Xmldom――定义了DOM(文档对象模型)接口,这里对DOM接口进行了Borland的实现;

l  Msxmldom――实现微软对Xmldom中定义的接口的实现,主要调用微软的COM对象来实现,对Xmldom中定义接口的封装;

l Xercesxmldom――Borland通过Xerces XML DOM方式来实现对Xmldom中定义接口的封装;

l Oxmldom――Borland通过使用OpenXML来实现对Xmldom中定义接口的封装;


TXMLDocument类的属性,请参考Borland的帮助文件;


  读写XML文档
l 读取XML文档

通常情况下不通过直接使用TXMLDocument对象来进行XML文件的读取,而是使用XMLDoc单元中提供的几个有用的函数来读取XML文档,这些函数包括:

function LoadXMLDocument(const FileName: DOMString): IXMLDocument;

function LoadXMLData(const XMLData: DOMString): IXMLDocument; overload;

function LoadXMLData(const XMLData: string): IXMLDocument; overload;

function NewXMLDocument(Version: DOMString = '1.0'): IXMLDocument;

可以看出这些函数全部返回的是IXMLDocument接口,得到了IXMLDocument接口在进行文档的操作;

这些函数都是通过创建TXMLDocument对象来实现对XML文档的读取的;其中NewXMLDocument仅仅创建一个IXMLDocument接口。

可以这样利用NewXMLDocument来读取XML文档:

  XMLDoc := NewXMLDocument;

XMLDoc.LoadFromFile(FileName);


l 保存XML文档

可以通过下面的方式来保存XML文档:


XMLDoc := NewXMLDocument;

iRoot := IXMLDoc.CreateNode(‘TestXMLDocument’);

XMLDoc.DocumentElement := iRoot;

XMLDoc.SaveToFile(FileName);


  可以看出通过接口来操作XML文档是非常方便的;


选用不同类型的XML解析方式
  上面已经提到有三种方式实现DOM,也就是可以应用Borland提供的3种不同的XML解析器来对XML文档进行解析;


  三种解析器

  1、微软的解析器(MSXML SDK)

微软解析器主要应用在Windows中,在安装MSXML SDK的时候会安装解析器,同时IE浏览器也提供了解析器,这个解析器是一个COM。

  2、Apache的Xerces解析器

Borland自己实现了一个Xerces解析器,这个可以通过调用xercesxmldom.dll模块来实现;如果使用这个解析器可能需要同应用程序一起进行分发xercesxmldom.dll,XercesLib.dll,CC3260MT.DLL三个DLL文件

  3、OpenXML解析器

这个解析器的源代码存在于xdom.pas单元中,这个可以通过http://www.philo.de/xml/进行跟新下载,这个是一个德国人写的XML解析器;

  使用不同解析器的比较

对于三种方式的解析器比较如下:

  1、微软的解析器

微软的解析器当然好了,但是也不能排除存在的意外情况,在我个人的经验中,至少我们公司对于XML解析的方式,只有在IE6.0以上的版本才能够正常的工作;

至于,Borland同样是通过引入MSXML.DLL的接口来实现的,所以可以推理出,同样存在同样的问题;这个通过研究TMSDOMImplementation(msxmldom单元中)的实现方式可以得到证明,实现的过程中通过调用CoCreateInstance函数接口来实现解析的;

在发布解析XML的代码的时候可能就会存在由于IE的本版的不同,需要把IE6.0一同发布,比较麻烦;

  2、Borland的Xerces解析器

这种方式的解析器是通过 LoadLibrary(PChar(LibName));函数,LibName的内容是xercesxmldom.dll(Windows平台),libxercesxmldom.so.1(Linux平台)。那么就需要随同应用程序一起发布的Dll,就包括了xercesxmldom.dll,XercesLib.dll,CC3260MT.DLL;

这个发布相对于发布不同版本的IE6.0来说要相对简单一些;

  3、OpenXML解析器

由于存在xdom.pas单元,这个单元中包含了完全的XML解析的源代码,那么应用这种方式,可以避免软件发布的种种问题,这是由于解析的代码被静态编译在应用程序内部。唯一不好的地方就是应用程序的体积可能要大一些;


l 如何使用不同的解析器

我们可以写一个函数来使用不同的解析器;

function NewDiffXmlDocument(DOMVender: string;

Version: DOMString = '1.0'): IXMLDocument;

var

XMLDoc : TXMLDocument;

begin

XMLDoc := TXMLDocument.Create(nil);

XMLDoc.DOMVendor := GetDOMVendor(DOMVender);

Result := XMLDoc;

Result.Active := True;

if Version <> '' then

Result.Version := Version;

end;


其中DOMVender如果用Borland提供的三种方式进行解析的话,分别取值是:

Microsoft――存在于msxmldom.pas单元中的SMSXML常量;

Xerces――存在于xercesxmldom .pas单元中的SXercesXML常量;

OpenXML――存在于oxmldom.pas单元中的SOpenXML常量;


这个是由于在msxmldom,xercesxmldom,oxmldom三个单元的initailization部分,都通过调用RegisterDOMVendor函数,注册了不同的解析器接口;


当然,Borland同样提供了一种可以灵活进行扩展的机制来扩展用户自己的解析器,这个需要继承,TDOMVendor类(存在于xmldom单元中)。实际上,Borland自己就是通过这种方式来实现不同方式解析器的;具体的实现过程可以通过参考oxmldom单元中对xdom的封装;


有关许多接口,会需要通过xml进行数据交换,弄个例子,方便参考

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs,XMLDoc,XMLIntf, StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    Memo1: TMemo;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
var
Xml: TXMLDocument;
Rootnode,node : IXMLNode;
begin
Xml := TXMLDocument.Create(nil);
// Xml.LoadFromFile('aaa.xml');
try
//加入版本信息 ‘<?xml version="1.0" encoding="GB2312" ?> ’
Xml.Active := True;
Xml.Version := '1.0';
Xml.Encoding :='GB2312';

Rootnode := Xml.CreateNode('CIF_INFO');
Xml.DocumentElement := Rootnode;
node := Xml.CreateNode('TXNCODE');
Rootnode.ChildNodes.Add(node);
node.Text := '420001';
node := Xml.CreateNode('RESPCODE');
Rootnode.ChildNodes.Add(node);
node.Text := '0000';
node := Xml.CreateNode('CIFID');
Rootnode.ChildNodes.Add(node);
node.Text := '0030209728';
node := Xml.CreateNode('RESCODE');
Rootnode.ChildNodes.Add(node);
node.Text := '0000';
node := Xml.CreateNode('RESMSG');
Rootnode.ChildNodes.Add(node);
node.Text := '';

Xml.SaveToFile('aaa.xml');
xml.Active := False;
showmessage('创建成功!');
finally
Xml.Free;
end;
end;

procedure TForm1.Button2Click(Sender: TObject);
var
Xml: TXMLDocument;
Rootnode,node : IXMLNode;
nodelist:IXMLNodeList;
b,c,str :string;
i:Integer;
begin
Xml := TXMLDocument.Create(Application);


try
Xml.LoadFromFile('aaa.xml');
Xml.Active := True;

Rootnode := Xml.DocumentElement;
nodeList :=Rootnode.ChildNodes;
for i:=0 to nodelist.Count-1 do
    begin
      if  Rootnode.ChildNodes.NodeValue = null then
         begin
           c:='空';
         end
         else
         begin
           c:= Rootnode.ChildNodes.NodeValue;
         end;
      str:=str+c+#13#10;
    end;
//b := Rootnode.ChildNodes[ 'CIFID'].NodeValue;
Memo1.Lines.Add(str);
xml.Active := False;
finally
Xml.Free;
end;
end;
end.

创建XML文档,以及节点
------------------------------------------}
procedure TForm1.CreateXMLClick(Sender: TObject);
var
  pNode,cNode: IXMLNode;                   {定义两个节点: 父节点、子节点}
begin
  xmldcmnt1.XML.Clear;
  xmldcmnt1.Active := True;                {必须先激活}
  xmldcmnt1.Version := '1.0';              {设置版本}
  xmldcmnt1.Encoding := 'GB2312';          {设置语言}

  pNode := xmldcmnt1.AddChild('科室名单'); {添加的第一个节点是根节点, 现在的 pNode 是根节点}
  pNode.SetAttribute('备注', '测试');      {为根节点设置属性}

  pNode := pNode.AddChild('人员');         {为根节点添加子节点, 现在的 pNode 是 "人员" 节点}
  pNode.SetAttribute('职务', '科长');      {设置属性}
  pNode.SetAttribute('备注', '正局级');

  cNode := pNode.AddChild('姓名');          {为 pNode 添加子节点, 返回值 cNode 指向了新添加的节点}
  cNode.Text := '张三';

  cNode := pNode.AddChild('性别');
  cNode.Text := '男';

  cNode := pNode.AddChild('年龄');
  cNode.Text := '34';
end;

<?xml version="1.0" encoding="GB2312"?>
<科室名单 备注="测试">
     <人员 职务="科长" 备注="正局级">
           <姓名>张三</姓名>
           <性别>男</性别>
           <年龄>34</年龄>
     </人员>
</科室名单>


{-----------------------------------------
添加XML节点
------------------------------------------}
procedure TForm1.Button1Click(Sender: TObject);
var
  newNode, newNodeAdd: IXMLNode;
begin
  newNode := xmldcmnt1.DocumentElement.AddChild('人员');
  newNode.Attributes['职务'] := '秘书';

  newNodeAdd := newNode.AddChild('姓名');
  newNodeAdd.Text := '小翠';

  newNodeAdd := newNode.AddChild('性别');
  newNodeAdd.Text := '女';

  Memo1.Lines := xmldcmnt1.XML; {查看}
  {会在尾部增加:
   <人员 职务="秘书"><姓名>小翠</姓名><性别>女</性别></人员>
  }
end;

<?xml version="1.0" encoding="GB2312"?>
<科室名单 备注="测试">
    <人员 职务="科长" 备注="正局级">
        <姓名>张三</姓名>
        <性别>男</性别>
        <年龄>34</年龄>
    </人员>
    <人员 职务="秘书">
       <姓名>小翠</姓名>
       <性别>女</性别>
    </人员>
</科室名单>


{-----------------------------------------
判断节点的类型
------------------------------------------}
//判断是否是支节点
procedure TForm1.Button1Click(Sender: TObject);
var
  node: IXMLNode;
begin
  node := xmldcmnt1.DocumentElement.ChildNodes[0]; {这是"人员"节点}

  if node.HasChildNodes and not node.IsTextElement then
    ShowMessage('是支节点'); {是支节点}
end;


//判断是否是叶节点
procedure TForm1.Button2Click(Sender: TObject);
var
  node: IXMLNode;
begin
  node := xmldcmnt1.DocumentElement.ChildNodes[0].ChildNodes[0]; {这是"姓名"节点}

  if node.IsTextElement then
    ShowMessage('是叶节点'); {是叶节点}
end;


//判断是否是文本节点
procedure TForm1.Button3Click(Sender: TObject);
var
  node: IXMLNode;
begin
  node := xmldcmnt1.DocumentElement.ChildNodes[0].ChildNodes[0].ChildNodes[0];
  {这是"张三"那个文本节点}

  if node.NodeName='#text' then
    ShowMessage('是文本节点'); {是文本节点}
end;


//判断是否是空节点
procedure TForm1.Button4Click(Sender: TObject);
var
  node: IXMLNode;
begin
  node := xmldcmnt1.DocumentElement.ChildNodes[4];
  {这是根节点下的第五个节点: "辅助人员", xml 中设为空}

  if not node.HasChildNodes then
    ShowMessage('是空节点'); {是空节点}
end;


{-----------------------------------------
NodeValue 和NodeName的区别
------------------------------------------}
procedure TForm1.Button1Click(Sender: TObject);
var
  node: IXMLNode;
begin
  node := xmldcmnt1.DocumentElement;

  node := node.ChildNodes[0]; {现在的 node 指向了第一个人员节点}

  //属性值: NodeValue 是可读写的
  ShowMessage(node.AttributeNodes[0].NodeValue); {科长}
  node.AttributeNodes[0].NodeValue := '正科长';
  ShowMessage(node.AttributeNodes[0].NodeValue); {正科长}

  //属性名: NodeName 是只读的
  ShowMessage(node.AttributeNodes[0].NodeName);  {职务}
  //node.AttributeNodes[0].NodeName := 'xxx';    {如果企图给属性名赋值会出错}

  node := node.ChildNodes[0]; {现在的 node 指向了第一个人员"张三"的姓名节点}

  //节点值: NodeValue 是可读写的
  ShowMessage(node.NodeValue); {张三}
  node.NodeValue := '张老三';
  ShowMessage(node.NodeValue); {张老三}

  //节点名: NodeName 是只读的
  ShowMessage(node.NodeName);  {姓名}
  //node.NodeName := 'xxx';    {如果企图给节点名赋值会出错}
end;


{-----------------------------------------
某节点的上一个节点、下一个节点、父节点
------------------------------------------}
procedure TForm1.Button1Click(Sender: TObject);
var
  node,nodeX: IXMLNode;
begin
  node := XMLDocument1.DocumentElement;
  node := node.ChildNodes[1];
  node := node.ChildNodes[1];
  {现在的节点 node 指向了我们的例子中的第二个人员"李四"}

  ShowMessage(node.ChildNodes[0].NodeValue); {女}

  //获取该节点的上一个节点, 它上一个节点应该是李四的姓名
  nodeX := node.PreviousSibling;  {PreviousSibling}
  ShowMessage(nodeX.NodeValue);   {李四}

  //获取该节点的下一个节点, 它下一个节点应该是李四的年龄
  nodeX := node.NextSibling;      {NextSibling}
  ShowMessage(nodeX.NodeValue);   {43}

  //获取该节点的父节点
  nodeX := node.ParentNode;       {ParentNode}
  ShowMessage(nodeX.NodeName);    {人员}
end;


{-----------------------------------------
对象的 XML 属性
------------------------------------------}
//XMLDocument1 对象的 XML 属性
procedure TForm1.Button1Click(Sender: TObject);
begin
  {前面我们经常用这句话, 因为这里的 Lines 与 XML 同属于 TStrings}
  Memo1.Lines := XMLDocument1.XML;

  {如果不怕麻烦, 这样写也可以:}
  Memo1.Lines.Text := XMLDocument1.XML.Text;

  {如果知道了这一点, 那 XML 属性的功能可就多了, 并且这里的 XML 属性是可写的}
  {不过这里要谈的是节点的 XML 属性}
end;


//根节点的 XML 属性
procedure TForm1.Button2Click(Sender: TObject);
var
  node: IXMLNode;
begin
  {先看根节点: XMLDocument1.DocumentElement}
  node := XMLDocument1.DocumentElement;

  //Memo1.Lines := node.XML; {这一句会出错}
  {因为节点的 XML 属性是 WideString 类型的, 应该这样:}
  Memo1.Lines.Text := node.XML; {将会读出根节点与根节点包含的所有内容}

  {还有一个更大的区别: 节点的 XML 是只读的!}
end;


//子节点的 XML 属性
procedure TForm1.Button3Click(Sender: TObject);
var
  node: IXMLNode;
begin
  node := XMLDocument1.DocumentElement;
  node := node.ChildNodes[0];

  Memo1.Lines.Text := node.XML; {会显示一个子节点的全部}
end;


//属性的 XML 属性
procedure TForm1.Button4Click(Sender: TObject);
var
  node: IXMLNode;
begin
  node := XMLDocument1.DocumentElement;
  node := node.AttributeNodes[0]; {属性也是 IXMLNode 类型的}

  ShowMessage(node.NodeName);  {备注}
  ShowMessage(node.NodeValue); {测试}

  {用 XML 属性一次把他们都读出来:}
  ShowMessage(node.XML);       {备注="测试"}
end;


//叶节点的 XML 属性
procedure TForm1.Button5Click(Sender: TObject);
var
  node: IXMLNode;
begin
  node := XMLDocument1.DocumentElement;
  node := node.ChildNodes[0];
  node := node.ChildNodes[0];
  node := node.ChildNodes[0]; {这就是叶节点了}

  ShowMessage(node.XML);  {张三}

  {这时的 XML 属性和 Text 属性一样了}
  ShowMessage(node.Text); {张三}
end;



1        四川茂县山体塌方        新闻 视频 图片        13775
四川茂县山体塌方 初步估计7000方左右
【四川茂县山体塌方 初步估计7000方左右】中新网8月6日电 据四川阿坝州公路局消息:今日15时45分,国道213线K769+700(茂县石大关旧关楼)发生山体高位坍方7000余...
2        女子狂撕咬宠物狗        新闻 视频 图片        3586
女子狂撕咬宠物狗将狗毛吐到地上 坐立不安状似嗑过药
一名女子抱着小狗骂骂咧咧,连咬小狗好几口,还把满嘴的狗毛吐到地上。小狗几次试图挣脱她的怀抱,都被拽了回来。视频发布者表示女子坐立不安,看起来像是磕了药。...
3        吉林千人同吃拌饭        新闻 视频 图片        60714
吉林千人同吃拌饭 原材料重达百斤盛放在巨型木锅中
导读:原标题:吉林千人同吃拌饭 原材料重达百斤盛放在巨型木锅中, 2017年08月6日,吉林省延吉市,“2017食运会美食嘉年华”正式启动,在食运会美食嘉年华活动现场...
4        郑州现最萌街道        新闻 视频 图片        39225
5        王毅会见朝鲜外相        新闻 视频 图片        17132
6        女学生网吧住一月        新闻 视频 图片        85235
7        泸州蚊子被热死        新闻 视频 图片        100623
8        游客行纳粹礼被捕        新闻 视频 图片        253641
9        日文游戏全网禁售        新闻 视频 图片        45054
10        藏快递车混入清华        新闻 视频 图片        87606

11        马蓉移民澳洲        新闻 视频 图片        63899

作者: c19900420    时间: 2017-8-11 03:41
指导,模版装修的很漂亮。很满意。下次还会再来
作者: wbd902    时间: 2017-8-11 05:57
高大上了,服务很周到,能达到我想要的效果,设计后生意越来越好了!好开心啊!
作者: 1124789174    时间: 2017-8-11 22:55
卖家服务好,模板质量好。发货快速。
作者: 乱世扶稣    时间: 2017-8-15 17:04
酷很霸气哦!服务真的真的很好哟~~赞一个,还会推荐其他商家来的哦~~棒
作者: 武器    时间: 2017-8-17 04:31
使用了,界面清爽,功能齐全,是想要的效果。
作者: anleeycn    时间: 2017-8-21 04:00
,大爱,喜欢,是我想要的,不错,值得购买,
作者: ebxly    时间: 2017-8-22 14:34
事情好垃圾的
作者: ziyang701    时间: 2017-8-22 22:06
这次合作,整个过程很顺利,今后我的店铺还是会请你帮我装修,希望越来越好
作者: jiandao1    时间: 2017-8-23 05:34
.耐心。负责
作者: 小白    时间: 2017-8-23 07:02
店主人好,模版也好操作,希望生意兴隆
作者: 小白    时间: 2017-8-24 02:14
家人不错值得购买超赞
作者: dfgdgdfgdf    时间: 2017-8-24 23:00
务很好,设计的宝贝很漂亮我很满意,以后有需要还会合作
作者: 阿拉丁    时间: 2017-8-26 02:09
垃圾网络公司,没这个技术别吹这个牛B,从6月份给我做网站做到11月份,不是这不行就是那个不行。技术不行就别干这行,就这种服务态度,劳资钱当送给你们
作者: feiyang2006    时间: 2017-8-26 16:17
学习了,不错,讲的太有道理了
作者: ye112219    时间: 2017-8-26 18:52
度一直很好,赞一下客服售前,和技术售后,特别是18号28号33号技术!赞你们。人好,技术好,态度好,服务好,什么都好!
作者: 阿拉丁    时间: 2017-8-27 09:57
很复杂很耐心祝生意好
作者: huaxue98    时间: 2017-8-31 21:01
评,客服态度也特别好,077号笨蛋棒棒哒???
作者: 武器    时间: 2017-9-2 01:45
真是收益匪浅
作者: niyaoz1    时间: 2017-9-4 04:05
支持一下
作者: java12005    时间: 2017-9-5 20:18
耐心的卖家,好评




欢迎光临 信息发布软件,b2b软件,广告发布软件 (http://www.postbbs.com/) Powered by Discuz! X3.2