有時,只需要用xml作一些小的應用,比如只是簡單地保存日誌或者一些配置,這時我們只需要直接讀寫XML就好,效率第一。 Delphi盒子有一個直接讀寫XML文件(例子和代碼),其核心函數為下面兩個函數(一讀一寫):
{------------------------------------------------- ------------------------------Fun/PRo:GetXMLNodeValue@Date:2004.12.11@Param:xmlFilexml文件@Param:xmlnodepath節點@Param:xmlattrname節點中的屬性名稱,如果直接取節點值則可以忽略此參數。 @Param:dep節點的參數的分隔符,默認為.@Return:第一個節點的值--------------------------- -------------------------------------------------- --}functionGetXMLNodeValue(strEntityEngineFile:String;xmlNodePath:String;constxmlattrname:String='';constdep:Char='.'):String;varxmlDocument:IXMLDocument;node:IXMLNode;xmlnodeList:TStrings;i:Integer;urlcount:Integer ;begin//xml節點路徑xmlnodeList:=TStringList.Create;xmlnodeList.Delimiter:=dep;xmlnodeList.DelimitedText:=xmlnodepath;urlcount:=xmlnodeList.Count;//xml對象xmlDocument:=TXMLDocument.Create(nil);xmlDocument .LoadFromFile(strEntityEngineFile);xmlDocument.Active:=true;trynode:=xmlDocument.DocumentElement;if(node.NodeName=xmlnodeList[0])thenbegin//掃描節點fori:=1tourlcount-1dobeginif(node<>nil)thennode: =getnodefromIXMLNodeList(node.ChildNodes,xmlnodeList[i])elseBreak;end;if(node=nil)thenbeginresult:='';endelsebegin//判斷是取屬性還是取節點內容if(Trim(xmlattrname)='')thenresult :=node.Textelseresult:=node.AttributeNodes.Nodes[xmlattrname].NodeValue;end;endelsebeginresult:='';end;exceptresult:='error';end;xmlDocument.Active:=false;end;{--- -------------------------------------------------- --------------------------Fun/Pro:SetXMLNodeValue@Date:2004.12.11@Param:xmlFilexml文件@Param:xmlnodepath節點@Param: xmlattrname節點中的屬性名稱,如果直接取節點值則可以忽略此參數。 @Param:dep節點的參數的分隔符,默認為.@Return:操作成功否------------------------------ -------------------------------------------------} functionsetXmlNodeValue(strEntityEngineFile:String;xmlNodePath:String;constxmlattrname:String='';constvalue:String='';constdep:Char='.'):boolean;varxmlDocument:IXMLDocument;node:IXMLNode;xmlnodeList:TStrings;i:Integer ;urlcount:Integer;begin//xml節點路徑xmlnodeList:=TStringList.Create;xmlnodeList.Delimiter:=dep;xmlnodeList.DelimitedText:=xmlnodepath;urlcount:=xmlnodeList.Count;//xml對象xmlDocument:=TXMLDocument.Create( nil);xmlDocument.LoadFromFile(strEntityEngineFile);xmlDocument.Active:=true;trynode:=xmlDocument.DocumentElement;if(node.NodeName=xmlnodeList[0])thenbegin//掃描節點fori:=1tourlcount-1dobeginif(node<> nil)thennode:=getnodefromIXMLNodeList(node.ChildNodes,xmlnodeList[i])elseBreak;end;if(node<>nil)thenbeginif(Trim(xmlattrname)='')thennode.Text:=valueelsenode.AttributeNodes.Nodes[xmlattrname] .NodeValue:=value;xmlDocument.SaveToFile(strEntityEngineFile);end;end;result:=true;exceptresult:=false;end;xmlDocument.Active:=false;end;但是上述兩個函數有一個問題:它只能按節點名和屬性名查找第一條記錄。舉例:如果要操作類似下述XML文件,節點和屬性名相同的有多個,只是屬性的值不一樣,上面的讀寫函數就罷工了。
<colourname=normalattributered=100green=125blue=150/><colourname=goodattributered=150green=175blue=200/><colourname=Excellentattributered=0green=0blue=255/>OK,程序員的最大樂趣就是自己動手了。我們來改造一下這兩個函數。在原有函數的基礎上增加了兩個參數:
{------------------------------------------------- ------------------------------Fun/Pro:GetXMLNodeSpecialValue@Date:2004.12.11@Param:xmlFilexml文件@Param:xmlnodepath節點@Param:xmlattrname節點中的屬性名稱,如果直接取節點值則可以忽略此參數。 @Param:XMLSpecialName要查找的節點中屬性名@Param:XMLSpecialValue要查找的節點中某屬性對應的值@Param:dep節點的參數的分隔符,默認為.@Return:某屬性的值---- -------------------------------------------------- -------------------------}functionGetXMLNodeSpecialValue(strEntityEngineFile:String;XMLNodePath:String;constXMLAttrName:String='';constXMLSpecialName:String=''; constXMLSpecialValue:String='';constdep:Char='.'):String;varxmlDocument:IXMLDocument;node:IXMLNode;xmlnodeList:TStrings;i:Integer;urlcount:Integer;begin//xml節點路徑xmlnodeList:=TStringList.Create ;xmlnodeList.Delimiter:=dep;xmlnodeList.DelimitedText:=xmlnodepath;urlcount:=xmlnodeList.Count;//xml對象xmlDocument:=TXMLDocument.Create(nil);xmlDocument.LoadFromFile(strEntityEngineFile);xmlDocument.Active:=true; trynode:=xmlDocument.DocumentElement;if(node.NodeName=xmlnodeList[0])thenbegin//掃描節點fori:=1tourlcount-1dobeginif(node<>nil)thenbeginnode:=getnodefromIXMLNodeList(node.ChildNodes,xmlnodeList[i]); endelseBreak;end;if(node=nil)thenbeginresult:='';endelsebegin//判斷是取屬性還是取節點內容if(Trim(xmlattrname)='')thenresult:=node.Textelsebeginresult:=node.AttributeNodes.Nodes [XMLSpecialName].NodeValue;//這裡不想再聲明一個臨時變量了,就用result來比較,可能有隱患。 while((result<>XMLSpecialValue))dobeginnode:=node.NextSibling;while(node.NodeName='#comment')dobeginnode:=node.NextSibling;end;result:=node.AttributeNodes.Nodes[XMLSpecialName].NodeValue; end;result:=node.AttributeNodes.Nodes[XMLAttrName].NodeValue;end;end;endelsebeginresult:='';end;exceptresult:='error';end;xmlDocument.Active:=false;end;寫函數
{------------------------------------------------- ------------------------------Fun/Pro:SetXMLNodeSpecialValue@Date:2004.12.11@Param:xmlFilexml文件@Param:xmlnodepath節點@Param:xmlattrname節點中的屬性名稱,如果直接取節點值則可以忽略此參數。 @Param:XMLSpecialName要查找的節點中屬性名@Param:XMLSpecialValue要查找的節點中某屬性對應的值@Param:dep節點的參數的分隔符,默認為.@Return:操作成功與否---- -------------------------------------------------- -------------------------}functionSetXMLNodeSpecialValue(strEntityEngineFile:String;xmlNodePath:String;constxmlattrname:String='';constvalue:String=''; constXMLSpecialName:String='';constXMLSpecialValue:String='';constdep:Char='.'):boolean;varxmlDocument:IXMLDocument;node:IXMLNode;xmlnodeList:TStrings;i:Integer;urlcount:Integer;CMPValue:String;begin //xml節點路徑xmlnodeList:=TStringList.Create;xmlnodeList.Delimiter:=dep;xmlnodeList.DelimitedText:=xmlnodepath;urlcount:=xmlnodeList.Count;//xml對象xmlDocument:=TXMLDocument.Create(nil);xmlDocument.LoadFromFile (strEntityEngineFile);xmlDocument.Active:=true;trynode:=xmlDocument.DocumentElement;if(node.NodeName=xmlnodeList[0])thenbegin//掃描節點fori:=1tourlcount-1dobeginif(node<>nil)thennode:=getnodefromIXMLNodeList (node.ChildNodes,xmlnodeList[i])elseBreak;end;if(node<>nil)thenbegin{if(Trim(xmlattrname)='')thennode.Text:=valueelsenode.AttributeNodes.Nodes[xmlattrname].NodeValue:= value;}if(Trim(XMLAttrName)='')thennode.Text:=valueelsebeginCMPValue:=node.AttributeNodes.Nodes[XMLSpecialName].NodeValue;while(CMPValue<>XMLSpecialValue)dobeginnode:=node.NextSibling;while(node. NodeName='#comment')dobeginnode:=node.NextSibling;end;CMPValue:=node.AttributeNodes.Nodes[XMLSpecialName].NodeValue;end;node.AttributeNodes.Nodes[XMLAttrName].NodeValue:=value;end;xmlDocument. SaveToFile(strEntityEngineFile);end;end;result:=true;exceptresult:=false;end;xmlDocument.Active:=false;end;