WikiCommons

kbmMW Pro, Enterprise and Community Edition has extensive support for LINQ like functionality, which can also work on not only XML data, but also data provided in all the other serialization formats (YAML, JSON, BSON, CSV, MessagePack) kbmMW supports.

What is kbmMW’s LINQ? You can read much more about it here and here.

LINQ is also an additional way to parse XML or one of the other serialization formats supported. In fact, behind the scenes, it all boils down to the traditional kbmMW streamers, but LINQ provides a different interface to them.

So we again start out with the same XML sample data as the previous XML parsing “Did you know… XML…” posts.

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>';

And we still want it parsed into a list of TDef objects. To make TDef “Linq’able” we prefix it with the kbmMW_Linq attribute:

type
   [kbmMW_Linq]
   TDef = class
   public
      Defaultcode:string;
      Omschrijving:string;
      Waarde:string;
   end;

Then let us look at the single line of code needed to convert the XML to TDef instances:

var
   defs:TObjectList<TDef>;
begin
     defs:=Linq.UsingXML(XML,'^/DefaultBody/Default/$').AsGeneric.List<TDef>;
...
end;

What happens here, is we tell LINQ to base it’s operation on XML. The XML is walked, node by node, to determine which nodes are subject for including as the subset of data that LINQ should work on.

In our case we filter the node path using a regular expression (^/DefaultBody/Default/$) which basically states, that only child nodes of nodes having the absolute path /DefaultBody/Default is included in the LINQ data subset.

We could have stated exactly which subnodes (fields) we are interested in, by adding an additional argument to UsingXML, but in this case, we have not provided it, letting LINQ figure it out.

The LINQ data could then be sorted, or additionally worked on by the other LINQ features, but for this demo, we just want a generic list of TDef retuned.

The result is an TObjectList<TDef> containing two TDef objects, each populated with the expected values from the XML.

To complete the code, we do need to include required units in the uses section:

uses
...
  Generics.Collections,
  kbmMWORM,
  kbmMWLinq,
  kbmMWRTTI;

And we must register TDef and TObjectList<TDef> as classes kbmMW should be able to marshal. This is typically done in the unit’s intiialization section.

initialization
  TkbmMWRTTI.EnableRTTI([TDef,TObjectList<TDef>]);
  kbmMWRegisterKnownClasses([TDef,TObjectList<TDef>]);

end.

 


Loading

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.