XMLParser FAQ

 

Installation

Use

Environment

License


 

Installation

1
Q.

How to install XMLParser component?

A.
    Installation steps:
  1. Select menu Component/Install packages
  2. Press Add button and select file parsdpk.bpl
  3. Press Ok button
  4. Modify LibraryPath: menu Tools/Environment options/Library

 

Use

1
Q.

How to create XMLParser component at runtime?

A.

Here is a sample:

var parser : TIcXMLParser;
begin
  parser := TIcXMLParser.Create(nil);
  try
    ... // do something
  finally
    parser.Free;
  end;
end;

Constuctor has one parameter. This is component's owner. If component is created at runtime and owner is not specified, then it must be disposed manually.

2
Q.

How to create xml document from xml file?

A.

You shold use one of two Parse methods. Parsing gets xml data from input and generates xml document in memory. Source of xml data can be file or stream.

function Parse(FileName : string; var doc : TIcXMLDocument) : boolean;
function Parse(Stream : TStream; var doc : TIcXMLDocument) : boolean; 
var 
  doc : TIcXMLDocument;
  fileName : string; 
begin
  try
    XMLParser.Parse(fileName,doc);
  finally
    doc.Free;
  end;
end;

If parsing was successful, then new document is created and it should be disposed manually at the end of program. If existing document is passed to parse method, then it is cleared first (all nodes are removed). When parsing failed empty document is returned.

Caution: XMLDocument does not heave to be created before parsing, but it must be disposed at the end of program.

3
Q.

What returns TIcXMLParser.Parse function?

A.

Result of Parse function has meaning only if validation occurs after parsing (when ValidateDocument property is set ot true). These two source fragments are equivalent:

XMLParser.ValidateDocument := true;
result := XMLParser.Parse('file.xml',doc); 
XMLParser.ValidateDocument := false;
XMLParser.Parse('file.xml',doc);
result := XMLParser.Validate(doc); 

4
Q.

How to parse data stored in a String (not StringList)? How can I do this with your component?

A.

XMLParser component accepts data from two inputs: file and stream. You can create TStringStream and use method Parse(Stream : TStream; doc : TIcXMLDocument). Here is a sample

var stream : TStringStream;
    xmlParser : TIcXMLParser;
    doc : TIcXMLDocument;
    input : string;
begin
  ...
  stream := TStringStream.Create(input);
  try
    xmlParser.Parse(stream,doc);
  finally
    stream.Free;
  end;
end;

5
Q.

How to validate xml document?

A.

You should use TIcXMLParser.Validate function with XMLDocument or automatically validate document after parsing by setting TIcXMLParser.ValidateDocument property to true.

See question 3

6
Q.

How to obtain list of validation errors?

A.

If document is not valid, then property ValidationErrors contains all errors. ValidationErrors is a list of TIcError objects. Single error object contains error message and reference to node, which returned this error. You can simply display list of error messages in a list box and access node, on which occured error, by clicking on some message in list.
Below is a sample:

var 
  doc : TIcXMLDocument;
  isValid : boolean;
  lbErrors : TListBox;
begin
  ...
  isValid := XMLParser.Validate(doc);
  if isValid
    then ShowMessage('Document is valid')
    else begin
	  XMLParser.ValidationErrors.CreateMessagesList(lbErrors.Items);
      ShowMessage('Document is not valid');
    end;
end;

Method CreateMessagesList copies messages from ValidationErrors into specified string list.

If you want to assign error objects to items in string list you should scan ValidationErrors list manually. Then you can access node which returns error.

var failedNode : TIcXMLNode;
begin
  failedNode := TIcError(XMLParser.ValidationErrors[lbErrors.ItemIndex]).Node;
end;

7
Q.

How can I access the 2nd or 3rd node (in sample below) directly without recursive functions? I would like a function that returns TIcXMLNode as result so I can do what I want with it later!

<r2setup>
  <users>
    <user>...</user>
    <user>...</user>
    <user>...</user>
  </users>
</r2setup>
A.

There is solution for this problem, but accessing elements by index is slower than recursive accessing (every element has pointer to its next element). First you should use GetChildern method of TIcXMLElement class. It returns list of child elements for calling element.

procedure TIcXMLElement.GetChildren(nl : TIcNodeList);

Node list should be created before and disposed after using, because elements in list are copies, not references. Then you can access every element in the list with method Item.

function TIcNodeList.Item(Index : integer; NodeType : byte) : TIcXMLNode;

Node type for TIcXMLElement is ntElement. First node in list has index 1.
There is sample solution of this problem.

