<?xml version="1.0" encoding="ISO-8859-2"?>
<!DOCTYPE zprava SYSTEM "techrep.dtd">

<zprava cislo="22/2003" jazyk="en">
<nazev>XML parser API library for Netopeer</nazev>
<autor>Petr Novák</autor>
<datum>15. 11. 2003</datum>


<h1>Motivation</h1>

<p>The Netopeer router configuration system has several front-ends that use the same operations on a XML document. This API library provides a parser independent (this is very useful, because XML is a new technology and parsers have not stable API, some their functions do not conform to W3C standards or their behaviour is slightly different from what we need) and implementation/reimplementation of some methods we need (e. g., other devide elements, id generating, validation etc.).</p>

<p>This library wraps the current XML parser (Libxml2 at this time) and provides all the methods we need for front-ends. Front-ends can use a direct access to the Libxml2 library or work with the XML document using another parser library, but it is not recommended, because the parser independence is then lost.
</p>

<obr src="picture">Component hierarchy</obr>

<h1>Description</h1>
<p>API library provides the following methods for working with the XML
document:</p>
<ul>
<li>Basic operations on XML files (open, create, modify and write).</li>
<li>On-demand validation (e. g., for verification before writing or after adding some new nodes).</li>
<li>Finding elements and attributes in the document using the XPath.</li>
<li>DTD and Relax NG support.</li>
</ul>

<p>XML tags are divided into these groups:</p>
<ul>
<li>Document</li>
<li>Element</li>
<li>Attribute</li>
</ul>

<h1>Detailed description</h1>

<h2>Schema support</h2>

<p>API supports DTD and Relax NG. Relax NG is used implicitly, if DTD is used, a <tt>DTD</tt> directive must to be defined:</p>
<pre>#define DTD</pre>
<p><i>Note:</i> The current Netopeer schema is defined using DTD, so the DTD directive is defined in the API library header file (<soubor>parser.h</soubor>). It will be removed in the future.</p>

<h2>Data types and constants</h2>
<dl>
<dt><tt><b>TExceptionSubType</b></tt></dt>
<dd>	Contains all kinds of exceptions. Available values are:<br/>
	NO_ERROR<br/>
	API_EXCEPTION For bad parameters of API library methods call.<br/>
	PARSER_ERROR For some errors in the parser library (initialization errors etc.) - Libxml2 at this time.<br/>
	UNDEFINED_ERROR</dd>

<dt><tt><b>TExceptionType</b></tt></dt>
	<dd>Type of an exception. All types are contained in the header file <soubor>parser-exception.h</soubor>.</dd>

<dt><tt><b>TException</b></tt></dt>
	<dd>Class representing exception that was raised in the parser API library and programs using this library.</dd>

<dt><tt><b>TDocument</b></tt></dt>
	<dd>Class representing whole XML document.</dd>

<dt><tt><b>TElement</b></tt></dt>
	<dd>Class representing the XML element.</dd>

<dt><tt><b>TAttribure</b></tt></dt>
	<dd>Class representing the XML attribute.</dd>

<dt><tt><b>TElementsList</b></tt></dt>
	<dd>Vector of the items of TElement.</dd>

<dt><tt><b>TAttributesList</b></tt></dt>
	<dd>Vector of the items of TAttribute.</dd>
</dl>

<h2>Classes overview</h2>

<h3>TException</h3>
<p><b>Purpose:</b> Error reporting.</p>
<p><b>Description:</b> Provides exceptions (error messages) from the API library (e. g., an incorrect value in some method), current parser (Libxml2 at this time) and unidentified errors. Each exception has its own exception subtype (what kind of an exception it is), type (error number) and a text message.<br/>
All exception types and subtypes are listed in the header file <soubor>parser-exceptions.h</soubor>.</p>
<p><b>Methods:</b></p>
<dl>
<dt><tt><b>TException</b>(const string text Message, const TExceptionSubType subType, const TExceptionType type)</tt></dt>
	<dd>Constructor. This method is used for raising an exception in the API library.</dd>

