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
Top Related