| xHarbour Reference Documentation > Class Reference (textmode) |
![]() |
![]() |
![]() |
Creates a new TXmlDocument object.
TXmlDocument():new( [<nFileHandle>|<cXmlString>], [<nStyle>] ) --> oTXmlDocument
Constants for XML object creation
| Constant | Value | Description |
|---|---|---|
| HBXML_STYLE_INDENT | 1 | Indents XML nodes with one space |
| HBXML_STYLE_TAB | 2 | Indents XML nodes with tabs |
| HBXML_STYLE_THREESPACES | 4 | Indents XML nodes with three spaces |
| HBXML_STYLE_NOESCAPE | 8 | Reads and creates unescaped characters |
| in data sections |
Note: when the style HBXML_STYLE_NOESCAPE is set, the textual content enclosed in an opening and closing XML tag is scanned for characters that normally must be escaped in XML. This can lead to a considerable longer time for reading the XML data.
The characters to be escaped are single and double quotes ('"), ampersand (&), and angled brackets (<>). If such characters exist in textual content and are not escaped, a parsing error is generated, unless HBXML_STYLE_NOESCAPE is used.
Function TXmlDocument() creates the object and method :new() initializes it.
The TXmlDocument() class provides objects for reading and creating XML files. XML stands for eXtensible Markup Language which is similar to HTML, but designed to describe data rather to display it. To learn more about XML itself, the internet provides very good free online tutorials. The website www.w3schools.com is is a good place to quickly learn the basics on XML.
A TXmlDocument object maintains an entire XML document and builds from it a tree of TXmlNode() objects which contain the actual XML data. The first XML node is stored in the :oRoot instance variable, which is the root node of the XML tree. Beginning with the root node, an XML document can be traversed or searched for particular data. The classes TXmlIteratorScan() and TXmlIteratorRegEx() are available to find a particular XML node, based on its tag name, attribute or data it contains.
| See also: | TXmlIterator(), TXmlIteratorRegEx(), TXmlIteratorScan(), TXmlNode() |
| Category: | Object functions , xHarbour extensions |
| Header: | hbxml.ch |
| Source: | rtl\txml.prg |
| LIB: | xhb.lib |
| DLL: | xhbdll.dll |
Creating an XML file
// The example uses the Customer database and creates an XML file
// from it. The database structure and its records are written
// to different nodes in the XML file. The basic XML tree is this:
//
// <database>
// <structure>
// <field .../>
// </structure>
// <records>
// <record>
// <fieldname> data </fieldname>
// </record>
// </records>
// </database>
#include "hbXml.ch"
PROCEDURE Main
LOCAL aStruct, aField, nFileHandle
LOCAL oXmlDoc, oXmlNode, hAttr, cData
LOCAL OXmlDatabase, oXmlStruct, oXmlRecord, oXmlField
USE Customer
aStruct := DbStruct()
// Create empty XML document with header
oXmlDoc := TXmlDocument():new( '<?xml version="1.0"?>' )
// Create main XML node
oXmlDatabase := TXmlNode():new( , "database", { "name" => "CUSTOMER" } )
oXmlDoc:oRoot:addBelow( oXmlDatabase )
// copy structure information to XML
oXmlStruct := TXmlNode():new( , "structure" )
oXmlDataBase:addBelow( oXmlStruct )
FOR EACH aField IN aStruct
// store field information in XML attributes
hAttr := { "name" => Lower( aField[1] ), ;
"type" => aField[2], ;
"len" => LTrim( Str(aField[3]) ), ;
"dec" => LTrim( Str(aField[4]) ) }
oXmlField := TXmlNode():new(, "field", hAttr )
oXmlStruct:addBelow( oXmlField )
NEXT
// copy all records to XML
oXmlNode := TXmlNode():new( , "records" )
oXmlDataBase:addBelow( oXmlNode )
DO WHILE .NOT. Eof()
hAttr := { "id" => LTrim( Str( Recno() ) ) }
oXmlRecord := TXmlNode():new( , "record", hAttr )
FOR EACH aField IN aStruct
IF aField[2] == "M"
// Memo fields are written as CDATA
cData := FieldGet( Hb_EnumIndex() )
oXmlField := TXmlNode():new( HBXML_TYPE_CDATA , ;
Lower( aField[1] ), ;
NIL , ;
cData )
ELSE
// other fields are written as normal tags
cData := FieldGet( Hb_EnumIndex() )
cData := Alltrim( CStr( cData ) )
oXmlField := TXmlNode():new( HBXML_TYPE_TAG , ;
Lower( aField[1] ), ;
NIL , ;
cData )
ENDIF
// add field node to record
oXmlRecord:addBelow( oXmlField )
NEXT
// add record node to records
oXmlNode:addBelow( oXmlRecord )
SKIP
ENDDO
// create XML file
nFileHandle := FCreate( "Customer.xml" )
// write the XML tree
oXmlDoc:write( nFileHandle, HBXML_STYLE_INDENT )
// close files
FClose( nFileHandle )
USE
RETURN
Reading an XML file
// This example uses the Customer.xml file created in the
// prevous example and extracts from it the structure definition
// for the Customer.dbf file.
PROCEDURE Main
LOCAL oXmlDoc := TXmlDocument():new()
LOCAL oXmlNode, aStruct := {}
oXMlDoc:read( Memoread( "customer.xml" ) )
oXmlNode := oXmlDoc:findFirst()
? oXmlNode:cName
oXmlNode := oXmlDoc:findFirst( "structure" )
? oXmlNode:cName
oXmlNode := oXmlDoc:findFirst( "field" )
DO WHILE oXmlNode <> NIL
// attributes are stored in a hash
AAdd( aStruct, { oXmlNode:aAttributes[ "name" ] , ;
oXmlNode:aAttributes[ "type" ] , ;
Val( oXmlNode:aAttributes[ "len" ] ), ;
Val( oXmlNode:aAttributes[ "dec" ] ) } )
oXmlNode := oXmlDoc:findNext()
ENDDO
AEval( aStruct, {|a| Qout( ValToPrg(a) ) } )
RETURN
Escape characters in XML
// The example demonstrates the effect of HBXML_STYLE_NOESCAPE
// when XML code is created.
#include "hbXml.ch"
PROCEDURE Main
LOCAL oXmlDoc, oXmlNode
oXmlDoc := TXmlDocument():new( '<?xml version="1.0"?>' )
oXmlNode:= TXmlNode():new( , "text", , [this must be escaped: "'&<>] )
oXmlDoc:oRoot:addBelow( oXmlNode )
? oXmlDoc:toString()
** output:
// <?xml version="1.0"?>
// <text>this must be escaped: "'&<></text>
? oXmlDoc:toString( HBXML_STYLE_NOESCAPE )
** output:
// <?xml version="1.0"?>
// <text>this must be escaped: "'&<></text>
RETURN
http://www.xHarbour.com