<dt><tt>string <b>getMessage</b>(void)</tt></dt>
	<dd>Returns the text exception (error) message.</dd>

<dt><tt>TExceptionSubType <b>getSubType</b>(void)</tt></dt>
	<dd>Returns the exception subtype (what kind of exception it is).</dd>

<dt><tt>TExceptionType <b>getType</b>(void)</tt></dt>
	<dd>Returns the exception type (error number).</dd>
</dl>


<h3>TDocument</h3>
<p><b>Purpose:</b> Operations on the whole XML document.</p>
<p><b>Description:</b> Includes methods for working with the whole document,
such as creating a new document, open an existing document, writing a document
to the file and validating it.</p>
<p>It supports an automatic id attribute generation for each created element.
The name of the id attribute can be changed by setting the <tt>ID</tt> const in
the <soubor>parser.h</soubor> header file (implicit name is '<tt>id</tt>'). The
value is an integer number.</p>
<p><i>Note:</i> The sequence of id attribute values need not allways be increasing. If any elements are removed, their id values are marked as empty in the next parsing of the document and are used at creating the new elements.
</p>
<p><b>Methods:</b></p>
<dl>
<dt><tt><b>TDocument</b>(const string DocumentName, const string GlobalGrammarPath, const string LocalGrammarPath)</tt></dt>
	<dd>Constructor for creating the new document.<br/>
	<i>Note:</i> You must enter only one of the schema paths.</dd>

<dt><tt><b>TDocument</b>(const string XMLFilePath, const string GrammarPath)</tt></dt>
	<dd>Constructor for parsing an existing document. If the document is using DTD as its schema, the second parameter cannot be set (DTD must be defined in the XML document).</dd>

<dt><tt><b>&vlnka;TDocument</b>(void)</tt></dt>
	<dd>Destructor.<br/>
	<i>Note:</i> If this destructor is used, the entire document is erased and all elements linking to some part of this document became unreachable.</dd>

<dt><tt>void <b>write</b>(const string XMLFileName)</tt></dt>
	<dd>Writes the document to the file. If the XMLFileName is entered, the document is saved to the file with this name, otherwise the file name is the internal document name (If the document was parsed from file, its file name becomes the internal document name. If the document was created as a new, the internal name of the document is a root element name with <soubor>.xml</soubor> suffix.).<br/>
	<i>Note:</i> Validation is not executed in this method. You must call it yourself before writing.</dd>

<dt><tt>bool <b>validate</b>(TElement &amp;badElement, TAttribute &amp;badAttribute)</tt></dt>
	<dd>Returns true, if the document is valid according to the schema (DTD or Relax NG). If the document is not valid, first non-valid element or first non-valid attribute is returned as a parameter. Always only one of them is returned, the second is empty (you can use <tt>exist</tt> method to check it). If the document is valid, both parameters are empty. When the document is not valid and the error is somewhere else than in some element or attribute, both parameters are empty too.</dd>

<dt><tt>TElement <b>getRootElement</b>(void)</tt></dt>
	<dd>Returns the root element of the document.</dd>
</dl>


<h3>TElement</h3>
<p><b>Purpose:</b> Provides operations on a single XML element.</p>
<p><b>Description:</b> Includes elementary operation for reading element information, editing it, editing element attributes and searching elements.<br/>
<i>Note:</i> The term element in this context realy means an XML element (i. e., not node with an attribute, CDATA, processing instruction or other type).</p>
<p><b>Methods:</b></p>
<dl>
<dt><tt><b>TElement</b>(void)</tt></dt>
	<dd>Implicit constructor.</dd>

