用delphi中的XMLDocument生成xml文件的问题 本帖最后由 jncharles 于 2010-08-15 11:33:28 编辑 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 提供實例,研究參考:1. XMLDocument生成XML:unit uExport; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, XMLDoc, XMLIntf; type TfrmExport=class(TForm) Button1:TButton; Label10:TLabel; edTo:TEdit; procedure Button1Click(Sender:TObject); procedure FormCreate(Sender: TObject); end; var frmExport:TfrmExport; xml:TXMLDocument; Root, Son1:IXMLNode; implementation {$R *.dfm} procedure addOne(var son, par:IXMLNode; chs, atn1, atv1, atn2, atv2:string); begin son:=par.AddChild(chs); if (atn1 <> ' ')and(atv1 <> ' ') then son.Attributes[atn1]:=atv1; if (atn2 <> ' ')and(atv2 <> ' ') then son.Attributes[atn2]:=atv2; end; function UploadOne(xmlPath, idxName1, idxVal1, idxName2, idxVal2, idxName3, idxVal3, idxName4, idxVal4, idxName5, idxVal5 :string ):Boolean; var Son2, Son3, Son4:IXMLNode; begin xml:=TXMLDocument.Create(nil); xml.Active:=True; xml.Encoding:= 'utf-8 '; Root:=xml.AddChild( 'export-list '); addOne(Son1, Root, 'add-list ', ' ', ' ', ' ', ' '); addOne(Son2, Son1, 'category ', 'name ', 'Table1 ', ' ', ' '); addOne(Son3, Son2, 'attr ', 'name ', idxName1, ' ', ' '); addOne(Son3, Son2, 'attr ', 'name ', idxName2, ' ', ' '); addOne(Son3, Son2, 'attr ', 'name ', idxName3, ' ', ' '); addOne(Son3, Son2, 'attr ', 'name ', idxName4, ' ', ' '); addOne(Son3, Son2, 'attr ', 'name ', idxName5, ' ', ' '); addOne(Son2, Son1, 'object ', 'folder ', 'Corporate Library remotePath ', 'name ', 'SourceFile '); addOne(Son3, Son2, 'source ', 'url ', 'sourcePath ', ' ', ' '); addOne(Son3, Son2, 'category ', 'name ', 'Table1 ', ' ', ' '); addOne(Son4, Son3, 'attr ', 'name ', idxName1, 'value ', idxVal1); addOne(Son4, Son3, 'attr ', 'name ', idxName2, 'value ', idxVal2); addOne(Son4, Son3, 'attr ', 'name ', idxName3, 'value ', idxVal3); addOne(Son4, Son3, 'attr ', 'name ', idxName4, 'value ', idxVal4); addOne(Son4, Son3, 'attr ', 'name ', idxName5, 'value ', idxVal5); xml.SaveToFile(xmlPath); result:=True; end; procedure TfrmExport.Button1Click(Sender:TObject); begin if not DirectoryExists(edTo.Text) then begin ShowMessage( 'Target Path not exist. '); exit; end; screen.Cursor:=crHourGlass; UploadOne(edTo.Text+ '\000001.xml ', 'edIdxN1.Text ', 'edIndex1.Text ', 'edIdxN2.Text ', 'edIndex2.Text ', 'edIdxN3.Text ', 'edIndex3.Text ', 'edIdxN4.Text ', 'edIndex4.Text ', 'edIdxN5.Text ', 'edIndex5.Text ', ); screen.Cursor:=crDefault; ShowMessage( 'Finished. '); end; procedure TfrmExport.FormCreate(Sender: TObject); begin edto.Text:= 'c:\temp '; end; end. 2.生成XML並解析:procedure TForm1.btreadClick(Sender: TObject); begin List := TList.Create; //初始化列表 InXMLDoc.LoadFromFile( 'c:\Input.xml '); //調入Input.xml文件 Root := InXMLDoc.DocumentElement; //取XML檔的根結點,即“ <學生花名冊> ” Parent_Node := Root.ChildNodes.First; //使Parent_Node指向學生結點 while (Parent_Node <> nil) do //迴圈取多個學生,可再多加幾個學生資訊測試 begin if (Parent_Node.NodeName = '學生 ') then //判斷是否為學生結點 begin Student := TStudent.Create; //新建一個學生的結構資訊 Student.sex := Parent_Node.Attributes[ '性別 ']; //取學生的性別屬性 Child_Node := Parent_Node.ChildNodes.First; //使Child_Node指向該學生的第一個子結點資訊 while (Child_Node <> nil) do //迴圈取學生的各個子各點 begin if (Child_Node.NodeName = '姓名 ') then //判斷是否為姓名結點 Student.name := Child_Node.Text //取姓名結點的值,取於name欄位中 else if (Child_Node.NodeName = '年齡 ') then //此行起後四行與前兩行類似 Student.age := StrToInt(Child_Node.Text) else if (Child_Node.NodeName = '電話 ') then Student.phone := Child_Node.Text; Child_Node := Child_Node.NextSibling; //順序取下一個學生的子結點資訊 end; List.Add(Student); end; Parent_Node := Parent_Node.NextSibling; //順序取下一個學生資訊 end; ShowMessage( 'Read over! '); btwrite.Enabled := True; end; //------------------------------------------------------------------------ procedure TForm1.btwriteClick(Sender: TObject); begin OutXMLDoc.Active := true; //啟動OutXMLDoc,自動初始化空的XML文檔 OutXMLDoc.Encoding := 'GB2312 '; //設置字元集 Root := OutXMLDoc.AddChild( '學生花名冊 '); //建根結點 for i := 0 to List.Count - 1 do //迴圈取各個學生資訊 begin Student := List.Items[i]; //順序取一個學生資訊 if (Student <> nil) then begin Parent_Node := Root.AddChild( '學生 '); //根結點後添加一個學生結點 Parent_Node.Attributes[ '性別 '] := Student.sex; //給學生結點設置性別屬性 Child_Node := Parent_Node.AddChild( '姓名 '); //學生結點後添加一個姓名結點 Child_Node.Text := Student.name; //設置姓名的文本值 Child_Node := Parent_Node.AddChild( '年齡 '); //此行起後四行與前兩行類似 Child_Node.Text := IntToStr(Student.age); Child_Node := Parent_Node.AddChild( '電話 '); Child_Node.Text := Student.phone; end; end; OutXMLDoc.SaveToFile( 'c:\Output.xml '); //把組織好的XML文檔存於Output.xml文件中 OutXMLDoc.Active := false; //鈍化(關閉)OutXMLDoc List.Free; //最後釋放保存臨時學生資訊的清單 ShowMessage( 'Write over! '); end; 3.XML遍歷解析:unit Unit1;interfaceusesWindows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,Dialogs, xmldom, XMLIntf, msxmldom, XMLDoc, StdCtrls;typeTForm1 = class(TForm) XMLDocument1: TXMLDocument; Button1: TButton; Button2: TButton; procedure Button1Click(Sender: TObject); procedure Button2Click(Sender: TObject);end;varForm1: TForm1;implementation{$R *.dfm}//讀取 xml 的函數{功能1: 傳入一個節點參數, 返回節點及其包含的所有內容;功能2: 排除了空節點.}function ReadXml(node: IXMLNode): string;varnodeList,attrList: IXMLNodeList;str,strName,strValue: string;i: Integer;beginResult := '';if not node.HasChildNodes then Exit;attrList := node.AttributeNodes; {根節點的屬性清單}nodeList := node.ChildNodes; {根節點下的子節點列表}str := '<' + node.NodeName;{先讀取屬性}for i := 0 to attrList.Count - 1 dobegin strName := attrList[i].NodeName; strValue := attrList[i].NodeValue; str := str + ' ' + strName + '=' + AnsiQuotedStr(strValue, '"');end;str := str + '>' + sLineBreak; {sLineBreak 是常量, 相當於 #13#10}{讀取子節點}for i := 0 to nodeList.Count - 1 dobegin strName := nodeList[i].NodeName; if nodeList[i].IsTextElement then begin strValue := nodeList[i].NodeValue; str := str + '<' + strName + '>' + strValue + '</' + strName + '>' + sLineBreak; end else if nodeList[i].HasChildNodes then begin str := str + ReadXml(nodeList[i]); {這是最關鍵的遞迴呼叫} str := str + '</' + strName + '>' + sLineBreak; {封口} end;end;str := str + '</' + node.NodeName + '>'; {封口}Result := str;end;//調用測試(1):procedure TForm1.Button1Click(Sender: TObject);varstr,s1,s2: string;beginXMLDocument1.LoadFromFile('c:\temp\test.xml');{必須用萬一提供的 xml 測試檔, 才能有相同的返回值}{讀取文件頭}s1 := AnsiQuotedStr(XMLDocument1.Version, '"'); {讀出版本, 並添加雙引號}s2 := AnsiQuotedStr(XMLDocument1.Encoding, '"'); {讀出字元集, 並添加雙引號}str := Format('<?xml version=%s encoding=%s?>',[s1,s2]); {這就是檔頭了}str := str + sLineBreak + ReadXml(XMLDocument1.DocumentElement);ShowMessage(str); {返回 xml 包含問頭在內的所有內容}end;//調用測試(2)procedure TForm1.Button2Click(Sender: TObject);varstr: string;node: IXMLNode;beginXMLDocument1.LoadFromFile('c:\temp\test.xml');node := XMLDocument1.DocumentElement.ChildNodes[0];str := ReadXml(node);ShowMessage(str); {返回返回根節點下第一個子節點的所有內容}end;end.///你這個比較簡單,直接遍歷XML再進行解析就可以了...(提供了幾個測試demo,你自己研究一下)/// 如果用生文本文件的方式来生成xml文件,可以吗?我不需要解析,遍历 看重點...文本文件方式生成xml我沒有做測試,我是用XMLDocument生成XMLDoc進行處理的...你認真研究一下提供的demo程序代碼還有更正一下:你的xml文件就是對別人發來的xml進行了解析才獲取出了數據,要不你如何獲取xml裡的數據???仔細研究一下,我先下班了... 我的数据来源于我的数据库,要生成一个xml文件对这个xml文件不需要解析,遍历。 问题一是你没有使用自动缩进这个选项,添加下面这一行: XMLDocument.Options := [doNodeAutoIndent]; 怎样在主窗体的一个panel里打开一个子窗体 SocketConnection如何设置连接超时? 提个很菜的pas控件问题 内存泄漏之二,什么情况下会申请内存, VCLSKIN问题 SQL语言难题! 怎樣提高數據查詢速度 CMMP协议和SGIP协议在流程上有什么区别? 从字符串中提取特定字符,请高手相助 关于Inno Setup indy10 发数据问题 送分100分:求几个VC6中的数据类型与DELPHI6相对应的数据类型
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, XMLDoc, XMLIntf; type
TfrmExport=class(TForm)
Button1:TButton;
Label10:TLabel;
edTo:TEdit;
procedure Button1Click(Sender:TObject);
procedure FormCreate(Sender: TObject);
end;
var
frmExport:TfrmExport;
xml:TXMLDocument; Root, Son1:IXMLNode;
implementation
{$R *.dfm}
procedure addOne(var son, par:IXMLNode; chs, atn1, atv1, atn2, atv2:string);
begin
son:=par.AddChild(chs);
if (atn1 <> ' ')and(atv1 <> ' ') then son.Attributes[atn1]:=atv1;
if (atn2 <> ' ')and(atv2 <> ' ') then son.Attributes[atn2]:=atv2;
end; function UploadOne(xmlPath,
idxName1, idxVal1,
idxName2, idxVal2,
idxName3, idxVal3,
idxName4, idxVal4,
idxName5, idxVal5
:string
):Boolean;
var Son2, Son3, Son4:IXMLNode;
begin xml:=TXMLDocument.Create(nil);
xml.Active:=True;
xml.Encoding:= 'utf-8 ';
Root:=xml.AddChild( 'export-list ');
addOne(Son1, Root, 'add-list ', ' ', ' ', ' ', ' '); addOne(Son2, Son1, 'category ', 'name ', 'Table1 ', ' ', ' '); addOne(Son3, Son2, 'attr ', 'name ', idxName1, ' ', ' ');
addOne(Son3, Son2, 'attr ', 'name ', idxName2, ' ', ' ');
addOne(Son3, Son2, 'attr ', 'name ', idxName3, ' ', ' ');
addOne(Son3, Son2, 'attr ', 'name ', idxName4, ' ', ' ');
addOne(Son3, Son2, 'attr ', 'name ', idxName5, ' ', ' ');
addOne(Son2, Son1, 'object ', 'folder ', 'Corporate Library remotePath ', 'name ', 'SourceFile '); addOne(Son3, Son2, 'source ', 'url ', 'sourcePath ', ' ', ' ');
addOne(Son3, Son2, 'category ', 'name ', 'Table1 ', ' ', ' '); addOne(Son4, Son3, 'attr ', 'name ', idxName1, 'value ', idxVal1);
addOne(Son4, Son3, 'attr ', 'name ', idxName2, 'value ', idxVal2);
addOne(Son4, Son3, 'attr ', 'name ', idxName3, 'value ', idxVal3);
addOne(Son4, Son3, 'attr ', 'name ', idxName4, 'value ', idxVal4);
addOne(Son4, Son3, 'attr ', 'name ', idxName5, 'value ', idxVal5); xml.SaveToFile(xmlPath);
result:=True;
end; procedure TfrmExport.Button1Click(Sender:TObject);
begin
if not DirectoryExists(edTo.Text) then begin
ShowMessage( 'Target Path not exist. ');
exit;
end; screen.Cursor:=crHourGlass; UploadOne(edTo.Text+ '\000001.xml ',
'edIdxN1.Text ', 'edIndex1.Text ',
'edIdxN2.Text ', 'edIndex2.Text ',
'edIdxN3.Text ', 'edIndex3.Text ',
'edIdxN4.Text ', 'edIndex4.Text ',
'edIdxN5.Text ', 'edIndex5.Text ',
); screen.Cursor:=crDefault;
ShowMessage( 'Finished. ');
end; procedure TfrmExport.FormCreate(Sender: TObject);
begin
edto.Text:= 'c:\temp ';
end; end.
begin
List := TList.Create; //初始化列表
InXMLDoc.LoadFromFile( 'c:\Input.xml '); //調入Input.xml文件
Root := InXMLDoc.DocumentElement; //取XML檔的根結點,即“ <學生花名冊> ”
Parent_Node := Root.ChildNodes.First; //使Parent_Node指向學生結點
while (Parent_Node <> nil) do //迴圈取多個學生,可再多加幾個學生資訊測試
begin
if (Parent_Node.NodeName = '學生 ') then //判斷是否為學生結點
begin
Student := TStudent.Create; //新建一個學生的結構資訊
Student.sex := Parent_Node.Attributes[ '性別 ']; //取學生的性別屬性
Child_Node := Parent_Node.ChildNodes.First; //使Child_Node指向該學生的第一個子結點資訊
while (Child_Node <> nil) do //迴圈取學生的各個子各點
begin
if (Child_Node.NodeName = '姓名 ') then //判斷是否為姓名結點
Student.name := Child_Node.Text //取姓名結點的值,取於name欄位中
else if (Child_Node.NodeName = '年齡 ') then //此行起後四行與前兩行類似
Student.age := StrToInt(Child_Node.Text)
else if (Child_Node.NodeName = '電話 ') then
Student.phone := Child_Node.Text;
Child_Node := Child_Node.NextSibling; //順序取下一個學生的子結點資訊
end;
List.Add(Student);
end;
Parent_Node := Parent_Node.NextSibling; //順序取下一個學生資訊
end;
ShowMessage( 'Read over! ');
btwrite.Enabled := True;
end; //------------------------------------------------------------------------
procedure TForm1.btwriteClick(Sender: TObject);
begin
OutXMLDoc.Active := true; //啟動OutXMLDoc,自動初始化空的XML文檔
OutXMLDoc.Encoding := 'GB2312 '; //設置字元集
Root := OutXMLDoc.AddChild( '學生花名冊 '); //建根結點
for i := 0 to List.Count - 1 do //迴圈取各個學生資訊
begin
Student := List.Items[i]; //順序取一個學生資訊
if (Student <> nil) then
begin
Parent_Node := Root.AddChild( '學生 '); //根結點後添加一個學生結點
Parent_Node.Attributes[ '性別 '] := Student.sex; //給學生結點設置性別屬性
Child_Node := Parent_Node.AddChild( '姓名 '); //學生結點後添加一個姓名結點
Child_Node.Text := Student.name; //設置姓名的文本值
Child_Node := Parent_Node.AddChild( '年齡 '); //此行起後四行與前兩行類似
Child_Node.Text := IntToStr(Student.age);
Child_Node := Parent_Node.AddChild( '電話 ');
Child_Node.Text := Student.phone;
end;
end;
OutXMLDoc.SaveToFile( 'c:\Output.xml '); //把組織好的XML文檔存於Output.xml文件中
OutXMLDoc.Active := false; //鈍化(關閉)OutXMLDoc
List.Free; //最後釋放保存臨時學生資訊的清單
ShowMessage( 'Write over! ');
end;
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, xmldom, XMLIntf, msxmldom, XMLDoc, StdCtrls;type
TForm1 = class(TForm)
XMLDocument1: TXMLDocument;
Button1: TButton;
Button2: TButton;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
end;var
Form1: TForm1;implementation{$R *.dfm}
//讀取 xml 的函數
{
功能1: 傳入一個節點參數, 返回節點及其包含的所有內容;
功能2: 排除了空節點.
}
function ReadXml(node: IXMLNode): string;
var
nodeList,attrList: IXMLNodeList;
str,strName,strValue: string;
i: Integer;
begin
Result := '';
if not node.HasChildNodes then Exit;attrList := node.AttributeNodes; {根節點的屬性清單}
nodeList := node.ChildNodes; {根節點下的子節點列表}str := '<' + node.NodeName;{先讀取屬性}
for i := 0 to attrList.Count - 1 do
begin
strName := attrList[i].NodeName;
strValue := attrList[i].NodeValue;
str := str + ' ' + strName + '=' + AnsiQuotedStr(strValue, '"');
end;
str := str + '>' + sLineBreak; {sLineBreak 是常量, 相當於 #13#10}{讀取子節點}
for i := 0 to nodeList.Count - 1 do
begin
strName := nodeList[i].NodeName;
if nodeList[i].IsTextElement then
begin
strValue := nodeList[i].NodeValue;
str := str + '<' + strName + '>' + strValue + '</' + strName + '>' + sLineBreak;
end else if nodeList[i].HasChildNodes then
begin
str := str + ReadXml(nodeList[i]); {這是最關鍵的遞迴呼叫}
str := str + '</' + strName + '>' + sLineBreak; {封口}
end;
end;str := str + '</' + node.NodeName + '>'; {封口}Result := str;
end;
//調用測試(1):
procedure TForm1.Button1Click(Sender: TObject);
var
str,s1,s2: string;
begin
XMLDocument1.LoadFromFile('c:\temp\test.xml');
{必須用萬一提供的 xml 測試檔, 才能有相同的返回值}
{讀取文件頭}
s1 := AnsiQuotedStr(XMLDocument1.Version, '"'); {讀出版本, 並添加雙引號}
s2 := AnsiQuotedStr(XMLDocument1.Encoding, '"'); {讀出字元集, 並添加雙引號}
str := Format('<?xml version=%s encoding=%s?>',[s1,s2]); {這就是檔頭了}str := str + sLineBreak + ReadXml(XMLDocument1.DocumentElement);ShowMessage(str); {返回 xml 包含問頭在內的所有內容}
end;
//調用測試(2)
procedure TForm1.Button2Click(Sender: TObject);
var
str: string;
node: IXMLNode;
begin
XMLDocument1.LoadFromFile('c:\temp\test.xml');
node := XMLDocument1.DocumentElement.ChildNodes[0];
str := ReadXml(node);
ShowMessage(str); {返回返回根節點下第一個子節點的所有內容}
end;end.///你這個比較簡單,直接遍歷XML再進行解析就可以了...(提供了幾個測試demo,你自己研究一下)///
看重點...
文本文件方式生成xml我沒有做測試,我是用XMLDocument生成XMLDoc進行處理的...
你認真研究一下提供的demo程序代碼還有更正一下:你的xml文件就是對別人發來的xml進行了解析才獲取出了數據,要不你如何獲取xml裡的數據???仔細研究一下,我先下班了...
XMLDocument.Options := [doNodeAutoIndent];