有时,只需要用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;