<dt><tt>void <b>blank</b>(void)</tt></dt>
	<dd>Cleans current TElement instance and sets it to an empty.<br/>
	<i>Note:</i> It cleans just a link from the current TElement instance. If you can erase the real element from the XML document, use <tt>erase</tt>.<br/>
	Before using a cleared TElement instance, you must assign it a new value first.</dd>

<dt><tt>bool <b>exist</b>(void)</tt></dt>
	<dd>Returns true if the current TElement instance is not empty.</dd>

<dt><tt>string <b>getName</b>(void)</tt></dt>
	<dd>Returns a working element name.</dd>

<dt><tt>string <b>getValue</b>(void)</tt></dt>
	<dd>Returns the character data content of the  working element. Subelements and their contents are not included. In the case of a mixed content, the text nodes of the working element, which are interspersed by subelements, are concatenated and retured. All whitespace are preserved.<br/>
	For example, consider the following part of the XML document:<br/>
	<blockquote><pre>
	&lt;element1&gt;
		value_part1
		&lt;element2&gt;
			another_value
		&lt;/element2&gt;
		value_part2
	&lt;/element1&gt;
	</pre></blockquote>
	If we call getValue for the element <tt>element1</tt>, we
        obtain:<blockquote><pre>
	<![CDATA[
		value_part1



		value_part2]]>
	</pre>
	</blockquote></dd>

<dt><tt>void <b>setValue</b>(const string Value)</tt></dt>
	<dd>Sets the character data value of the working element.<br/>
	<i>Note:</i> It removes all existing text nodes in this element and creates a single new text node with the given value.</dd>

<dt><tt>bool <b>hasChild</b>(void)</tt></dt>
	<dd>Returns true if the working element has any child elements.<br/>
	<i>Note:</i> Child element in this context means only an XML element, not attribute node, text node, processing instruction etc.</dd>

<dt><tt>TElementsList <b>getChilds</b>(const string ChildName)</tt></dt>
	<dd>Returns child elements of the working element. If ChildName is specified, only elements with this name are returned.<br/>
	<i>Note:</i> Child element in this context means only an XML element, not attribute node, text node, processing instruction etc.</dd>

<dt><tt>TElement <b>parentElement</b>(void)</tt></dt>
	<dd>Returns a parent element of the working element.<br/>
	If this method is called on the root element, it returns an empty element.</dd>

<dt><tt>void <b>erase</b>(const TElement)</tt></dt>
	<dd>Erases the selected child element of the working element. All its childs are erased too.</dd>

<dt><tt>TElement <b>create</b>(const string ElementName, const bool CreateId)</tt></dt>
	<dd>Creates a new child element of the working element and returns it. If CreateId is true, id attribute with the unique id for this new element is created.</dd>

<dt><tt>TElement <b>createBefore</b>(const TElementsList ElementsBefore, const string ElementName, const bool CreateId)</tt></dt>
	<dd>Creates a new child element of the working element and returns it. If CreateId is true, id attribute with the unique id for this new element is created.<br/>
	This created element is inserted before all elements in the ElementsBefore. If the ElementsBefore list is empty, the created element is inserted as the first child element of the working element.</dd>

<dt><tt>TElementsList <b>find</b>(const string XPath)</tt></dt>
	<dd>Finds items through the XPath expression in the XML tree.<br/>
	The search context starts at the the current element. Use an absolute path in the XPath expression if you want to search the entire document.</dd>

<dt><tt>TAttribute <b>getAttribute</b>(const string AttributeName)</tt></dt>
	<dd>Gets an selected attribute of the working element.</dd>

<dt><tt>TAttributesList <b>getAttributes</b>(void)</tt></dt>
	<dd>Gets a list of all attributes of the working element.</dd>

<dt><tt>TAttribute <b>createAttribute</b>(const string AttributeName, const string AttributeValue)</tt></dt>
	<dd>Creates a new working element attribute with the given name and value.</dd>

<dt><tt>void <b>eraseAttribute</b>(const TAttribute ErasedAttribute)</tt></dt>
	<dd>Erases the selected attribute of the working element.</dd>

