Last Updated:

Using XML in delphi

The advantage of using XML in e-business is the high efficiency of B2B systems with low costs for its creation due to a clear and visual representation of structured information, the ability to use modern network protocols and the creation of real-time business systems.

Table of Contents

Using COM in a Delphi environment

Recently, much attention has been paid to building e-business systems, or as they are also called - B2B (business to business). Taking into account the recommendations for building exchange streaming systems of the coordinating body of Internet technologies - WWW Consortium: the emphasis is on XML technologies and the construction of systems for the exchange of XML documents.

 

The independence of presenting information in the form of XML documents allows different firms involved in e-business to produce independent software.

In all systems, the exchange, as a rule, is built on the same scheme, using HTTP requests. As an information protection protocol, the SSL protocol is used (but this is a separate topic).

One possible way to process xml messages is to build BIN/CGI (ISAPI) applications or COM (server) components that generate or process XML documents.

On the one hand, the application acts as a client that in POST mode issues an HTTP request, on the other hand, there is a WEB server on the side of which the request is processed and the response is issued. XML documents are used in information exchange.

One of the most effective implementations is to use an existing XML parser that supports the DOM model. This parser is a Win'98 distribution or part of IE 4.7 and later (for Win'95) and represents a COM server located in the msxml.dll library.

Component Object Model (COM) - Represents encapsulated data and methods into a single entity and a way to access them through an interface system. Delphi makes it easy to access the classes of a COM object (multiple classes can be included in a single COM server). Objects are accessed by initializing an instance of a class through the interface system. Interfaces are described by the Interface Definition Language (IDL), which can be done automatically by means of the environment.

Delphi tools import msxml.dll from the COM server, build IDL interface description files and a binary description library type description file - TLB. This operation is carried out through the system menu: Project | Type Library Import: (Figure 1). Next, a dialog box appears (Figure 2) in which you need to select the COM object (in our case, the object is registered under the name "Microsoft.XMLDom (Version 2.0)") and create a TLB file (create Unit button). Using a .tlb file, the environment generates a "Pascalean" COM server description file - MSXML_TLB.pas

 

The MSXML_TLB.pas file describes all the interfaces, constants, and coclasses of the COM server.

To access the objects of a COM element, you must add the name of the library description file (MSXML_TLB.pas) to the USES directive. The following is a simple program that uses the DOM standard msxml.dll parser, which loads an XML document and displays it in the Memo1 text box element.

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  OleServer, MSXML_TLB, StdCtrls;
type
  TForm1 = class(TForm)
    Button1: TButton;
    Memo1: TMemo;
    procedure Button1Click(Sender: TObject);
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

Procedure 
TForm1.Button1Click(Sender: Tobject);
   // declaration of the coclass of the DOMDocument object;
var
coDoc : CoDOMDocument;
   // class consistent with the IDOMDocument interface;
var Doc: IXMLDOMDocument;

begin
   // create an instance of the DOMDocument object;
     Doc := coDoc.Create;
   // calling the Load method of an instance of the DOMDocument object;
     Doc.load('data.xml');
   // access to the xml property of the DOMDocument object instance;
     Memo1.Text:=Doc.xml;
end;

end.

DOM Concept - Document Object Model

Each XML document is represented as a set of many objects (classes), with which it is possible to access individual elements (fields of the object). DOM - interface describes access both to simple objects of the DOMString or CharacterData type, and to parts or individual elements of the XML document: DOMFragmentElement, DOMNode, DOMElement.

The following are the most important properties and methods of the XMLDOMDocument, XMLDOMNode, XMLDOMNodeList objects. It should be noted that the following methods and functions of the Document Object Model (DOM) are used by the Microsoft XML parser msxml.dll and slightly more extensively than the W3C-approved DOM model.

A more complete description of the DOM object interface can be found on the http://msdn.microsoft.com/xml/

