Topic: Extract Elements from XML

Hello.

I have an XML file comprising:

<?xmlversion="1.0"encoding="UTF-8"?>
<DistanceMatrixResponse>
<status>OK</status>
<origin_address>London,UK</origin_address>
<destination_address>Hastings,UK</destination_address>
<row>
<element>
<status>OK</status>
<duration>
<value>7471</value>
<text>2hours5mins</text>
</duration>
<distance>
<value>122507</value>
<text>123km</text>
</distance>
</element>
</row>
</DistanceMatrixResponse>

It's actually one long line of XML. It seems as though this forum editor has inserted the CRLFs.

I'm drawing a blank on how to extract the time (2hours5minutes) and distance (123km) elements. Does MVD have an XML parser?
Thanks

Re: Extract Elements from XML

Hello.


In the current version there is no XML parser.


But you can load the xml file to object TStringList and using string function like PosEx, Copy, Delete to find all elements.

var
  sl: TStringList;
begin
  sl := TStringList.Create;
  sl.LoadFromFile(''xmlfilename);
  sl.text; // contain xml doc as text
Dmitry.

Re: Extract Elements from XML

Thanks for the suggestion, Dmitry.

However, I don't think my version of MVD (2.7) has the PosEx function.

It's not as robust as I'd like, but I was able to implement it this way. sResponse contains the contents of the XML file.