<dt><tt>string <b>getAttributeValue</b>(const string AttributeName)</tt></dt>
	<dd>Returns the value of the selected attribute of the working element.</dd>

<dt><tt>void <b>setAttributeValue</b>(const string AttributeName, const string AttributeValue)</tt></dt>
	<dd>Sets the value of the selected attribute in the working elemnet.<br/>
	If the attribute does not exist, it is created.</dd>
</dl>


<h3>TAttribute</h3>
<p><b>Purpose:</b> Provides an operation for attribute management.</p>
<p><b>Description:</b> Includes an elementary operations for reading attribute information and editing it.</p>
<p><b>Methods:</b></p>
<dl>
<dt><tt><b>TAttribute</b>(void)</tt></dt>
	<dd>Implicit constructor.</dd>

<dt><tt>void <b>blank</b> (void)</tt></dt>
	<dd>Cleans current TAttribute instance and sets it to empty.<br/>
	<i>Note:</i> It cleans just a link from the current TAttribute instance. If you want to erase a real attribute from am XML document, use <tt>eraseAttribute</tt> on the parent element<br/>
	Before using a cleared TAttribute instance, you must assign it a new value first</dd>

<dt><tt>bool <b>exist</b> (void)</tt></dt>
	<dd>Returns true if the current TAttribute instance is not empty.</dd>

<dt><tt>string <b>getName(void)</b></tt></dt>
	<dd>Returns the attribute name.</dd>

<dt><tt>string <b>getValue(void)</b></tt></dt>
	<dd>Returns the attribute value.</dd>

<dt><tt>void <b>setValue</b>(const string Value)</tt></dt>
	<dd>Sets the value of the attribute. Whitespace in the value is normalized automatically.</dd>
</dl>

<h1>Installation</h1>

<h2>Requirements</h2>
<p><b>Platform:</b> C++ (tested on g++ 3.2.0)</p>
<p><b>Parser:</b> Libxml2 version 2.5.0 and greater (tested on Libxml2-2.5.11)</p>

<h2>Description of the files</h2>
<p><soubor>parser.cpp</soubor> - API library souce code</p>
<p><soubor>parser.h</soubor> - API library header file</p>
<p><soubor>parser-exception.h</soubor> - API library exception list</p>
<p><soubor>Makefile</soubor></p>

<h2>Preparation for the installation</h2>
<p>You must set the LIBXML2 variable in the Makefile to the path where you have installed Libxml2.</p>

<h2>Installation</h2>
<p>Now you can compile the API library using:</p>
<p><vstup>$ make</vstup></p>
<p>This will create the shared library <soubor>libparser.so.0.0.1</soubor> in the current directory and the symbolic link to it named <soubor>libparser.so.0</soubor>. You can erase an temporary object file using:</p>
<p><vstup>$ make clean</vstup></p>

<h1>Using</h1>
<h2>Changing the behaviour</h2>
<p>You can change the schema and the name of the id attribute that is generated for a new elements. Both are specified and can be changed in the header file <soubor>parser.h</soubor>. It must be done before the compilation.</p>

<h2>Your source code</h2>
<p>You must import the API library header file using</p>
<pre>#include "path/parser.h"</pre>
<p>or</p>
<pre>#include &lt;path/parser.h&gt;</pre>
<p>it you have it in the standard header files directory.</p>

<p><i>Note:</i> Some methods can raise an exception if they are called with bad parameters or Libxml2 is not correctly compiled. You must catch it or your program will be terminated.</p>

<h2>Your source code compilation</h2>
<p>This library can be compiled using the usual procedure, you must only set the path to the header files and libraries of the Libxml2, if you do not have it in the standard directories.</p>

<h1>Conclusion</h1>
<p>The actual syntax is documented in the header file <soubor>parser.h</soubor>.</p>

</zprava>
