FINALLY ITS EASY TO CREATE AND READ XML...

5
43 Issue Nr 3 2015 BLAISE PASCAL MAGAZINE GENERATE DELPHI SUPPORT FOR READING AND WRITING XML FILES PAGE 1 - THAT ADHERE TO THE GOOGLE MERCHANTS RATING DATA SPECIFICATIONS First a little bit about the XSD schema converter. Its delivered as a demo application (that is full featured in what it does), but which can be tailored if required to any developers need. Its main internal components, are a TkbmMWXSDParser class (with a number of assistant classes), a TkbmMWXSDPascalCodeGen class (descending from TkbmMWXSDCustomCodeGen) and of course the TkbmMWDOMXML class for speedy and complete handling of the XML, in which XSD files are written. As can be seen, it’s actually possible to utilize the parse tree generated by the XSD parser to output other types documents by First download the XSD from Google here: https://developers.google.com/ merchant-review-feeds/schema Next one have to compile (if not already done) and run the kbmMW ConvertXSD.exe application. Now click Convert XSD file, and select the downloaded merchant_reviews.xsd file. A split second later, the file has been read, validated and a merchant_reviews.pas file has been generated in the same directory. In the right pane, it’s possible to see which classes kbmMW's XSD converter have found. And in the left pane, any warnings or errors would have been listed. This article is actually less about how Google Merchants ratings work, and more about the principle of utilizing kbmMW to convert XSD (XML schema documents) to easily streamable Delphi objects. kbmMW Enterprise Edition includes a complete XSD schema converter, which takes an xsd file as input and outputs readily compilable Pascal objects, that are very easy to read, alter and stream to and from XML and JSON. Delphi expert starter inheriting from the TkbmMWXSDCustomCodeGen. That's however out of scope for this article. I’ve done some comparisons with the built in XSD importer tool in Delphi, and find that the kbmMW ConvertXSD tool is better and more accurate in converting XSD documents, and easily converts XSD documents not possible using Embarcaderos XSD inporter. The outset for this article is to generate Delphi support for reading and writing XML files that adhere to the Google merchants rating data specifications. BY KIM MADSEN FINALLY ITS EASY TO CREATE AND READ XML FILES

Transcript of FINALLY ITS EASY TO CREATE AND READ XML...

43Issue Nr 3 2015 BLAISE PASCAL MAGAZINE

GENERATE DELPHI SUPPORT FOR READING AND WRITING XML FILES PAGE 1 - THAT ADHERE TO THE GOOGLE MERCHANTS RATING DATA SPECIFICATIONS

First a little bit about the XSD schema converter. Its delivered as a demo application (that is full featured in what it does), but which can be tailored if required to any developers need. Its main internal components, are a TkbmMWXSDParser class (with

a number of assistant classes), a TkbmMWXSDPascalCodeGen

class (descending from TkbmMWXSDCustomCodeGen)

and of course the TkbmMWDOMXML

class for speedy and complete handling of the XML, in which XSD files are written. As can be seen, it’s actually possible to utilize the parse tree generated by the XSD parser to output other types documents by

First download the XSD from Google here:https://developers.google.com/merchant-review-feeds/schema

Next one have to compile (if not already done) and run the kbmMW ConvertXSD.exe application.

Now click Convert XSD file, and select the downloaded merchant_reviews.xsd file. A split second later, the file has been read, validated and a merchant_reviews.pas file has been generated in the same directory.

In the right pane, it’s possible to see which classes kbmMW's XSD converter have found. And in the left pane, any warnings or errors would have been listed.

This article is actually less about how Google Merchants ratings work, and more about the principle of utilizing kbmMW to convert XSD (XML schema documents) to easily streamable Delphi objects.kbmMW Enterprise Edition includes a complete XSD schema converter, which takes an xsd file as input and outputs readily compilable Pascal objects, that are very easy to read, alter and stream to and from XML and JSON.

Delphi

expertstarter

inheriting from the TkbmMWXSDCustomCodeGen.

That's however out of scope for this article.I’ve done some comparisons with the built in XSD importer tool in Delphi, and find that the kbmMW

