dfm文件是Delphi中存储窗体控件信息的,有时为了对大批量的dfm文件操作(如:批量替换控件、作检查等),往往不是太方便。
XML对结构化的数据读写则很强,将文本类型的dfm转为xml后进行操作,再转回dfm存储大大方便了操作。
//DFM to XMLprocedure Dfm2Xml(ADfmStrings: TStrings; AXml: IDsXmlDocument);Var i: integer; mStr : string; mParentNode, mNode : IDsXMLNode; mObjName, mClass, mObjType: string; mPropName, mPropValue: string; mInItem: Boolean; //有Item的也会有End相对,所以要和Object end分开begin mInItem := False; mParentNode := AXML; for i:=0 to ADfmStrings.Count - 1 do beginmStr := trim(ADfmStrings.Strings[i]);//对象开始if (copy(mStr, 1, 6) = 'object') or (copy(mStr, 1, 9) = 'inherited') thenbegin //先写入属性 - 如果还有属性没有写 if mPropName '' then beginmNode := AXml.createElement(mPropName);mNode.text := mPropValue;mParentNode.appendChild(mNode);mPropName := ''; end; mObjType := CutToken(mStr, ' '); //Type: object or inherited mObjName := CutToken(mStr, ': '); //ObjName: Ex. frmCmsI03 mClass := mStr;//ClassName: Ex. TButton mNode := AXml.createElement(mObjName); (mNode as IDsXmlElement).setAttribute('ObjType', mObjType); (mNode as IDsXmlElement).setAttribute('Class', mClass); mParentNode.appendChild(mNode); mParentNode := mNode;end//对象结束else if (mStr = 'end') and (not mInItem) thenbegin //先写入属性 if mPropName '' then beginmNode := AXml.createElement(mPropName);mNode.text := mPropValue;mParentNode.appendChild(mNode);mPropName := ''; end; mParentNode := mParentNode.parentNode;end//属性处理elsebegin //有 = 说明是一个属性的新的开始 if (Pos(' = ', mStr) 0) and (not mInItem) then begin//先写入属性if mPropName '' thenbegin mNode := AXml.createElement(mPropName); mNode.text := mPropValue; mParentNode.appendChild(mNode);end;mPropName := CutToken(mStr, ' = ');mPropValue := CutToken(mStr, ' = '); end else //说明这个属性可能有多行mPropValue := mPropValue + '#13#10' + mStr;if mStr = 'item' then mInItem := True;if mStr = 'end' then mInItem := False;end; end;end;//XML to DFMprocedure Xml2Dfm(AXml: IDsXmlDocument; ADfmStrings: TStrings); procedure Node2Dfm(ANode: IDsXMLNode; oString: TStrings; IdentSpace: string); VarmObjName, mClass, mObjType: string;mPropName, mPropValue: string;mNode : IDsXMLNode;i: integer;mVar : Variant; beginmObjName := (ANode as IDsXmlElement).NodeName;mClass := (ANode as IDsXmlElement).getAttribute('Class');mObjType := (ANode as IDsXmlElement).getAttribute('ObjType');//写入Object beginoString.Add(Format('%s%s %s: %s', [IdentSpace, mObjType, mObjName, mClass]));//写入属性for i:= 0 to ANode.childNodes.length - 1 dobegin mNode := ANode.childNodes.item[i]; //Has Child 说明是一个新的对象 mVar := (mNode as IDsXmlElement).getAttribute('ObjType'); if not varIsNull(mVar) thenNode2Dfm(mNode, oString, IdentSpace + ' ') //是属性,写进去就好了. else beginmPropName := mNode.nodeName;mPropValue := mNode.text;mPropValue := StringReplace(mPropValue, '#13#10', #13#10, [rfReplaceAll]);//写入:缩进oString.Add(Format('%s%s = %s', [IdentSpace+' ', mPropName, mPropValue])); end;end;//写入EndoString.Add(Format('%send', [IdentSpace])); end; begin Node2Dfm(AXml.Get_documentElement, ADfmStrings, '');end;
用到的类型:
(本文来源于图老师网站,更多请访问https://m.tulaoshi.com/bianchengyuyan/)uses MSXML2_TLB;//类型自己重新定义过type IDsXmlDocument = IXMLDOMDocument2; IDsXmlNode = IXMLDOMNode; IDsXmlElement = IXMLDOMElement; IDsXmlNodeList = IXMLDOMNodeList;