How to parse XML in 3 different ways using kbmMW Pro, Enterprise and Community Edition.
This is a post based on a public question on the NLDelphi.com forums.
Having the following XML, how do can it be parsed?
const XML: string = '<?xml version="1.0"?>'+ '<DefaultBody>'+ '<Default>'+ ' <Defaultcode>XML_BOLIMPORT_MAP</Defaultcode>'+ ' <Omschrijving>Folder waar de xml bestanden staan, die gemaakt zijn door bolmate vanuit de inkoop</Omschrijving>'+ ' <Waarde>Z:\tmp</Waarde>'+ '</Default>'+ '<Default>'+ ' <Defaultcode>XML_DESTUSED_MAP</Defaultcode>'+ ' <Omschrijving>XMLBestanden die verplaatst worden als ze klaar zijn</Omschrijving>'+ ' <Waarde>Z:\tmp\xmlexport</Waarde>'+ '</Default>'+ '</DefaultBody>';
Into a list of TDef objects:
type TDef = class public Defaultcode:string; Omschrijving:string; Waarde:string; end; TDefs = class(TObjectList<TDef>);
Contents
Method 1 – Basic XML parsing
We use the standard kbmMW DOM parser.
using kbmMWXML; ... function ParseXML1(const AString:string):TDefs; var xml:TkbmMWDOMXML; i:integer; data,node,child:TkbmMWDOMXMLNode; def:TDef; begin Result:=TDefs.Create; xml:=TkbmMWDOMXML.Create(AString); try data:=xml.Top; // Will usually be DefaultBody node for i:=0 to data.Nodes.Count-1 do begin node:=data.Nodes[i]; if node.Name='Default' then begin def:=TDef.Create; child:=node.ChildByName['Defaultcode']; if child<>nil then def.DefaultCode:=child.GetAsString; child:=node.ChildByName['Omschrijving']; if child<>nil then def.Omschrijving:=child.GetAsString; child:=node.ChildByName['Waarde']; if child<>nil then def.Waarde:=child.GetAsString; Result.Add(def); end; end; finally xml.Free; end; end;
Method 2 – Using object notation
Notice there are many more dynamic ways to access the data using object notations than just this example.
uses kbmMWXML, kbmMWObjectNotation; ... function ParseXML2(const AString:string):TDefs; var xml:TkbmMWDOMXML; co:TkbmMWONCustomObject; o:TkbmMWONObject; def:TDef; begin Result:=TDefs.Create; xml:=TkbmMWDOMXML.Create(AString); try def:=TDef.Create; co:=xml.SaveToObjectNotation; def.DefaultCode:=TkbmMWONNative(co.Path('DefaultBody/Default/0/Defaultcode',[mwonpoLastIsValue],'/',mwontString)).AsString; def.Omschrijving:=TkbmMWONNative(co.Path('DefaultBody/Default/0/Omschrijving',[mwonpoLastIsValue],'/',mwontString)).AsString; def.Waarde:=TkbmMWONNative(co.Path('DefaultBody/Default/0/Waarde',[mwonpoLastIsValue],'/',mwontString)).AsString; Result.Add(def); def:=TDef.Create; def.DefaultCode:=TkbmMWONNative(co.Path('DefaultBody/Default/1/Defaultcode',[mwonpoLastIsValue],'/',mwontString)).AsString; def.Omschrijving:=TkbmMWONNative(co.Path('DefaultBody/Default/1/Omschrijving',[mwonpoLastIsValue],'/',mwontString)).AsString; def.Waarde:=TkbmMWONNative(co.Path('DefaultBody/Default/1/Waarde',[mwonpoLastIsValue],'/',mwontString)).AsString; Result.Add(def); finally co.Free; xml.Free; end; end;
Method 3 – Using object marshalling
This is by far the easiest way to parse the data, and also makes it very easy to generate XML from the objects again.
Notice that the TDef and TDefs class definitions has been augmented with a couple of attributes.
uses Generics.Collections, kbmMWObjectMarshal, kbmMWXMLMarshal, kbmMWRTTI; type [kbmMW_Root('Default',[mwrfIncludePublic])] TDef = class public Defaultcode:string; Omschrijving:string; Waarde:string; end; [kbmMW_Root('DefaultBody')] [kbmMW_Child('Default')] TDefs = class(TObjectList<TDef>); ... function ParseXML3(const AString:string):TDefs; var xml:TkbmMWXMLMarshal; begin xml:=TkbmMWXMLMarshal.Create; try Result:=xml.FromString<TDefs>(AString); finally xml.Free; end; end; ... initialization kbmMWRegisterKnownClasses([TDef,TDefs]);