For many Delphi programmers, saving settings is associated with using INI files in your programs. The use of this method, in more or less serious projects, should be avoided, as it limits flexibility, which prevents further expansion of the program. It is worth saying that this approach is quite popular, due to its ease of use and the presence of built-in tools in the development environment.
However, the ideal option for storing program settings are structured XML files. Their advantage is that the number of parameters may not be fixed. To understand this better, let's look at a specific example.
In the USearch program, when you click on an entry, a context menu appears in which a list of items is displayed. These items are commands, which in turn are loaded from the settings file. If the settings were stored in INI file, the program could save and load a certain number of instructions, such as 10 or 50. As soon as a larger value is needed, the code will have to be rewritten and recompiled accordingly.
Taking the approach using XML files, we will be able to load all section parameters dynamically. To all this, the configuration file will become more elegant, without excessive numbering of parameters. But, standard means to work with XML in Delphi have many disadvantages, so I recommend using standard library MSXML. It is usually included by default operating systems Windows family.
To connect MSXML, we need to generate an interface file with a list of all functions by importing it from the COM server. How to import an interface, quite a few detailed articles have been written, but I suggest you download the file MSXML2_TLB.PAS already ready to use. After the file is downloaded, place it next to your project, or drop it into the lib folder of the Delphi environment. Thus, all created programs will be able to use the module MSXML, you just need to add the line MSXML2_TLB to uses .
For clarity, consider the following example of using this library:
LoadProcedureData; var XMLDoc: DOMDocument; Root: IXMLDOMElement; begin XMLDoc:= CoDOMDocument.Create; XMLDoc.Load("settins.xml"); Root:= XMLDoc.DocumentElement; ShowMessage(Root.SelectSingleNode("size/width").Text); Root:= nil; XMLDoc:= nil; end;
First, an instance of the DOMDocument class is created, and then the contents of the settings.xml file are loaded into memory. Since according to the standard any XML the file must contain a root tag (in this case config), then we need to get it using the function DocumentElement. Then the content between the tags is displayed
Here the SelectSingleNode method is used, which takes a string as a parameter
Despite the fact that the topic of working with XML in Delphi has been widely discussed on the Internet, questions on this topic quite often arise on all kinds of forums.
I've already posted this as well, but I'd like to get back to a real case of quickly parsing an XML file and extracting data, which I did at work today. It took me no more than 5 minutes to get the necessary data.
Background. Today it was necessary to process data on installed programs on users' computers (yes, yes, we detect pirates :)). The technical department provided me with such information ripped from unsuspecting users over a network using WMI. The program they used generates reports in XML format. Accordingly, they brought me a mountain of XML files with a rather complex structure, from which I needed to extract only the name of the installed software products. Treatment . After reviewing a couple of files manually, I realized that it would not take long to grow old, and decided to write a small converter. Launching Delphi, I selected the XML DataBinding object in the repository and fed it one of the files. I left all the settings and parameters by default, and as a result, I formed a module with large quantity classes and interfaces to access the elements of this XML file. I did not begin to deal with the class structure for a long time, I immediately proceeded to writing a converter. In a new console application, I wrote a fairly simple code:
program XML2TXT;
uses
forms,
Classes, SysUtils,
SoftwareXML in "SoftwareXML.pas";
procedure CovertXML2Text;
var
softbase: IXMLSTDSoftwareType;
i: integer;
sr: TSearchRec;
CurDir:string;
ExportFile: TStringList;
begin
CurDir:= IncludeTrailingPathDelimiter(ExtractFilePath(Application.ExeName));
if FindFirst(CurDir+"*.xml", faAnyFile, sr) = 0 then
repeat
ExportFile:= TStringList.Create;
softbase:= LoadSTDSoftware(Pchar(CurDir+sr.Name));
for i:= 0 to softbase.InstalledSoftware.source.software.Count - 1 do
ExportFile.Add(softbase.InstalledSoftware.source.software[i].DisplayName);
ExportFile.Sort;
ExportFile.SaveToFile(CurDir + softbase.InstalledSoftware.Source.servername+".txt");
ExportFile.Free;
until FindNext(sr) 0;
end;
begin
Application.Initialize;
CovertXML2Text;
end.
As a result of which, I got one textbook for each computer in the grid, containing a list of installed software.
I feel that this code will require explanations. For example, why did I use the Forms module in a console application and call the Application.Initialize; procedure?
In fact, everything is simple - this is a small hack that allows you to use XML Data Binding in a console application. Because it stubbornly refused to initialize the class for working with XML. I haven’t figured out the true reasons yet - today time was important, and so I spent 4 out of 5 minutes fighting this error. :) I think later to deal with this problem and write what is the real reason.
The strange softbase class was created based on an XML file - that was the name of the root element, and softbase.InstalledSoftware.source.software[i].DisplayName - just navigating through nested elements to the desired one and getting its value.
This is what one of the most looks like. quick ways working with XML in Delphi.
XML is increasingly being used to store information and exchange it between applications and Web sites. In many applications, this language is used as a base language for storing data, in others - for exporting and importing XML data. It follows from this that it is time for developers to think about how XML data can be used in their own applications.
In this article, we'll take a look at the XML Document Object Model (DOM) and Microsoft's implementation of it, the Microsoft XML DOM.
The XML DOM is an object model that provides the developer with objects for loading and manipulating XML files. The object model consists of the following main objects: XMLDOMDocument, XMLDOMNodeList, XMLDOMNode, XMLDOMNamedNodeMap, and XMLDOMParseError. Each of these objects (except XMLDOMParseError) contains properties and methods that allow you to get information about the object, manipulate the values and structure of the object, and navigate the structure of the XML document.
Let's look at the main XML DOM objects and give some examples of their use in Borland Delphi.
Using XML DOM in Borland Delphi
In order to use the Microsoft XML DOM in Delphi applications, you must include the appropriate type library in your project. To do this, we execute the command Project | Import Type Library and in the Import Type Library dialog box, select the Microsoft XML version 2.0 (Version 2.0) library, which is usually located in the Windows\System\MSXML.DLL file
After clicking the Create Unit button, the MSXML_TLB interface module will be created, which will allow us to use the XML DOM objects: DOMDocument, XMLDocument, XMLHTTPRequest and a number of others implemented in the MSXML.DLL library. A reference to the MSXML_TLB module must be specified in the Uses list.
XML DOM device
The Document Object Model represents an XML document as a tree structure consisting of branches. The XML DOM APIs allow applications to traverse the document tree and manipulate its branches. Each branch can have a specific type (DOMNodeType), according to which the parent and child branches are defined. In most XML documents, you will find element, attribute, and text branches. Attributes are a special kind of branch and are not child branches. Attributes are managed. special methods, provided by XML DOM objects.
In addition to implementing the World Wide Web Consortium (W3C) recommended interfaces, the Microsoft XML DOM contains methods that support XSL, XSL Patterns, Namespaces, and data types. For example, the SelectNodes method allows you to use the XSL Pattern Syntax to find branches in a specific context, and the TransformNode method supports using XSL to perform transformations.
Test XML Document
As an example of an XML document, let's take a music CD-ROM directory, which has the following structure:
Now we're ready to start looking at the XML DOM object model, which we'll start with the XMLDOMDocument object.
XML document - XMLDOMDocument object
Working with an XML document begins with loading it. To do this, we use the Load method, which has only one parameter, which specifies the URL of the document to be loaded. When loading files from a local disk, only the full file name is specified (the file:/// protocol can be omitted in this case). If the XML document is stored as a string, you should use the LoadXML method to load the document.
To control how the document is loaded (synchronous or asynchronous), use the Async property. By default, this property is set to True to indicate that the document is loaded asynchronously and control is returned to the application before the document is fully loaded. Otherwise, the document is loaded synchronously, and then you have to check the value of the ReadyState property to see if the document has loaded or not. You can also create an event handler for the OnReadyStateChange event that will receive control when the value of the ReadyState property changes.
The following shows how to load an XML document using the Load method:
Uses ... MSXML_TLB ... procedure TForm1.Button1Click(Sender: TObject); var XMLDoc: IXMLDOMDocument; begin XMLDoc:= CoDOMDocument.Create; XMLDoc.Async:= False; XMLDoc.Load('C:\DATA\DATA.xml'); // // Here is the code that manipulates // the XML document and its branches // XMLDoc:= Nil; end;
After the document is loaded, we can access its properties. For example, the NodeName property will contain the value #document, the NodeTypeString property will contain the value document, and the URL property will contain the value file:///C:/DATA/DATA.xml.
Error Handling
Of particular interest are the properties associated with the processing of the document when it is loaded. For example, the ParseError property returns an XMLDOMParseError object containing information about an error that occurred while processing the document.
To write an error handler, you can add the following code:
Var XMLError: IXMLDOMParseError; ... XMLDoc.Load('C:\DATA\DATA.xml'); XMLError:= XMLDoc.ParseError; If XMLError.ErrorCode<>0 Then // // Here we handle the error // Else Memo1.Lines.Add(XMLDoc.XML); ... XMLDoc:= Nil;
To find out what information is returned in case of an error, change the following directory entry:
remove closing element
Now let's write the code that returns the property values of the XMLDOMParseError object:
XMLError:= XMLDoc.ParseError; If XMLError.ErrorCode<>0 Then With XMLError, Memo1.Lines do begin Add('File:' + URL); Add('Code:' + IntToStr(ErrorCode)); Add('Error:' + Reason); Add('Text:' + SrcText); Add('Line: ' + IntToStr(Line)); Add('Position:' + IntToStr(LinePos)); end Else Memo1.Lines.Add(XMLDoc.XML); end;
and run our application. As a result, we get the following error information.
As you can see from the above example, the information returned by the XMLDOMParseError object is quite enough to locate the error and understand the reason for its occurrence.
Now let's restore the closing element
Accessing the document tree
To access the document tree, you can either get the root element and then iterate through its child branches, or find some specific branch. In the first case, we get the root element through the DocumentElement property, which returns an object of type XMLDOMNode. The following shows how to use the DocumentElement property to get the contents of each child element:
VarNode: IXMLDOMNode; Root: IXMLDOMElement; I: Integer; ... Root:= XMLDoc.DocumentElement; For I:= 0 to Root.ChildNodes.Length-1 do Begin Node:= Root.ChildNodes.Item[I]; Memo1.Lines.Add(Node.Text); end;
For our XML document, we will get the following text.
If we are interested in a specific branch, or a branch below the first child branch, we can use either the NodeFromID method or the GetElementByTagName method of the XMLDOMDocument object.
The NodeFromID method requires a unique identifier defined in the XML Schema or Document Type Definition (DTD) and returns the branch with that identifier.
The GetElementByTagName method requires a string with a specific element (tag) and returns all branches with this element. The following shows how to use this method to find all the artists in our CD-ROM directory:
Nodes: IXMLDOMNodeList; Node: IXMLDOMNode; ... Nodes:= XMLDoc.GetElementsByTagName('ARTIST'); For I:= 0 to Nodes.Length-1 do Begin Node:= Nodes.Item[I]; Memo1.Lines.Add(Node.Text); end;
For our XML document, we will get the following text
Note that the SelectNodes method of the XMLDOMNode object provides a more flexible way to access document branches. But more on that below.
Document branch - XMLDOMNode object
An XMLDOMNode object represents a document branch. We've already encountered this object when we got the document's root element:
Root:= XMLDoc.DocumentElement;
To obtain information about the branch of an XML document, you can use the properties of the XMLDOMNode object (Table 1).
To access the data stored in a branch, one typically uses either the NodeValue property (available for attributes, text branches, comments, processing instructions, and CDATA sections), the Text property, which returns the text content of the branch, or the NodeTypedValue property. The latter, however, can only be used for branches with typed elements.
Navigating the document tree
The XMLDOMNode object provides many ways to navigate the document tree. For example, the parent branch is accessed through the ParentNode property (XMLDOMNode type), child branches are accessed through the ChildNodes (XMLDOMNodeList type), FirstChild and LastChild (XMLDOMNode type) properties, and so on. The OwnerDocument property returns an object of type XMLDOMDocument that identifies the XML document itself. The properties listed above make it easy to navigate the document tree.
Now let's iterate through all the branches of the XML document:
Root:= XMLDoc.DocumentElement; For I:= 0 to Root.ChildNodes.Length-1 do Begin Node:= Root.ChildNodes.Item[I]; If Node.HasChildNodes Then GetChilds(Node,0); end;
As noted above, the SelectNodes of the XMLDOMNode object provides a more flexible way to access document branches. In addition, there is a SelectSingleNode method that returns only the first branch of the document. Both of these methods allow you to specify XSL templates for finding branches.
Consider the process of using the SelectNodes method to retrieve all branches that have a CD branch and a PRICE sub-branch:
Root:= XMLDoc.DocumentElement; Nodes:= Root.SelectNodes('CD/PRICE');
All PRICE sub-branches of the CD branch will be placed in the Nodes collection. We will return to the discussion of XSL templates a little later.
Manipulation of child branches
To manipulate child branches, we can use the methods of the XMLDOMNode object (Table 2).
In order to completely remove the entry about the first disk, you must run the following code:
Var XMLDoc: IXMLDOMDocument; Root: IXMLDOMNode; Node: IXMLDOMNode; XMLDoc:= CoDOMDocument.Create; XMLDoc.Async:= False; XMLDoc.Load('C:\DATA\DATA.xml'); // Get the root element Root:= XMLDoc.DocumentElement; Node:= Root; // Remove the first child branch Node.RemoveChild(Node.FirstChild);
Note that in this example we are deleting the first child branch. How to remove the first element of the first child branch is shown below:
Var XMLDoc: IXMLDOMDocument; Root: IXMLDOMNode; Node: IXMLDOMNode; XMLDoc:= CoDOMDocument.Create; XMLDoc.Async:= False; XMLDoc.Load('C:\DATA\DATA.xml'); // Get the root element Root:= XMLDoc.DocumentElement; // and first child branch Node:= Root.FirstChild; // Remove the first child branch Node.RemoveChild(Node.FirstChild);
In the above example, we have not deleted the first branch
Now let's add a new branch. Below is the code showing how to add a new music CD-ROM entry:
Var NewNode: IXMLDOMNode; Child: IXMLDOMNode; ... // Create a new branch -
The above code shows the following sequence of steps for adding a new branch:
- Creating a new branch using the CreateNode method:
- creating an element using the CreateNode method;
- adding an element to a branch using the AppendChild method;
- setting the value of an element through the Text property;
- ... repeat for all elements.
- Adding a new branch to a document using the AppendChild method.
Recall that the AppendChild method adds a branch to the end of the tree. To add a branch to a specific location in the tree, you must use the InsertBefore method.
Branch set - XMLDOMNodeList object
The XMLNodeList object contains a list of branches, which can be built using the SelectNodes or GetElementsByTagName methods, or retrieved from the ChildNodes property.
We have already seen the use of this object in the example given in the "Navigating the Document Tree" section. Here we present some theoretical remarks.
The number of branches in the list can be obtained as the value of the Length property. The branches have indices from 0 to Length-1, and each individual branch is accessible through the Item array element with the corresponding index.
Moving through the list of branches can also be done using the NextNode method, which returns the next branch in the list, or Nil if the current branch is the last one. To return to the beginning of the list, call the Reset method.
Create and save documents
So, we have seen how you can add branches and elements to existing XML documents. Now let's create an XML document on the fly. First of all, remember that a document can be loaded not only from a URL, but also from a regular string. The following shows how to create a root element, which can then be used to build the rest of the elements dynamically (which we already covered in Manipulating Child Branches):
Var XMLDoc: IXMLDOMDocument; Root: IXMLDOMNode; Node: IXMLDOMNode; S: WideString; ...S:='
After building the XML document, we save it to a file using the Save method. For instance:
XMLDoc.Save('C:\DATA\NEWCD.XML');
In addition to saving to a file, the Save method allows you to save an XML document to a new XMLDOMDocument object. In this case, the document is completely processed and, as a result, its structure and syntax are checked. The following shows how to store the document in another object:
Procedure TForm1.Button2Click(Sender: TObject); var XMLDoc2: IXMLDOMDocument; begin XMLDoc2:= CoDOMDocument.Create; XMLDoc.Save(XMLDoc2); Memo2.Lines.Add(XMLDoc2.XML); ... XMLDoc2:= Nil; end;
Finally, the Save method also allows you to save the XML document to other COM objects that support the IStream, IPersistStream, or IPersistStreamInit interfaces.
Using XSL Templates
When discussing the SelectNodes method of the XMLDOMNode object, we mentioned that it provides a more flexible way to access document branches. The flexibility is that you can specify an XSL template as a criterion for selecting branches. Such templates provide a powerful mechanism for finding information in XML documents. For example, to get a list of all the music CD-ROM titles in our catalog, we could run the following query:
To find out which artists' CDs were released in the US, the query is formed as follows:
Nodes:= Root.SelectNodes('CD/ARTIST');
The following shows how to find the first drive in a directory:
Nodes:= Root.SelectNodes('CD/TITLE');
And last:
Nodes:= Root.SelectNodes('CD/TITLE');
To find Bob Dylan's discs, you can run the following query:
Nodes:= Root.SelectNodes('CD[$any$ ARTIST="Bob Dylan"]/TITLE');
and to get a list of discs released after 1985, we run the following query:
Nodes:= Root.SelectNodes('CD/TITLE');
A more detailed discussion of XSL syntax requires a separate post. To intrigue readers and encourage further research, I will give just one small example of a possible use of XSL. Let's say we need to convert our directory into a regular HTML table. Using traditional methods, we must go through all the branches of the tree and form the corresponding tags for each element received.
Using XSL, we simply create a template (or style sheet) in which we specify what and how to transform. Then we impose this template on our catalog - and you're done: we have the text of the XSL template that converts the catalog into a table (Listing 2).
The code for overlaying the XSL template on our directory looks like this:
Procedure TForm1.Button2Click(Sender: TObject); var XSLDoc: IXMLDOMDocument; begin XSLDoc:= CoDOMDocument.Create; XSLDoc.Load('C:\DATA\DATA.xsl'); Memo2.Text:= XMLDoc.TransformNode(XSLDoc); XSLDoc:= Nil; end;
Concluding our discussion of XSL, it should be said that at present this language is actively used for transformation between different XML documents, as well as for document formatting.
Conclusion
For obvious reasons, it is impossible to cover all the Microsoft XML DOM objects and give examples of their use in one article. Here we have only touched on the main issues of using the XML DOM in applications. In table. Figure 3 shows all the objects implemented in the Microsoft XML DOM.
ComputerPress 12"2000
XML is increasingly being used to store information and exchange it between applications and Web sites. In many applications, this language is used as a base language for storing data, in others - for exporting and importing XML data. It follows from this that it is time for developers to think about how XML data can be used in their own applications.
In this article, we'll take a look at the XML Document Object Model (DOM) and Microsoft's implementation of it, the Microsoft XML DOM.
The XML DOM is an object model that provides the developer with objects for loading and manipulating XML files. The object model consists of the following main objects: XMLDOMDocument, XMLDOMNodeList, XMLDOMNode, XMLDOMNamedNodeMap, and XMLDOMParseError. Each of these objects (except XMLDOMParseError) contains properties and methods that allow you to get information about the object, manipulate the values and structure of the object, and navigate the structure of the XML document.
Let's look at the main XML DOM objects and give some examples of their use in Borland Delphi.
Using XML DOM in Borland Delphi
In order to use the Microsoft XML DOM in Delphi applications, you must include the appropriate type library in your project. To do this, we execute the command Project | Import Type Library and in the Import Type Library dialog box, select the Microsoft XML version 2.0 (Version 2.0) library, which is usually located in the Windows\System\MSXML.DLL file
After clicking the Create Unit button, the MSXML_TLB interface module will be created, which will allow us to use the XML DOM objects: DOMDocument, XMLDocument, XMLHTTPRequest and a number of others implemented in the MSXML.DLL library. A reference to the MSXML_TLB module must be specified in the Uses list.
XML DOM device
The Document Object Model represents an XML document as a tree structure consisting of branches. The XML DOM APIs allow applications to traverse the document tree and manipulate its branches. Each branch can have a specific type (DOMNodeType), according to which the parent and child branches are defined. In most XML documents, you will find element, attribute, and text branches. Attributes are a special kind of branch and are not child branches. Attributes are manipulated using special methods provided by XML DOM objects.
In addition to implementing the World Wide Web Consortium (W3C) recommended interfaces, the Microsoft XML DOM contains methods that support XSL, XSL Patterns, Namespaces, and data types. For example, the SelectNodes method allows you to use the XSL Pattern Syntax to find branches in a specific context, and the TransformNode method supports using XSL to perform transformations.
Test XML Document
As an example of an XML document, let's take a music CD-ROM directory, which has the following structure:
Now we're ready to start looking at the XML DOM object model, which we'll start with the XMLDOMDocument object.
XML document - XMLDOMDocument object
Working with an XML document begins with loading it. To do this, we use the Load method, which has only one parameter, which specifies the URL of the document to be loaded. When loading files from a local disk, only the full file name is specified (the file:/// protocol can be omitted in this case). If the XML document is stored as a string, you should use the LoadXML method to load the document.
To control how the document is loaded (synchronous or asynchronous), use the Async property. By default, this property is set to True to indicate that the document is loaded asynchronously and control is returned to the application before the document is fully loaded. Otherwise, the document is loaded synchronously, and then you have to check the value of the ReadyState property to see if the document has loaded or not. You can also create an event handler for the OnReadyStateChange event that will receive control when the value of the ReadyState property changes.
The following shows how to load an XML document using the Load method:
Uses ... MSXML_TLB ... procedure TForm1.Button1Click(Sender: TObject); var XMLDoc: IXMLDOMDocument; begin XMLDoc:= CoDOMDocument.Create; XMLDoc.Async:= False; XMLDoc.Load('C:\DATA\DATA.xml'); // // Here is the code that manipulates // the XML document and its branches // XMLDoc:= Nil; end;
After the document is loaded, we can access its properties. For example, the NodeName property will contain the value #document, the NodeTypeString property will contain the value document, and the URL property will contain the value file:///C:/DATA/DATA.xml.
Error Handling
Of particular interest are the properties associated with the processing of the document when it is loaded. For example, the ParseError property returns an XMLDOMParseError object containing information about an error that occurred while processing the document.
To write an error handler, you can add the following code:
Var XMLError: IXMLDOMParseError; ... XMLDoc.Load('C:\DATA\DATA.xml'); XMLError:= XMLDoc.ParseError; If XMLError.ErrorCode<>0 Then // // Here we handle the error // Else Memo1.Lines.Add(XMLDoc.XML); ... XMLDoc:= Nil;
To find out what information is returned in case of an error, change the following directory entry:
remove closing element
Now let's write the code that returns the property values of the XMLDOMParseError object:
XMLError:= XMLDoc.ParseError; If XMLError.ErrorCode<>0 Then With XMLError, Memo1.Lines do begin Add('File:' + URL); Add('Code:' + IntToStr(ErrorCode)); Add('Error:' + Reason); Add('Text:' + SrcText); Add('Line: ' + IntToStr(Line)); Add('Position:' + IntToStr(LinePos)); end Else Memo1.Lines.Add(XMLDoc.XML); end;
and run our application. As a result, we get the following error information.
As you can see from the above example, the information returned by the XMLDOMParseError object is quite enough to locate the error and understand the reason for its occurrence.
Now let's restore the closing element
Accessing the document tree
To access the document tree, you can either get the root element and then iterate through its child branches, or find some specific branch. In the first case, we get the root element through the DocumentElement property, which returns an object of type XMLDOMNode. The following shows how to use the DocumentElement property to get the contents of each child element:
VarNode: IXMLDOMNode; Root: IXMLDOMElement; I: Integer; ... Root:= XMLDoc.DocumentElement; For I:= 0 to Root.ChildNodes.Length-1 do Begin Node:= Root.ChildNodes.Item[I]; Memo1.Lines.Add(Node.Text); end;
For our XML document, we will get the following text.
If we are interested in a specific branch, or a branch below the first child branch, we can use either the NodeFromID method or the GetElementByTagName method of the XMLDOMDocument object.
The NodeFromID method requires a unique identifier defined in the XML Schema or Document Type Definition (DTD) and returns the branch with that identifier.
The GetElementByTagName method requires a string with a specific element (tag) and returns all branches with this element. The following shows how to use this method to find all the artists in our CD-ROM directory:
Nodes: IXMLDOMNodeList; Node: IXMLDOMNode; ... Nodes:= XMLDoc.GetElementsByTagName('ARTIST'); For I:= 0 to Nodes.Length-1 do Begin Node:= Nodes.Item[I]; Memo1.Lines.Add(Node.Text); end;
For our XML document, we will get the following text
Note that the SelectNodes method of the XMLDOMNode object provides a more flexible way to access document branches. But more on that below.
Document branch - XMLDOMNode object
An XMLDOMNode object represents a document branch. We've already encountered this object when we got the document's root element:
Root:= XMLDoc.DocumentElement;
To obtain information about the branch of an XML document, you can use the properties of the XMLDOMNode object (Table 1).
To access the data stored in a branch, one typically uses either the NodeValue property (available for attributes, text branches, comments, processing instructions, and CDATA sections), the Text property, which returns the text content of the branch, or the NodeTypedValue property. The latter, however, can only be used for branches with typed elements.
Navigating the document tree
The XMLDOMNode object provides many ways to navigate the document tree. For example, the parent branch is accessed through the ParentNode property (XMLDOMNode type), child branches are accessed through the ChildNodes (XMLDOMNodeList type), FirstChild and LastChild (XMLDOMNode type) properties, and so on. The OwnerDocument property returns an object of type XMLDOMDocument that identifies the XML document itself. The properties listed above make it easy to navigate the document tree.
Now let's iterate through all the branches of the XML document:
Root:= XMLDoc.DocumentElement; For I:= 0 to Root.ChildNodes.Length-1 do Begin Node:= Root.ChildNodes.Item[I]; If Node.HasChildNodes Then GetChilds(Node,0); end;
As noted above, the SelectNodes of the XMLDOMNode object provides a more flexible way to access document branches. In addition, there is a SelectSingleNode method that returns only the first branch of the document. Both of these methods allow you to specify XSL templates for finding branches.
Consider the process of using the SelectNodes method to retrieve all branches that have a CD branch and a PRICE sub-branch:
Root:= XMLDoc.DocumentElement; Nodes:= Root.SelectNodes('CD/PRICE');
All PRICE sub-branches of the CD branch will be placed in the Nodes collection. We will return to the discussion of XSL templates a little later.
Manipulation of child branches
To manipulate child branches, we can use the methods of the XMLDOMNode object (Table 2).
In order to completely remove the entry about the first disk, you must run the following code:
Var XMLDoc: IXMLDOMDocument; Root: IXMLDOMNode; Node: IXMLDOMNode; XMLDoc:= CoDOMDocument.Create; XMLDoc.Async:= False; XMLDoc.Load('C:\DATA\DATA.xml'); // Get the root element Root:= XMLDoc.DocumentElement; Node:= Root; // Remove the first child branch Node.RemoveChild(Node.FirstChild);
Note that in this example we are deleting the first child branch. How to remove the first element of the first child branch is shown below:
Var XMLDoc: IXMLDOMDocument; Root: IXMLDOMNode; Node: IXMLDOMNode; XMLDoc:= CoDOMDocument.Create; XMLDoc.Async:= False; XMLDoc.Load('C:\DATA\DATA.xml'); // Get the root element Root:= XMLDoc.DocumentElement; // and first child branch Node:= Root.FirstChild; // Remove the first child branch Node.RemoveChild(Node.FirstChild);
In the above example, we have not deleted the first branch
Now let's add a new branch. Below is the code showing how to add a new music CD-ROM entry:
Var NewNode: IXMLDOMNode; Child: IXMLDOMNode; ... // Create a new branch -
The above code shows the following sequence of steps for adding a new branch:
- Creating a new branch using the CreateNode method:
- creating an element using the CreateNode method;
- adding an element to a branch using the AppendChild method;
- setting the value of an element through the Text property;
- ... repeat for all elements.
- Adding a new branch to a document using the AppendChild method.
Recall that the AppendChild method adds a branch to the end of the tree. To add a branch to a specific location in the tree, you must use the InsertBefore method.
Branch set - XMLDOMNodeList object
The XMLNodeList object contains a list of branches, which can be built using the SelectNodes or GetElementsByTagName methods, or retrieved from the ChildNodes property.
We have already seen the use of this object in the example given in the "Navigating the Document Tree" section. Here we present some theoretical remarks.
The number of branches in the list can be obtained as the value of the Length property. The branches have indices from 0 to Length-1, and each individual branch is accessible through the Item array element with the corresponding index.
Moving through the list of branches can also be done using the NextNode method, which returns the next branch in the list, or Nil if the current branch is the last one. To return to the beginning of the list, call the Reset method.
Create and save documents
So, we have seen how you can add branches and elements to existing XML documents. Now let's create an XML document on the fly. First of all, remember that a document can be loaded not only from a URL, but also from a regular string. The following shows how to create a root element, which can then be used to build the rest of the elements dynamically (which we already covered in Manipulating Child Branches):
Var XMLDoc: IXMLDOMDocument; Root: IXMLDOMNode; Node: IXMLDOMNode; S: WideString; ...S:='
After building the XML document, we save it to a file using the Save method. For instance:
XMLDoc.Save('C:\DATA\NEWCD.XML');
In addition to saving to a file, the Save method allows you to save an XML document to a new XMLDOMDocument object. In this case, the document is completely processed and, as a result, its structure and syntax are checked. The following shows how to store the document in another object:
Procedure TForm1.Button2Click(Sender: TObject); var XMLDoc2: IXMLDOMDocument; begin XMLDoc2:= CoDOMDocument.Create; XMLDoc.Save(XMLDoc2); Memo2.Lines.Add(XMLDoc2.XML); ... XMLDoc2:= Nil; end;
Finally, the Save method also allows you to save the XML document to other COM objects that support the IStream, IPersistStream, or IPersistStreamInit interfaces.
Using XSL Templates
When discussing the SelectNodes method of the XMLDOMNode object, we mentioned that it provides a more flexible way to access document branches. The flexibility is that you can specify an XSL template as a criterion for selecting branches. Such templates provide a powerful mechanism for finding information in XML documents. For example, to get a list of all the music CD-ROM titles in our catalog, we could run the following query:
To find out which artists' CDs were released in the US, the query is formed as follows:
Nodes:= Root.SelectNodes('CD/ARTIST');
The following shows how to find the first drive in a directory:
Nodes:= Root.SelectNodes('CD/TITLE');
And last:
Nodes:= Root.SelectNodes('CD/TITLE');
To find Bob Dylan's discs, you can run the following query:
Nodes:= Root.SelectNodes('CD[$any$ ARTIST="Bob Dylan"]/TITLE');
and to get a list of discs released after 1985, we run the following query:
Nodes:= Root.SelectNodes('CD/TITLE');
A more detailed discussion of XSL syntax requires a separate post. To intrigue readers and encourage further research, I will give just one small example of a possible use of XSL. Let's say we need to convert our directory into a regular HTML table. Using traditional methods, we must go through all the branches of the tree and form the corresponding tags for each element received.
Using XSL, we simply create a template (or style sheet) in which we specify what and how to transform. Then we impose this template on our catalog - and you're done: we have the text of the XSL template that converts the catalog into a table (Listing 2).
The code for overlaying the XSL template on our directory looks like this:
Procedure TForm1.Button2Click(Sender: TObject); var XSLDoc: IXMLDOMDocument; begin XSLDoc:= CoDOMDocument.Create; XSLDoc.Load('C:\DATA\DATA.xsl'); Memo2.Text:= XMLDoc.TransformNode(XSLDoc); XSLDoc:= Nil; end;
Concluding our discussion of XSL, it should be said that at present this language is actively used for transformation between different XML documents, as well as for document formatting.
Conclusion
For obvious reasons, it is impossible to cover all the Microsoft XML DOM objects and give examples of their use in one article. Here we have only touched on the main issues of using the XML DOM in applications. In table. Figure 3 shows all the objects implemented in the Microsoft XML DOM.
ComputerPress 12"2000
I welcome everyone! For several years I wrote in Matlab, and then I was impatient to write a program in Delphi.
I need to learn how to work with xml documents. I work in RAD Stiduo XE3. There is a TXMLDocument component, probably known to many Delphi programmers. It seems like he can do a lot. But the problem is that there is no clear documentation and description for it. Help in RAD Studio is garbage, because there is no normal information there; only meager help scattered across the pages on some methods and procedures (without examples and a normal description). Rummaged all Internet. I found only topics on forums with specific tasks, where you have to guess for another hour what this or that line does, associated with accessing the xml file.
I also need a guide to the main functions, procedures and methods used when working with xml. Textbook, manual, description. Or at least "xml in Delphi for dummies". For instance:
To open an xml file, use the XMLDocument1.LoadFromFile("filemane.xml") method, where filename is the file name.
The nodelist variable of type IXMLNode is used to store the list of child elements. To determine this list, use the Xmldocument1.DocumentElement method (where XMLDocument1 is the xml file being examined).
To query the contents of the child element "element1" use the XMLDocument1.DocumentElement.ChildNodes[ "element1"].Text... method.
and in this spirit further on all applied methods, procedures, data types.
Where can I find such manuals/descriptions? Who can help?
If you need a specific task, I will describe it.
I have an xml document like this:
some text
some errortext
Other error text
In the program code we have:
var
...
parent, child1: IXMLNode;
begin
XMLDocument1.LoadFromFile("f:\filename.xml");
XMLDocument1.Active:=true;
.
.
end
What you need to learn to do:
(I apologize in advance if I name the components of the xml document incorrectly)
1. Get the name of the root element (in our case, ltm), as well as a list of its attributes (version, type) and their values ("1.0", "settings").
2. Get the number of elements that are children of the root. In this case, there are 7 of them: templateFiles, dimensions, hotspot, hotspot, data, data, data. Get the names of elements (tags) (templateFiles, dimensions, etc.). After getting the number of elements and learning how to extract their names, I will loop from 0 to count-1 and do what I need.
3. Get the number and list of attributes of the required element. For example, for the hotspot element. The correct answer would be 4 attributes. For the first hotspot element, these will be name, style, scena, ath. For the second - the same, only instead of the ath attribute - the rz attribute.
Note that there are 2 hotspot elements in the file, with different attributes. Here's how to work with them (if there are more than 1 elements of the same name)?
I want so: I receive the list of child elements on rel. to the root one (see point 2), I run a loop through them with for and find the hotspot elements whose name parameter is equal to the required one (say "hs015_2" - there will certainly be one such element). Is there any way to solve this issue without a loop? That is, get the value of the scena attribute for the hotspot element that has name="hs015_2"?
4. Do the above with respect to nodes and elements that are children of children. In my example, a node (child of and parent of and.
If I understand correctly, you need to somehow transfer the contents of the node to type variable IXMLNode and do the same as in paragraphs 1-3. So?
5. You need to learn how to change the above parameters (set your own).
It seems that's all for now. At this stage, syntactic constructions are the most important for me.
Who owns this topic, please write other syntactic constructions to solve the above questions (how to get attributes, their number, number of elements, their names, etc.). The main thing now is to master the syntax, and I will implement my algorithm later. Many thanks in advance to everyone!
P.S. I really would not want to write my own XML parser from scratch just because there is no normal description for the existing ones.