XMLDOMDocument Object
Represents the top level of the object hierarchy and contains methods for working with the document: loading it, analyzing it, creating elements, attributes, comments, etc. .
Properties
AsyncProperty identifying the current processing mode
ParseErrorReturns a reference to an XMLDOMParseError error-handling object
Enable - disable document verification. 
urlReturns the URL of the document
documentElementContains a reference to the root element of the document as an XMLDOMElement object.
Methods
load(url)
loadXML(xmlString)
Loads an XML document,
save(objTarget)Saves an XML document in a file
abortInterruption of the process of loading and processing the document.
createAttribute (name)Creates a new attribute with the specified name for the current element.
createNode(Type, name, nameSpaceURI)Creates a node of the specified type and name
createElement(tagName)Creates a document item with the specified title.
createTextNode(data)Creates text inside a document
getElementsByTagName(tagname)Returns a reference to a collection of document items with the specified name
nodeFromID(idString)Search for an item by ID
 

XMLDOMNode object
The XMLDOMNode object, which implements the underlying Node DOM interface, is designed to manipulate an individual node in the document tree. Its properties and methods allow you to get and change complete information about the current node - its type, name, full name, its contents, a list of child elements, etc.
Properties
nodeName, baseNameGets the name of the current node.
prefixReturns a Namespace prefix.
dataTypeSpecifies the content type of the current site
nodeType, nodeTypeStringGets the type of the current node:
attributesReturns a list of attributes of the current node as an XMLDOMNamedNodeMap collection.
textReturns the contents of the current subtree as text
xmlReturns an XML representation of the current subtree.
nodeValueReturns the contents of the current node.
childNodesReturns a list of child elements in the form of an XMLDOMNodeList.
firstChild, lastChildReturns the first/last child element
previousSibling ,nextSiblingReturns the previous/next sister element.
parentNodeContains a reference to the parent element.
ownerDocumentReturns a pointer to the document in which the current node is located.
Methods
appendChild(newChild)Adds a new child element to the current node.
insertBefore(newChild, refChild)Inserts a child node to the left of the node specified by the refChild parameter.
cloneNode (deep)Create a copy of the current item.
getAttribute(name)
getAttributeNode (name)
setAttribute(name, value)
setAttributeNode(XMLDOMAttribute)
Access to the attributes (create, read, write) of the object. Name - the name of the attribute, value - its value. Returns the value of the XMLDOMAttribute object.
replaceChild(newChild, oldChild) removeChild(oldChild)Replace the oldChild object of the current list of child objects with newChild. Delete the oldChild object
selectNodes(patternString) selectSingleNode(patternString)Returns an XMLDOMNodeList object selected from the search pattern or the first node
transformNode(stylesheet)
transformNodeToObject(stylesheet, outputObject)
Assigns a style table to the subtree of the current node and returns a row - the result of processing. The parameter is a reference to the DOMDocument object in which the XSL statements reside.

XMLDOMNodeList object
It is a list of nodes - subtrees and contains methods by which you can organize the procedure for crawling the tree.
lengthnumber of elements in the node list
item(i)Select the i-th item from the list. Returns an XMLDOMNode object
nextNode()Select the next item in the list.

Use of XML in business.

For a clearer picture, an explanation is needed, and why all this is needed in order to understand how it works:

When building a B2B or corporate ERP system, when organizing information exchange of XML documents between enterprises or branches of the pr-ya, an effectively proven information transfer system based on existing WEB servers via HTTP protocols is used.

On the one hand, the application acts as a client that in POST mode issues an HTTP request, on the other hand, there is a WEB server, on the side of which the request is processed and the response is issued. XML documents are used as an exchange.

For example, in a simple corporate ERP system, an accounting program (ACS Accounting) needs to form a request for the issuance of an invoice and transfer it to a branch that has a warehouse (ACS Warehouse). Workstation A similar statement of the task when creating a B2B system, when Enterprise A requests the availability of products (makes an order for purchase) from Supplier B.

Enterprise A and its program acts as a customer. The warehouse is serviced by Supplier B, who has a database complex on the SQL server. The exchange is carried out through the corporate WEB server of Provider B.