var doc : TIcXMLDocument;
    nl : TIcNodeList;
    e,c1,c2,c3 : TIcXMLelement;
begin
  e := doc.GetDocumentElement.GetFirstChild; // returns 'users' el element
  nl := TIcNodeList.Create;
  try
    e.GetChildren(nl); // returns list of 'users' children
        
    c1 := nl.Item(1,ntElement); // first child in the list
    c2 := nl.Item(2,ntElement); // second child in the list
    c3 := nl.Item(3,ntElement); // third child in the list
    ...
  finally
    nl.Free; // finally free nodelist
  end;
end;

8
Q.

Am I right that the function to retrieve the value between <TAG> and </TAG> is GetValue?! If so, what does TAG1.GetValue return in the following case?

<TAG1>
  This is a test
  <TAG2>
    Another Test
  </TAG2>
  ... the second part
</TAG1>
A.

No, it isn't true. Every node of XML document inherits from TIcXMLNode and has two properties: name and value. Some nodes (like element) has valid only name property and value is undefined; some has valid only value property (like character data) and attributes nodes have both properties (attribute has name and value). So, character data (data between two tags) aren't value of element node. This is independent node. You can access this value by calling element node's method GetFirstCharData or GetCharData(index). Element can have more than one data nodes like in this sample:

<e>
  char data1
  <child1/>
    char data2
  <child2/>
</e>

In your sample GetValue for element returns empty string, because elements hasn't value.
Below is sample code how to obtain all nodes in your sample xml document:

var text1, text2 : TIcXMLText;
    el1,el2,el3 : TIcXMLElement;
begin
  el1 := doc.GetDocumentElement; // returns root element "e"
  text1 := el1.GetFirstCharData; // returns character data node
  text1.GetValue; 		 // returns "char data1" string
  el2 := el1.GetFirstChild;      // returns element "child1" (child of "e")
  text2 := el2.GetFirstCharData; // returns character data node
  text2.GetValue;		 // returns "char data2"
  el3 := el2.NextSibling;        // returns element "child2" 
end;

9
Q.

How to access all elements from content model? Method TContent Model.GetChildList.Item(x,0) does not return all elements, some are ignored.

A.

Accessing nodes from content model in this way may give unexpected result. More effective way to access nodes from Nodelist (especially when you iterate whole list) is moving from one node to next. It is sole safe way (at this time) to access nodes from content model. Below is example how to use this:

var
  nl : TIcNodeList;
  node : TIcXMLNode;

begin
  nl := doc.GetDocumentType.GetElementDecl('some_element').GetContentModel.GetChildList;

  node := nl.GetFirst;
  while node <> nil do
    begin
      node.GetName; // name of element in content model
      node := node.Next;
    end;
end;

You can access nodes with specified type using methods GetRoot(nodeType) and NextSibling instead of GetFirst and Next.

10
Q.

How to specify an external DTD for XML document? The only function I found that looked like it might be what I need is SetDocumentType, but it takes an TIcDocumentType object which has no way of referring to an external DTD.

A.

You can assign external DTD by specifying system literal for DTD. TIcDocumentType uses method SetSystemLiteral derived from TIcExternalNode to do this. Assigned external DTD is immediately parsed.
Caution: You should assign dtd to xml document before setting system literal.

 
doc := TIcXMLDocument.Create;
dtd := TIcDocumentType.Create('root',doc);
// assigns dtd to document
doc.SetDocumentType(dtd);
// specifies external dtd and parses it
dtd.SetSystemLiteral('external.dtd');

11
Q.

Is there any property I can set to leave spaces before and after the equal sign in attribute definition?
I would like to write attribute like: <anelement attribute="value"/>

A.

Formatting of xml attributes is hardcoded in component and there is no possibility to change it.

12
Q.

I get Access Violation error, when I'm trying to set system literal for DTD.

A.

When method SetSystemLiteral assigns system literal do DTD, linked DTD content is immediately parsed and attached to xml document. These operations require existing document. Therefore DTD node should be attached to xml document first, then system literal can be set.

See question 10

13
Q.

What is necessary to add another encoding schema to the xml parser

A.

To add new encoding schema to XMLParser it is necessary to widen enumerated type and two tables in IcCodePages.pas file.