ConvertXSD tool is better and more accurate in converting XSD documents, and easily converts XSD documents not possible using Embarcaderos XSD inporter.The outset for this article is to generate Delphi support for reading and writing XML files that adhere to the Google merchants rating data specifications.

BY KIM MADSEN

FINALLY ITS EASY TO CREATE AND READ

XML FILES

Issue Nr 3 2015 BLAISE PASCAL MAGAZINE44

The converted file looks like this (snippets only shown):unit ;merchant_reviews

// ==========================================================================// Generated by kbmMW XSD Converter// 5/11/2015 01:08:59// Based on: C:\svn_c4d\kbmmw\trunk\ConvertXSD\GoogleMerchantFeedback\merchant_reviews.xsd// ==========================================================================

// Log:// Converted without errors or warnings.

type

(*$HPPEMIT 'namespace Merchant_reviews {'*){$SCOPEDENUMS ON} = TLanguageCode( , , , , , , , ,& , , , , , , , , , , , , , , , , , , , , , , , , , , , , ,aa ab ae af ak am an ar av ay az ba be bg bh bi bm bn bo br bs ca ce ch co cr cs cu cv cy da de dv dz ee el enas, , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , ,& , , , ,eo es et eu fa ff fi fj fo fr fy ga gd gl gn gu gv ha he hi ho hr ht hu hy hz ia id ie ig ii ik io it iu ja jvis, , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , ,ka kg ki kj kk kl km kn ko kr ks ku kv kw ky la lb lg li ln lo lt lu lv mg mh mi mk ml mn mr ms mt my na nb nd neng nl nn no nr nv ny oc oj om os pa pi pl ps pt qu rm rn ro ru rw sa sc sd se sg si sk sl sm sn so sq sr ss st, , , , , , , , , ,& , , , , , , , , , , , , , , , , , , , , , , , , , , , ,orsu sv sw ta te tg th ti tk tl tn tr ts tt tw ty ug uk ur uz ve vi vo wa wo xh yi yo za zh zu, , , , , , , , , , ,& , , , , , , , , , , , , , , , , , , , , );to =TCountryCode

… = ( , );Ttype_1 singleton group = < >;TNonEmptyString kbmMWNullable string = ( , );Ttype summary detail = ( , , );Treviewer_type user editorial aggregator = ( , , );Tcollection_method unsolicited point_of_sale after_fulfillment

const : [ ] = CLanguageCode TLanguageCodearray of string( , , , , , , , , , , , , , , , , , , , , , ,'aa' 'ab' 'ae' 'af' 'ak' 'am' 'an' 'ar' 'as' 'av' 'ay' 'az' 'ba' 'be' 'bg' 'bh' 'bi' 'bm' 'bn' 'bo' 'br' 'bs' 'ca', , , , , , , , , , , , , , , , , , , , , , ,'ce' 'ch' 'co' 'cr' 'cs' 'cu' 'cv' 'cy' 'da' 'de' 'dv' 'dz' 'ee' 'el' 'en' 'eo' 'es' 'et' 'eu' 'fa' 'ff' 'fi' 'fj', , , , , , , , , , , , , , , , , , , , , , ,'fo' 'fr' 'fy' 'ga' 'gd' 'gl' 'gn' 'gu' 'gv' 'ha' 'he' 'hi' 'ho' 'hr' 'ht' 'hu' 'hy' 'hz' 'ia' 'id' 'ie' 'ig' 'ii', , , , , , , , , , , , , , , , , , , , , , ,'ik' 'io' 'is' 'it' 'iu' 'ja' 'jv' 'ka' 'kg' 'ki' 'kj' 'kk' 'kl' 'km' 'kn' 'ko' 'kr' 'ks' 'ku' 'kv' 'kw' 'ky' 'la', , , , , , , , , , , , , , , , , , , , , , ,'lb' 'lg' 'li' 'ln' 'lo' 'lt' 'lu' 'lv' 'mg' 'mh' 'mi' 'mk' 'ml' 'mn' 'mr' 'ms' 'mt' 'my' 'na' 'nb' 'nd' 'ne' 'ng', , , , , , , , , , , , , , , , , , , , , , ,'nl' 'nn' 'no' 'nr' 'nv' 'ny' 'oc' 'oj' 'om' 'or' 'os' 'pa' 'pi' 'pl' 'ps' 'pt' 'qu' 'rm' 'rn' 'ro' 'ru' 'rw' 'sa', , , , , , , , , , , , , , , , , , , , , , ,'sc' 'sd' 'se' 'sg' 'si' 'sk' 'sl' 'sm' 'sn' 'so' 'sq' 'sr' 'ss' 'st' 'su' 'sv' 'sw' 'ta' 'te' 'tg' 'th' 'ti' 'tk', , , , , , , , , , , , , , , , , , , , , , ,'tl' 'tn' 'to' 'tr' 'ts' 'tt' 'tw' 'ty' 'ug' 'uk' 'ur' 'uz' 've' 'vi' 'vo' 'wa' 'wo' 'xh' 'yi' 'yo' 'za' 'zh' 'zu'); : [ ] =CCountryCode TCountryCodearray of string… : [ ] = ( , );Ctype_1 Ttype_1array of string 'singleton' 'group' : [ ] = ( , );Ctype Ttypearray of string 'summary' 'detail' : [ ] = ( , , );Creviewer_type Treviewer_typearray of string 'user' 'editorial' 'aggregator' : [ ] = ( , , );Ccollection_method Tcollection_methodarray of string 'unsolicited' 'point_of_sale' 'after_fulfillment'