begin
    int1 := Pos('<text>',sResponse);
    int2 := Pos('</text>',sResponse);
    sTime := Copy(sResponse,int1+6,int2-(int1+6));
    sResponseCopy := Copy(sResponse,int2+6,Length(sResponse)-(int2+6));
    int3 := Pos('<text>',sResponseCopy);
    int4 := Pos('</text>',sResponseCopy);
    sDistance := Copy(sResponseCopy,int3+6,int4-(int3+6));
    MessageDlg('The distance between ' + Splash.Edit1.Text + ' and ' + Splash.Edit2.Text + ' is ' + sDistance +'.'+#10#10+'It will take ' + sTime + ' to get there.',mtInformation,mbOK,2);
end;

Re: Extract Elements from XML

Please download latest beta version 2.8 where I have added PosEx function.


Also I made an example for you:

procedure Form1_Button1_OnClick (Sender: string; var Cancel: boolean);
var
    sl: TStringList;
    s, sRow, sDuration, sDistance: string;
    iPos1, iPos2, iOffset: integer;
begin
     sl := TStringList.Create;
     sl.LoadFromFile('file.xml');

     iOffset := 1;
     iPos1 := 1;
     while true do
     begin
         iPos1 := PosEx('<row>', sl.Text, iOffset);
         if iPos1=0 then break;

         iPos2 := PosEx('</row>', sl.Text, iOffset);
         iOffset := iPos2+1;

         sRow := Copy(sl.Text, iPos1, iPos2-iPos1);

         sDuration := Copy(sRow,  Pos('<duration>', sRow),  Pos('</duration>', sRow)-Pos('<duration>', sRow) );
         sDistance := Copy(sRow,  Pos('<distance>', sRow),  Pos('</distance>', sRow)-Pos('<distance>', sRow) );


         s := Copy(sDuration, Pos('<text>', sDuration)+Length('<text>') , Pos('</text>', sDuration)-Pos('<text>', sDuration)-Length('<text>'));
         Form1.Memo1.Lines.Add(s);

         s := Copy(sDistance, Pos('<text>', sDistance)+Length('<text>') , Pos('</text>', sDistance)-Pos('<text>', sDistance)-Length('<text>'));
         Form1.Memo1.Lines.Add(s);
     end;    


     sl.Free;
end;


Project with the example:

Post's attachments

Attachment icon Parse XML.zip 5.04 kb, 556 downloads since 2016-11-08 

Dmitry.

Re: Extract Elements from XML

DriveSoft wrote:

Please download latest beta version 2.8 where I have added PosEx function.


Also I made an example for you:

procedure Form1_Button1_OnClick (Sender: string; var Cancel: boolean);
var
    sl: TStringList;
    s, sRow, sDuration, sDistance: string;
    iPos1, iPos2, iOffset: integer;
begin
     sl := TStringList.Create;
     sl.LoadFromFile('file.xml');

     iOffset := 1;
     iPos1 := 1;
     while true do
     begin
         iPos1 := PosEx('<row>', sl.Text, iOffset);
         if iPos1=0 then break;

         iPos2 := PosEx('</row>', sl.Text, iOffset);
         iOffset := iPos2+1;

         sRow := Copy(sl.Text, iPos1, iPos2-iPos1);

         sDuration := Copy(sRow,  Pos('<duration>', sRow),  Pos('</duration>', sRow)-Pos('<duration>', sRow) );
         sDistance := Copy(sRow,  Pos('<distance>', sRow),  Pos('</distance>', sRow)-Pos('<distance>', sRow) );


         s := Copy(sDuration, Pos('<text>', sDuration)+Length('<text>') , Pos('</text>', sDuration)-Pos('<text>', sDuration)-Length('<text>'));
         Form1.Memo1.Lines.Add(s);

         s := Copy(sDistance, Pos('<text>', sDistance)+Length('<text>') , Pos('</text>', sDistance)-Pos('<text>', sDistance)-Length('<text>'));
         Form1.Memo1.Lines.Add(s);
     end;    


     sl.Free;
end;


Project with the example:

Can you give the link to version 2.8?

Re: Extract Elements from XML

https://www.dropbox.com/s/k1wd8mqe3qb35 … a.zip?dl=0

Dmitry.

Re: Extract Elements from XML

@Dmitry - Many thanks for the link to 2.8 and the example code. Unfortunately, the XML is the response from an HTTP GET request - not a file I can load using LoadFromFile(<filename>). I could use the PosEx though. Which leads me to a question. When does 2.8 come out of Beta. I'm wondering about using the beta just to obtain the PosEx function smile.


@bemorhona-qt - Also many thanks for your code example.

Re: Extract Elements from XML

clyde wrote:

@Dmitry - Many thanks for the link to 2.8 and the example code. Unfortunately, the XML is the response from an HTTP GET request - not a file I can load using LoadFromFile(<filename>). I could use the PosEx though. Which leads me to a question. When does 2.8 come out of Beta. I'm wondering about using the beta just to obtain the PosEx function smile.



Example using HTTPGet('http://site.com/file.xml');

procedure Form1_Button1_OnClick (Sender: string; var Cancel: boolean);
var
    sXML: string;
    s, sRow, sDuration, sDistance: string;
    iPos1, iPos2, iOffset: integer;
begin
     sXML := HTTPGet('http://site.com/file.xml');

     iOffset := 1;
     iPos1 := 1;
     while true do
     begin
         iPos1 := PosEx('<row>', sXML, iOffset);
         if iPos1=0 then break;

         iPos2 := PosEx('</row>', sXML, iOffset);
         iOffset := iPos2+1;

         sRow := Copy(sXML, iPos1, iPos2-iPos1);

         sDuration := Copy(sRow,  Pos('<duration>', sRow),  Pos('</duration>', sRow)-Pos('<duration>', sRow) );
         sDistance := Copy(sRow,  Pos('<distance>', sRow),  Pos('</distance>', sRow)-Pos('<distance>', sRow) );


         s := Copy(sDuration, Pos('<text>', sDuration)+Length('<text>') , Pos('</text>', sDuration)-Pos('<text>', sDuration)-Length('<text>'));
         Form1.Memo1.Lines.Add(s);

         s := Copy(sDistance, Pos('<text>', sDistance)+Length('<text>') , Pos('</text>', sDistance)-Pos('<text>', sDistance)-Length('<text>'));
         Form1.Memo1.Lines.Add(s);
     end;    


end;

Now you can download final version of 2.8

Dmitry.

Re: Extract Elements from XML

@Dmitry - Many thanks. Downloaded. smile