Below is the following typical exchange algorithm:

  1. Enterprise A initiates process A (product ordering), which acts as a WEB-client.
  2. Process A generates an XML document (for example, a request-invoice) and sends it as a POST request http to the WEB server of Provider B. As a URI, the resource identifier of the processing application is used. The URI can be the same as for all types of documents, or individual for each type. It all depends on the structure of the B2B (WEB server.
  3. Web server analyzes the request and generates a server Process B, passing the body of the XML document as a parameter.
    Process B is started by the WEB server and processed either as an ASP page, a CGI (ISAPI) application or a JAVA server (server application)
  4. Process B - generates a query on the SQL database server.
  5. Sql Server performs the necessary operations in the database, generates a response, and returns it to Process B.
  6. Based on the response from the SQL server, Process B generates an XML document (response) and returns it as a response to an http request to the client application.
  7. Further, depending on the situation, either a new http request is generated on the client side or the session ends.

 

A few words about the organization of document circulation.

The general rule for developing an XML document exchange system is:

  • first, the development of a scheme for the flow of electronic documents and their structure;
  • secondly, the development of tables of functions of processes (subprocesses), i.e. what function in relation to which XML document each process will implement.

Each XML document, like an HTML document, must consist of a message header (tagged information)

) and the body of the message (for a request, this information is framed by tags for responding to a request). In order for an XML document to be properly formed, its two component parts "Title" and "Request" must be framed with tags, for example, the view of a typical document is presented below:

 

 

The title , unlike the HTML document, should contain various kinds of service information, including information about the type of document being transmitted and the process of its processing. The body of the document enters the information processing, i.e. the content part framed by tags. It should be noted that the structure of the headers should be the same for all types of documents.

For a process started by the server, the processing algorithm is preferable (but not necessary) to build as follows:

Some fundamental points when creating the client part

As already explained, when creating an XML document, its representation as a DOM model is used. The following is an example of the Delphi text part of the message header creation program.

procedure TThread1.HeaderCreate(Sender: Tobject);
var
  // declaration of a coclass, needed to create
  coDoc : CoDomDocument ;
  // XMLDomDocument object
  Doc: DomDocument;
  // declaration of DOMElement objects
  r : IXMLDOMElement;
  Node: IXMLDOMElement;
  // DOMtext
  txt : IXMLDOMText;
  // DOMAttribute
  attr : IXMLDOMAttribute;
begin

  // create DOM document
  Doc:=coDoc.Create;
  // set synchronous processing mode
  Doc Set_async(false);
  // initial initiation of the DOM document
  Doc.LoadXML('<Header/>');
  // get the address of the root element
  r:=Doc.Get_documentElement;

  // create DOMElement (<Sender> tag)
  Node := Doc.createElement('Sender');
  // creating a text node 'LLC "Typhoon"'
  txt := Doc.createTextNode( 'LLC "Typhoon"');
  // assigning the <Sender> node a value
  // text node 'LLC "Typhoon"'
  Node.appendChild(txt);
                                                
  // adding the <Sender> element to the document root as a child
  r.appendChild(Node);

  // similar operations for the <From> tag
  Node := Doc.createElement('From');
  
  txt := Doc.createTextNode( 'http://tayfun.ru/xml/default.asp');
  Node.appendChild(txt);
  r.appendChild(Node);

  // similar operations for the <To> tag
  Node := Doc.createElement('To');
  txt := Doc.createTextNode( 'http://irbis.ru');
  Node.appendChild(txt);
  r.appendChild(Node);
  
  // create DOMElement()
  Node := Doc.createElement( 'TypeDocument');
  // create an XMLDOMAttribute node
  Att := Doc.createAttribute( 'Id ', 'Order');
  // <TypeDocument Id="Order"/>
  Node.appendChild(att);
  r.appendChild(Node);

end;

It should be noted that declaring the coDoc variable : CoDomDocument and Doc : DomDocument , as well as its creation by the Create method ( Doc:=coDoc.Create;) is carried out once. Declaring a variable is in the global variable description section, not in a local procedure, as demonstrated for clarity in this example (i.e., one global variable of type DomDocument per program module).

the output of the above program will be the created title

, for our xml document example:

The main advantage of transmitting information in the form of XML documents is that it is possible to form a message using independent table structures in the DBMS on both the received and transmitted sides. Using our example, suppose you want to pass information about the invoices of Enterprise A, from the DBMS having the structure shown in Figure 6

To generate an xml document containing an invoice, an SQL query (query A) is initially built with information about the invoice itself:

    SELECT * FROM Invoice_General
    WHERE InvoiceNum = :num
  // :num  - parameter that specifies the invoice number. 

and then the SQL query (query B) is built information about the goods described in the invoice (detailed specification):

SELECT Goods,Qulity,Price, HZ_cod 
    FROM Goods 
    WHERE InvoiceNum = :num                      
  // :num - parameter that specifies the invoice number.

The following is part of the program that forms the body of an xml document:

procedure TThread1.DataBodyCreate(Sender: Tobject);
var
  // declaring a coclass and an XMLDomDocument object
  //coDoc : CoDomDocument ;
  // must be global, for the entire module.
  //Doc : DomDocument ;
  
  // declaration of DOMElement objects
  r : IXMLDOMElement;
  // DOMElement;
  Node, Node2 : IXMLDOMElement;
  Node3, Node4 : IXMLDOMElement;
  // DOMtext
  txt : IXMLDOMText;
  str : String;

// InvoiceNumber: integer; - global variable -
// has value 987654
// queryA, queryB : String; - global variable,
// has a value corresponding to the request
// queryA - query A with general information about the invoice
// queryB - query B information about the products described in
// invoice (see text)

begin

  // closes the request for access
  Query.Close;
  // see the text "request A"
  Query.Text := queryA;

  // assigning a parameter value
  Query.Params[0].AsInteger := InvoiceNumber;
  // request execution
  Query.ExecSQL;
  // opening access to request data
  Query.Open;

  // get the address of the root element
  r:=Doc.Get_documentElement;

  // create DOMElement (tag )
  Node2 := Doc.createElement( 'Request');
  // create DOMElement (tag )
  Node := Doc.createElement( 'Invoice');
  // adding an element to the root
  r.appendChild(Node2);
  // adding an element to
  node2. appendChild(Node);
  
  // create DOMElement (tag )
  Node3 := Doc.createElement( 'Depurture') ;
  // adding an element to
  Node. appendChild(Node3);

  // accessing the 'Depurture' field of the request
  str:= Query.FieldByName('Depurture').AsString;
  // create text node = field value
  txt := Doc.createTextNode(str);
  // assigning a value to a node
  // text node, variable str
  Node.appendChild(txt);
                                                   

// similar operations for the tag <Destination>, <DataSend>,
// <DataDepurture>, <Currency>
// <DestinationCompany> (DB field "Consignee" )

  Node := Doc.createElement( 'Destination');
  // database field name may not match the field name
  str:= Query.FieldByName('Consignee').AsString;
  // tag, this is the advantage of using
  txt := Doc.createTextNode(str);
  // DOM of the interface in front of the DBMS that has support for the XML interface,
  // type ORACLE 8i or Ms SQL 2000
  Node.appendChild(txt);

...
  // generating a request for a product specification
                                                     
  // closes the request for access
 Query.Close;
  // see the text "request B", info. About goods
 Query.Text := queryB;

  // assigning a parameter value
 Query.Params[0].AsInteger := InvoiceNumber;
  // request execution
 Query2.ExecSQL;
  // opening access to request data
 Query.Open;

  // create DOMElement (tag )
Node3 := Doc.createElement( 'Imems') ;
  // adding an element to
Node. appendChild(Node3);

  // loop through all query strings
while not Eof.Query do begin
   Node4 := Doc.createElement( 'Imem');
  // adding an element to
   Node3.appendChild(Node4);
  
  // generating data for the tag
  str:= Query.FieldByName('Price').AsString;
  txt := Doc.createTextNode(str);
  Node.appendChild(txt);
  ...
// similar operations for tags <HZ_Cod>, <Quality>, <GoodName>
  end;
end;

This procedure produces the following XML document text:

 

To generate the request, use the Open method of the IXMLHttpRequest object:

procedure Open(const bstrMethod, - method type ="POST"
           bstrUrl, - Url address of the server
           varAsync, - communication mode asynchronous/synchronous = true
           bstrUser, - username for authentication
           bstrPassword) - password

Creating a Document Processing Backend

As noted earlier, HTTP request processing can be done by either CGI applications or Java servlets. It is also possible to write ASP-pages. But in this case, data transfer is possible only by the "GET" method through the query string. Although, handling an HTTP request for ASP pages works more efficiently than a CGI application. However, in my opinion, it does not matter how to process, and it is more important to solve the question - how to build a processing program, and not by what means.

If from the previous chapter we considered the options for forming an XML document, then the task of the server application is reversed - parsing XML documents. The following is part of the program that parses an xml document:

procedure Tthread1.DataParser(Sender: Tobject);
var

// declaration of DOMElement objects
  r,FNode : IXMLDOMElement;
  Str,Filename : String;
  parm : String;

// declaration of a coclass and
CoDocXML, CoDocXSL, CoDocResult : CoDomDocument ;
// XMLDomDocument object
XMLDoc, XSLDoc, ResultDoc : DomDocument ;

// HttpStr : String; - global variable containing HTTP request string

Begin

  // create an XMLDoc document
  XMLDoc:=coDocXML.Create;
  // set synchronous processing mode
  XMLDoc.Set_async(false);
  // load DOM document from HttpStr string
  XMLDoc.LoadXML(HttpStr);

  // get the address of the root element
  r:=Doc.Get_documentElement;
  // get element value
  FNode:= r.SelectSingleNode("//TypeDocument");
  // get attribute value id="Order"
  FileName:= FNode.GetAttibute("id");
  // and the formation of the file name Order.xsl
  FileName:= FileName+".xsl";

  // create XSLDoc document
  XSLDoc:=coDocXSL.Create;
  // set synchronous processing mode
  XSLDoc.Set_async(false);
  // load DOM document from file Order.xsl
  XSLDoc.LoadXML(FileName);

  // create an XMLDoc document
  ResultDoc:=coDocResult.Create;
  // set synchronous processing mode
  ResultDoc.Set_async(false);
  // set parse check
  ResultDoc.validateOnParse := true;
 
  // parsing XMLDoc by XSL template
  XMLDoc.transformNodeToObject(XSLDoc, ResultDoc);

 // variable Str is assigned a text value
 // resulting document.
 Str:= ResultDoc.text;
 
 // find element
 FNode:= r.SelectSingleNode("//InvoiceNumber");
 // and getting the value of the element
 parm:= FNode.text;

 // closes the request for access
 Query.Close;
 Query.Text := Str;
 // assigning a parameter value
 Query.Params[0].AsString := parm;
 // request execution
 Query.ExecSQL;
end;

The whole highlight of parsing lies in the application of the XSL template, which is formed for each type of document individually. The result of parsing is a SQL query string. Subsequently, executing the generated SQL query string will make the necessary changes to the data in the DBMS.

The advantage of using parsing through a template is also that a certain flexibility of the data is obtained, and the algorithm is completely independent of the algorithm from the program code. The following is the text of an XSL template used to process an ORDER document:

<!-- Order.xsl file -->
<xsl:stylesheet xmlns:xsl="http://www.w3.org/TR/WD-xsl">
   <xsl:template match="/">
   <xsl:for-each select="//header">
      INSERT into TABREG ( FROM, TO, TYPEDOC,body) VALUES( '
       <xsl:value-of select="from" />',
      '<xsl:value-of select="to" />',
      '<xsl:value-of select="TypeDocument/@id" />' )
   </xsl:for-each>

    <xsl:for-each select="//item">
       INSERT into GOODS ( invoiceNumber, name, price, quality) VALUES( ' :num',
      '<xsl:value-of select="name" />',
      '<xsl:value-of select="price" />',
      '<xsl:value-of select="quality" />
   ' )
   </xsl:for-each>
  
   </xsl:template>
</xsl:stylesheet>

Explaining the above example, it should be noted that the use of a pair of tags is of a formal nature, because after parsing, at least one node must formally be present in the resulting XML document. The ResultDoc.text method assigns a text value to the resulting RESULTDoc XML document. In this case, the value is anything that is framed by tag pairs and , i.e. the SQL query we generated.

Another feature of writing a program should be noted the ability to use the SQL-parameter :num. Using the parameter allows you to simplify the text of the xsl-template. Determining the value of the corresponding node elements of an XML document is determined initially by selecting by the name of the corresponding node, for example:

// search for an element and then use the text property:
FNode:= r.SelectSingleNode("//InvoiceNumber");
// and getting the value of the element
parm:= FNode.text;

XSL at a glance

The abbreviation XSL comes from eXtensible Stylesheet Language - a formatting language for style sheets (XML data). As can be seen from the eXtensible Stylesheet Language (XSL) header, it is used to format XML data. As defined by the W3C, XSL consists of two parts:

  • XSLT - XSL Transformation. The language used to transform or format (transform) XML documents. Thus, with the help of XSLT, we can get different sections of a set of data and forms of data representation.
  • Formatting elements. These elements include all elements of the typographic design of the data, after processing them using XSL. Used only to generate HTML pages.

With XSLT, we can select the data we need from an XML file, and arrange it in a form to provide to the user. For example, in our case, we transformed the XML data as a SQL query. The classic application of XSL is usually the formatting of data in the form of HTML pages or a more rare representation in the form of RTF files.

An XSL file describes a template according to which the transformation of XML data will be performed. Returning to xsl templates, the following elements (directives) can be distinguished in XSLT:

XSL directives
description
xsl:apply-templatesA directive that specifies the application of appropriate patterns to the select="template name" attribute
xsl:attributecreates an attribute tree and adds it to the output element, parameter name="attribute name", namespace - URI for the namespace (namespace prefix)
xsl:call-templatecalls the template, attribute name=" URI on the template"
xsl:choose
xsl:when
xsl:otherwise
making selections based on the condition xsl:when expr="evaluating an expression in script ",
language="language-name"
test= "evaluated expression"
xsl:commentgenerates a comment in the output document
xsl:copy
xsl:copy-of
copies the current node to the output source or inserts a document fragment into the node where the select="source node name" attribute
xsl:elementcreates an output element by name, attribute name="element name", namespace="uri namespace reference"
xsl:for-eachreapplys the template to all nodes in the node list, the select attribute specifies the list of nodes
xsl:ifcondition validation, specified by the test attribute as an expression
xsl:includeincludes an external template, href attribute = "URI reference"
xsl:outputspecifies the output result, the method attribute can be "xml", "html" or "text"
xsl:paramspecifies the value of parameters, attribute name="parameter name", select= "value"
xsl:processing-instructioncreates a processing instruction, attribute name="process statement name"
xsl:sortsorts many nodes, attributes select = "hostname", data-type = data type {"text" | "number" | Qname}, order = sort direction {"ascending" | "descending"}
xsl:stylesheetdefines an xsl template document, is the root element for xslt
xsl:templatedefines an xsl template, attribute name= "URI prefix to template name", match= "point to the node to which the template applies"
xsl:textgenerates text in the output stream, attribute disable-output-escaping = "yes" or "no", indicates the possibility of generating ESC characters
xsl:value-ofinserts the value of the selected node as text, attribute select= "pointer to the node" from which the value is taken
xsl:variablespecifies the value of variable boundaries, attribute name = "variable name", select = "calculate variable value"
xsl:with-paramapplies a parameter to a template, attribute name="parameter name", select=expression to calculate the current context, default value "."
 

Conclusion

In conclusion, it should be noted that the use of the standard XML parser msxml.dll is not the only means of parsing and creating XML documents. For example, to create XML documents, use the TPageProduser and TТableProduser components efficiently. But, this article only emphasizes the breadth and possibility of applying the DOM model in practice.

The author will be very grateful for feedback on the relevance of the topic, general content, style of presentation, as well as all other comments that will help to further improve the quality of writing a collection of articles and the release of a book highlighting the practical side of using XML documents in e-commerce. More detailed information on the practical side of the use of electronic documents can be found on the author's website. It is also planned to place source texts and examples on the author's website.