1
Q. | How to install XMLParser component? |
A. |
|
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. 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. 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. 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. 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? |
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. |
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. |
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.
|