[ ( ,[ ])]kbmMW_Root mwrfIncludeOnlyTagged'Review'

When one is creating a project that needs

to read or write XML files that adhere to

the Google merchants ratings XSD, one

simply need to include this file in the uses

clause, and then use kbmMW's

serialization and deserialization methods

to convert XML or JSON to objects or

objects to XML or JSON.

At

https://developers.google.com/merchant-review-feeds/sample

there is a sample XML file provided by

Google, which we will use to see that we

can convert the XML to objects.

A new VCL application is created (it could

be a Firemonkey application too, kbmMW

works in both environments).

GENERATE DELPHI SUPPORT FOR READING AND WRITING XML FILES PAGE 2

45Issue Nr 3 2015 BLAISE PASCAL MAGAZINE

procedure . ( : );TForm1 btnSaveClick Sender TObject

var xmlm TkbmMWXMLMarshal xml TkbmMWDOMXML: ; : ;begin = ;if nil then FFeed exit

:= . ;xmlm TkbmMWXMLMarshal Create try . := ;xmlm Typed false

:= . ( );xml xmlm ValueToDOMXML FFeed

= if nil thenxml begin . . ( );Memo1 Lines Add 'xml=null'

;exit

;end finally . ;xmlm Free

;end

. := ;xml Typed false

. := ;xml AutoIndent true

. := ;xml AutoLineFeed true

. ;xml Update

. ( );xml SaveToFile 'newfeed.xml'

. ;xml Free

end;

In its uses clause we add the generated

merchant_review unit:

procedure . ( : );TForm1 btnLoadClick Sender TObjectvar : ; : ;xmlm TkbmMWXMLMarshal xml TkbmMWDOMXML

: ; : ; : ;m TMerchant r TReview d TNonEmptyStringbegin := . ;xml TkbmMWDOMXML Create try . ( );xml LoadFromFile 'merchant_reviews.xml'

:= . ;xmlm TkbmMWXMLMarshal Create

:= ( . ( , ));try FFeed TFeed xmlm ValueFromDOMXML TFeed xml

… Use the FFeed what you want .object for . ;finally xmlm Free

;end finally . ;xml Free

;end

Notice the optional use of .ValueOr[…]. The reason

is that for example reviewer_id is a nullable

value. kbmMW understands the difference between for

example a null string value and an empty string.

Similarly kbmMW understands nullable

integers, singles, doubles, Booleans,

dates, times, date/times etc.

Also notice the access of the review_date