TEncoding - enumerated type of all supported encodings. New item has to be added after US_ASCII and before UTF_8 encoding (because two last items UTF_8 and UTF_16 aren't in conversion table).

cps - array containing names for encodings

iso - array containing conversion tables for every encoding. There are proper unicode chars for every char from given encoding (from #00 to #FF).

14
Q.

How to get element value? I used TIcXMLElement.GetValue method, but it doesn't work. I have such xml document:

<element>
  element value
</element>
A.

Text between opening and closing tags isn't value of xml element. It is another xml node - character data. Character data are represented by TIcXMLText node. In xml document structure this node is child of element containig it. So, to get value of character data you should use method TIcXMLText.GetValue. First you have to get XMLText node with TIcXMLElement.GetFirstCharData method.

XMLElement nodes don't have value, only name. XMLText nodes have valid only value, don't have name.

See question 8

15
Q.

Is it possible to validate XML documents versus schema (XSD) with XMLParser component?

A.

It isn't possible to validate XML documents versus XSD schema using our XMLParser component. We don't plan to support this validation schema.

16
Q.

Is it possible to include the reference to a stylesheet file (<?xml:stylesheet ...> ) and the reference to a DTD file ( <!DOCTYPE ....>) in the header of an XML file produced with the IcXMLDocument object ?

A.

Stylesheets are not supported with XMLParser. Reference to DTD file can be included in xml file.

See question 10

17
Q.

How to create XMLDocument from scratch and write it back out?

A.

Below is a sample code, explaining how to create XMLDocument.

var doc : TIcXMLDocument;
    test,item : TIcXMLElement;
    parser : TIcXMLParser;
begin
  parser := TIcXLMParser.Create(nil);			// create XMLParser component if it wasn't created at design-time

  doc := TIcXMLDocument.Create;				// create XMLDocument
  doc.AssignParser(parser);                   		// associate XMLDocument with XMLParser component
  test := doc.CreateElement('test');			// create element 'test'
  doc.SetDocumentElement(test);				// set element 'test' as root element of XMLDocument
  item := doc.CreateElement('item');			// create element 'item'
  test.AppendChild(item);     				// set element 'item' as child of 'test'
  item.SetAttribute('attribute','value');		// set attribute for element 'item'
  item.SetCharData(doc.CreateTextNode('sample text'));  // create character data and appends it to 'item'

  doc.Write('file.xml');				// write XMLDocument to file

  doc.Free;
  parser.Free;
end;

This sample creates file 'file.xml' with the following content:

<?xml version = "1.0"?>

<test>
   <item attribute = "value">sample text</item>
</test>

18
Q.

How to add new XMLElement as a sibling of another one?

A.

You have to use AppendChild method for parent of XMLElement, which is on the same level like new.

  TIcXMLElement(e1.GetParent).AppendChild(e2);

Element e2 will be sibling of element e1.

19
Q.

Why I get an access violation when I try to write XMLDocument to file?

A.

XMLDocuments needs XMLParser component for some operations (like writting to file, setting system literal, etc.). Method TIcXMLDocument.AssignParser associates xmlDocument with xmlParser. When document is creatd by parsing file it is associated automatically with xmlParser, but manually created documents need to call this method.

  doc := TIcXMLDocument.Create;
  doc.AssignParser(XMLParser);
  // now we can write to file
  doc.Write('file');

In the verion 2.4.11 you get message box with information about this instead of exception information.

20
Q.

Does destructor of XMLDocument dispose memory of all document's elements?

A.

XMLDocument disposes memory of all nodes (elements, comments, attributes) wich are attached to it. If you create xmlelement and append to document (with method AppendChild), then you don't need to dispose it (because xmldocument do this).

var doc : TIcXMLDocument;
    e : TIcXMLElement;
begin
  xmlParser.Parse('file.xml',doc);
  e := doc.GetDocumentElement;

  // do something

  doc.Free;
end;  

In sample above element e can't be disposed manually, because it is contained in xmldocument and will be disposed by this document

Caution: XMLDocument is created by XMLParser in this sample and should be disposed.

 

Environment

1
Q.

I'm using Your free XMLParser version 2.4.x.0 for Delphi 5.0 and it doesn't work under Windows 95 second edition.

A.

This problems occurs, when you want to use 16-bit parser under Windows 95. XMLParser working in this mode uses internally unicode characters, but Windows 95 doesn't support unicode. If you want to use XMLParser under Windows 95, you should use 8-bit version. Under Windows 98 or NT you can use both versions.

 

License

1
Q.

I downloaded XMLParser component from internet, but there isn't source code. Why?

A.

Source code is available only for registered users, who bought XMLParser component.

2
Q.

Are there any limitations in free version of XMLParser component?

A.

Free version is fully functional. It doesn't contain source code.

3
Q.

How can I buy XMLParser component?

A.

Please visit our web page at address: www.icom-dv.de

4
Q.

Are future upgrades included in the price or there will be a special upgrade price from one version to the other?

A.

All upgrades are included in the buy price.