property. We want to display it as an ISO8601

formatted string in this case, but we could also have

asked it to be shown as a RFC1123 formattet string

instead or as a local date/time or as a GMT

date/time.

uses . , . , . , . , . ,Winapi WinapiWindows Messages System SysUtils System Variants System Classes

. , . , . , . , . ,Vcl Graphics Vcl Controls Vcl Forms Vcl Dialogs Vcl StdCtrls

;merchant_reviews

procedure . ( : );TForm1 FormCreate Sender TObjectbegin . ;Tmerchant_reviews RegisterStreamableObjects

end;

Before serializing or deserializing we need to let kbmMW know about the classes that are part of the merchant_reviews unit. This is done in the

OnFormCreate event in this sample:

Now everything is ready for streaming. Lets put

some code in the load XML buttons event handler to

load a Google merchants ratings XML file and have it

accessible via standard Delphi objects:

It’s that simple to convert the XML to true Delphi

objects! Now you can access all fields/attributes

like this:

Memo1 Lines Add r reviewer_id ValueOr. . ( + . . [ ]);'FFeed.merchant.review.reviewer_id=' '<null>'

Memo1 Lines Add Creviewer_type r reviewer_type. . ( + [ . ]);'FFeed.merchant.review.reviewer_type='

Memo1 Lines Add r review_date ISO8601String. . ( + . . );'FFeed.merchant.review.review_date='

Memo1 Lines Add BoolToStr r is_spam ValueOr false. . ( + ( . . [ ]));'FFeed.merchant.review.is_spam='

kbmMW have full support for timezones, and you

can operate the TkbmMWDateTime in much the

same way as you would with a TDateTime.

Ok.. then let us try to serialize the FFeed object

back to XML again potentially after we have made

changes to it, or perhaps even built a new Tfeed

instance from scratch.

It's as simple as that! Now a newfeed.xml file will

have been generated based on the FFeed object.

It will be data wise exact the same as the original xml

file we deserialized, although it may differ in

order or in filtering out empty XML nodes.

What if you would want to send the Ffeed object

instance to a browser, connected to a kbmMW

application server that is acting as a web server?

The browser usually understands Javascript, and

often jQuery is used for sending requests to a

webserver and receiving responses in what is called

an AJAX operation (Async Javascript and XML).

GENERATE DELPHI SUPPORT FOR READING AND WRITING XML FILES PAGE 3

procedure . ( : );TForm1 btnSaveJSONClick Sender TObject

var string jm TkbmMWJSONMarshal s: ; : ;begin = ;if nil then FFeed exit

:= . ;jm TkbmMWJSONMarshal Create try := . ( );s jm ValueToString FFeed

Now the string s contains the JSON data

. ;finally jm Free

;end

end;

The string can be sent directly to the browser as a

response to the browsers GET or POST request,

giving the mimetype application/json.

What makes the serialization/deserialization magic

happen is the combination of attributes given on the

Delphi types, and an advanced and intelligent built in

mechanism that understands the combination of

attributes and the type and relations between the

defined Delphi types that are to be

serialized/deserialized.

kbmMW's serializer is probably one of the most

advanced on the market, and is even

included in the free kbmMW CodeGear Edition.

A Delphi class can be decorated with a

number of attributes that hints to the

serializer/deserializer how it should go

about its operation.

This is a short explanation of the basic forms

of various attributes currently understood

by kbmMW:

As such, the browser typically do support parsing

XML to an extent, potentially via 3rdparty XML

Javascript libraries. However Javascript supports a

native textual object notation, that is more compact

than XML and faster for it to read. JSON is the name

for that notation (Javascript Object Notation).

So a better choice is to serialize the Ffeed object to

JSON and send that JSON stream to the browser.

The browser would see the streamed data as true

Javascript objects upon reception.

In kbmMW it’s simple to serialize to JSON:

[kbmMW_Ignore] Can be placed in front of any field or property to ensure that that particular field/property is not serialized. Eg.

[kbmMW_Ignore] property SomeValue:string read….

[kbmMW_NotNull] Can be placed in front of any field/property to indicate that the field must NOT take the value of NULL (undefined).

If it does, an exception will be raised upon serialization or deserialization.

[kbmMW_Element(..)] Place in front of any field/property to indicate that the value should be serialized as an element (a child node in XML).

Its also possible to specify the name of the child object like this: [kbmMW_Element('someName')]

[kbmMW_Attribute(..)] Similar to the kbmMW_Element, except that it directs that the value must be put in an attribute (in the parent node in

XML). For JSON it will work the same as kbmMW_Element. This attribute also accepts a naming argument.

[kbmMW_Root(..)] Specifies default naming of a class, and what parts of it should automatically be serialized/deserialized like all published

properties, all public properties or only properties/fields tagged with kbmMW_Attribute or kbmMW_Element attributes.

[kbmMW_Null(..)] Indicate that the element can take the value of NULL. Optionally a default value can be provided, which will be used in

case the value in the XML/JSON indicates NULL.

[kbmMW_Validate(…)] Validates a property/field or a complete class instance for its values and raises an exception if a value is out of spec.

A complete expression which can refer to any field in the class can be given. If the expression evaluates to false,

then an exception will be raised upon serialization/deserialization time.

Eg. [kbmMW_Validate('$someName=22')] accepts only the value 22 in the someName field.

Further there are special attributes:

Issue Nr 3 2015 BLAISE PASCAL MAGAZINE46

GENERATE DELPHI SUPPORT FOR READING AND WRITING XML FILES PAGE 4

[kbmMW_ConditionalType(…)] Controls (in combination with [kbmMW_Root]l) serialization and deserialization

of colletions containing different types of child objects within the same

collection.[kbmMW_Dataset(..)]

[kbmMW_Dataset(..)] Controls serialization/deserialization of fields/properties that are of type

[kbmMW_DatasetRow(..)] TkbmCustomMemTable or descendants.

[kbmMW_DatasetField(..)]

[kbmMW_DatasetVersion(..)]

[kbmMW_DatasetDefinition(..)]

[kbmMW_DatasetData(..)]

Finally it’s possible to register custom

serialization/deserialization code for handling

special serialization/deserialization requirements.

It already comes with such for handling

kbmMWNullable<..> types, TkbmMWDateTime

types, TStream types/descendants and

TkbmCustomMemtable descendants.

I hope this has given an appetizer for how versatile

the kbmMW object serialization/deserialization

framework is.

As an example of a fairly complex XSD that kbmMW

effortless converts and serializes/deserializes

accordingly to, but that even Delphi XE8 fails

converting, is the Personal Health Record XSD

found here:

http://www.recordsforliving.com/

Schemas/2006-04/PHR-

Model/R4L_PHRModel.xsd

You can find sample data here: http://www.recordsforliving.com/PersonalHealthRecords/SamplePHRs.aspx

As kbmMW is a modular framework, one can choose

only to use its XML capabilities, its JSON capabilities,

its serialization capabilities, its application server

capabilities, its database capabilities, its stream

storage capabilities, its memory table or its async

messaging capabilities etc without having to use all

other parts of the kbmMW framework.

But obviously, you will get the best of the best if

you take the plunge and choose to take advantage

of all the kbmMW features you need in your

applications as all parts are designed to work in

perfect harmony with each other.

/Kim Madsen / C4D

There is extra code you can download from your

subscription site....

47Issue Nr 3 2015 BLAISE PASCAL MAGAZINE

GENERATE DELPHI SUPPORT FOR READING AND WRITING XML FILES PAGE 5 - END

50 hands-on recipes to master the power of Delphi for

cross-platform and mobile development on Windows,

Mac OS X, Android, and iOS

Daniele Teti

Quick answers to common problems

Delphi CookbookSee our special offer:if you take out a subscription for two years the book will cost you only € 10,00

http://www.blaisepascal.eu/daniele_teti_book/DanieleTeti.html

OICH EC SR

OT

IDE

A

MAZING

BLAISE PASCAL

MAGAZINE

€ 30,00 including VAT € 39 including the printed book, ebook and shipping