Class: cXMLDOMDocument

Properties  Events  Methods    Index of Classes

Provides the Interface to the root node of an XML document

Hierarchy

cObject
---BaseXmlDomNode
------BaseXmlDomDocument
---------cXMLDOMDocument

Library: Common (Windows and Web Application) Class Library

Package: Flexml.pkg

Mixins: cXMLDOMNodeMixin cXMLDOMMixin

Description

The cXMLDOMDocument class provides the Interface to the root node of an XML document. It includes methods and properties used to obtain or create all other XML objects. An object of the cXmlDomDocument class is a grouping of nodes that logically describe an XML document. There is a root element, from which all other elements descend in a tree-like structure.

The cXMLDOMDocument class is your starting point for XML processing. Normally you create a cXMLDOMDocument and then create all of your other XML node objects dynamically, destroying those nodes when they are no longer needed. This section contains a good deal of introductory material designed to guide you through all of the XML classes and messages. This section is divided into the following sections:


XML Basics - an XML Overview


Examples - XML Sample code


None of the above examples demonstrate how to handle XML documents that use namespaces. For information about XML documents with namespaces refer to: Processing XML Documents with Namespaces.


XML Basics


Introduction

Extensible Markup Language (XML) is a markup language for describing structured data in a text file or elsewhere. It is not the purpose of this Help to describe the theory of XML, but rather the DataFlex support for it. There are many good books written on XML which you can find in local bookstores and the local library. In addition, you can find much information on the Internet.

DataFlex supports XML through an interface consisting of several classes, which allow you to access elements in an XML document; work on them, then save them back into the document. Each element you request is returned as a fully-formed DataFlex Object for you to work on. When you are done, it is saved back into the document.

The top-level DataFlex interface is simple and powerful but, for advanced use, you can also access the lower levels if you wish. For this reason, all the classes and messages are given here, but you can often achieve the results you want by using only the top-level interface.


XML Essentials

The following is a very brief reminder of the essentials you need to keep in mind when using the XML classes.

While Hypertext Markup Language (HTML) specifies how to display data in a browser (e.g. bold or italic), XML defines the content of the data as elements (e.g. Name and Address). In XML, you then use stylesheets to describe the presentation. You can then use different stylesheets and applications to present and process the same data differently in different browsers.

The structure of an XML document can be implied through its contents, or it can be formally defined, either by a Document Type Definition (DTD) or by a Schema. A DTD describes the rules of the document it accompanies, whereas a Schema is an extensible language which users can augment with additional information such as data types, inheritance, and presentation rules.

Data sent with a DTD or Schema is known as "valid XML". As long as it follows a few rules, data sent without a DTD or Schema is known as "well-formed" and implicitly describes itself. The rules are: Each start tag must have a corresponding end tag (and tags are case-sensitive); Elements must not overlap; Certain characters (<, >) cannot be used without special treatment, and each XML document must have a unique root element.

In HTML, there is always a single Document object, which always has one or more Forms child objects, each of which has a single Images Collection child object. In XML, there is no advance knowledge of the structure of a document, and objects can be named anything you like. For this reason, XML documents are thought of as trees, with multiple nodes. Some will have no children of their own, and some will have collections of other nodes as children. A Node can only have one parent, and either zero or one collection of children. Some nodes can also have attributes, and each such attribute is itself a node..

There are various types of nodes, such as Text, Element, Comment, Entity Reference, Processing Instructions.

Some types of node (mostly the document and element nodes) may have an attribute property which contains either a reference to a NamedNodeMap containing the attribute node objects, or null if there are none.

Every node also has a childnodes property which contains either a reference to a NodeList containing a list of the child node objects, or null if there are none.


XML In DataFlex

The key to understanding XML support in DataFlex is the Document Object Model (DOM). You can think of this as a tree-view with each branch being a node. In DOM you parse a document on a node-by-node basis. You never create all the nodes needed to represent a document. Instead you get a handle to the node or nodes you need, you work on them, then destroy the handle when no longer needed. Destroying the handle does not affect the actual XML document - just your access to it via a node handle.

In DOM the handles are referred to as interface handles. You ask an XML document to create an interface handle for a particular part of the XML structure. In DataFlex, we wrap the interface handles inside a DataFlex object. Actually, we create a DataFlex node object and bind the interface handle to the object. We talk to the node via DataFlex messages. When we are done, we destroy the DataFlex object which destroys the interface handle (one must always dispose of the interfaces).

The DataFlex model uses a very dynamic object creation/destruction scheme. You never really name the objects - you refer to them by their object handle (DataFlex Object ID). You call a function that says: "create me an XML node object, bind it to the following interface handle, and return its DataFlex object handle". You then work on the DataFlex node object. When done, you send a message saying "destroy the DataFlex node object".

Any message that returns or sends a handle is using DataFlex object handles. With the exception of the cXmlDomDocument object, all other objects are created by sending a message to the Document object or some other node object. When needed, a DataFlex object will be created and the object's ID (handle) will be returned. The object will be based on the appropriate class type, determined by the message being sent and the data being retrieved.

When you no longer need the node object it should be destroyed. This is done by sending the message Destroy to the object. This is extremely important. Any time an object handle is returned from an XML message, you have created a new object. It is your responsibility to destroy it when you no longer need it. If you forget to destroy an object it will be properly destroyed when you destroy its parent. Since all objects reside within an Xml document object, destroying the document object will properly dispose of child objects. However, this is considered bad technique.

You can traverse the Document tree by using property handles (and similarly-named functions) such as get DocumentObject, ParentNode, FirstChild, LastChild, NextSibling and PreviousSibling.

You can change the structure of the loaded XML document with methods such as CreateChildNode, CloneNode, RemoveNode, AddElement (procedure), AddElement (function), AddAttribute and others. You can change the content of nodes by setting read/write properties such as psNodeValue.

DTDs

There is no message that allows you to create a new DTD (it's not part of the Microsoft DOM specification.) The only way to create a new XML document with a DTD declaration is to create a new XML document and load a skeleton XML document that contains a DTD. You can do this by using LoadXML.(or LoadXMLDocument.)

Error Messages

Functions that fail when creating nodes return a 0. This is used by developers as normal error checking. All the node creation functions return an object handle. If the handle is zero, then no object was created and, most likely, an error that should be dealt with occurred.

Procedures that fail when creating nodes generate an error. Any of the Send AddXxxxxx messages (Send AddElement, Send AddChildComment, etc.) will generate an error DFERR_XML_INTERNAL_ERROR (4380) if the object can not be created and added. This is the only way you could tell if the operation succeeded or not. The assumption is made that you will never use the messages unless you are sure there will not be an error. If an error if possible you should use functions (Get CreateXxxxx followed by Get AppendNode or Get InsertBeforeNode) where you can check the return value to make sure the operation suceeded and proceed as needed.

Using the XML Classes

The cXmlDomDocument class is the starting point for most XML processing. Refer to the cXmlDomDocument class for more information about the XML Document Object Model (DOM) and using XML within DataFlex. Samples are provided in this section.


Processing XML Documents with Namespaces

If you are parsing or writing XML documents that use namespaces (i.e. where the xmlns attribute is used to declare one or more namespace names), then you must use special namespace-aware methods to read, write or traverse the document's elements and attributes.

The following lists the namespace aware methods you should use:
AddAttributeNS, AddElementNS, AttributeValueNS, AttributeValueNodeNS, ChildElementNS, ChildElementValueNS, IsElementNS, NextElementNS, RemoveAttributeNS, SetChildElementValueNS

For more information refer to the relevant help topic for these methods.


The Main XML Classes

The XML classes are derived from one of two super-classes - a cXmlDom Node class, or a cXmlDom Collection class.

Node Classes

The Node class exists in DataFlex as the cXmlDomNode class and is the super-class for all of the other XML node classes (document, elements, attributes, etc.) When you need to create access to a node you use one of these classes.

cXmlDomNode contains the interface to handle all processing needs common to all node classes. Its sub-classes contain specialized messages that apply to each special node type. For this reason, it is wise to thoroughly understand the cXmlDomNode interface - it is used by all of the other classes.

While you will normally create an object based on the special XML node type you are working with, you can use the cXmlDomNode class to represent any XML node, but then you will be limited to using the generic node interface.

The most commonly used node objects are:

cXmlDomDocument - this represents your entire XML document. Typically you will create this object using standard DataFlex object-creation syntax. All other XML objects will be created, dynamically, within this object. A normal lifespan of a document object is:


cXMLDomElement - this is is used to represent XML elements.

cXMLDomAttribute - this is used to represent attributes of an element.

Collection classes

Collection classes allow you to create an object that contains a collection of others nodes or attributes. FleXML has two types of collection objects - cXmlDomNodeList and cXmlDomNamedNodeMap. The cXmlDomNodeList is used to contain collections of other XML nodes (e.g. a collection of elements that all match a specified search pattern). The cXmlDomNamedNodeMap is used to contain collections of attributes (attributes are not considered to be nodes - although you can create attribute nodes).

Methods

The DataFlex methods (messages) allow you to traverse the DOM tree and manipulate its nodes. Each node is defined as a specific node type, which also defines valid parent and child nodes for each node type. For most XML documents, the most common node types are element, attribute and text.

XML Examples

The following examples show different aspects of using XML within DataFlex



None of the above examples demonstrate how to handle XML documents that use namespaces. For information about XML documents with namespaces refer to: Processing XML Documents with Namespaces.


Parsing an XML Document within a BPO

This sample shows you how to access an XML Document. To access an XML document for editing or reporting purposes you do the following:


The translates into DataFlex code as follows:

Object oBPOXML is a BusinessProcess
    :
    Procedure OnProcess
       Handle hoXML hoRoot hoList hoCust
       Integer iItems i bOK

       Get Create (RefClass(cXMLDOMDocument)) to hoXML
       
       // you can use Create (as above) or create
       // the object using standard Object syntax (as below) 
       //    Object oXML is a cXmlDomDocument
       //       Move Self to hoXML
       //    End_Object

       Set psDocumentName of hoXML to "http://localhost/xml/customer.xml"
       Set pbAsync of hoXML to False
       Set pbValidateOnParse of hoXML to True
     
       Get LoadXMLDocument of hoXML to bOK

       If not bOK Begin
           Send BasicParseErrorReport of hoXml
           Procedure_Return
       End
       Showln 'loaded'
       Get DocumentElement of hoXML to hoRoot
       Get FindNodeList of hoRoot "CUSTOMER" to hoList
       Get NodeListLength of hoList to iItems
       Decrement iItems
       For i from 0 to iItems
           Get CollectionNode of hoList i to hoCust
           Send ShowCust hoCust

           Send Destroy of hoCust
       Loop
       Send Destroy of hoList
       Send Destroy of hoRoot
       Send Destroy of hoXML
    End_Procedure  // OnProcess

    Procedure ShowCust Handle hoCust
       String sName sPhone sState
       Get AttributeValue of hoCust "NAME" to sName
       Get ChildNodeValue of hoCust "TELEPHONE" to sPhone
       Get ChildNodeValue of hoCust "ADDRESS/STATE" to sState
       Showln sName ' ' sPhone ' ' sState
    End_Procedure

End_Object    // oBPOXML



Display attributes for an element

The following program displays the attributes for an element on the screen.

Use dfallent.pkg
use Flexml.pkg

Object oTest Is A Panel

    Procedure Test
        Integer i // Index used to iterate through the list of attributes
        Integer bOk // Boolean to test return value
        Handle  hoXML      // Handle to XML document object
        Handle  hoRootNode // Handle to root node of document
        Handle  hoNode     // Handle to XML interface of search node
        Handle  hoAttributeCollection // Handle to collection of attributes
        Integer iAttributeCount  // Number of attributes of node found
        Handle  hoAttributeNode  // Hndl to dynamic object to access atributes
        String  sQueryString     // String to query for search node
        String  sAttributeName   // String that holds each attribute's name
        String  sAttributeValue  // String that holds each attribute's value
 
        // Create document object
        Get Create (RefClass(cXmlDomDocument)) to hoXML

        // Set the name of the document
        Set psDocumentName of hoXML to ".\Customer.xml"

        // Turn on the xml parse test so errors are reported.
        Set pbValidateOnParse of hoXML to True
 
        // Load the document
        Get LoadXMLDocument of hoXml to bOK
 
        // If the document fails to load, abort the program
        If Not bOK begin
            Send BasicParseErrorReport of hoXML
            Send Destroy of hoXML
            Procedure_Return
        End

        // Search from the root
        Get DocumentElement of hoXML to hoRootNode
        if (hoRootNode = 0) Begin
            Error 10001 "Cannot get the root node for the XML document test.xml"
            Send Destroy of hoXml
            Procedure_Return
        End
 
        // Do a query for a customer whose name is "Ming Foo Bakery"
        Move ("CUSTOMER[@NAME='Ming Foo Bakery']") to sQueryString
        Get FindNode of hoRootNode sQueryString to hoNode
 
        If (hoNode=0) Begin
            Error 10002  "Cannot find customer Ming. in the XML document test.xml"
        End
        Else Begin
            // Now do test - get attribute collection
            Get AttributeNodes of hoNode to hoAttributeCollection
            If (hoAttributeCollection = 0) Begin
                ERROR 10003 "Cannot get collection of attributes for Ming. node"
            End
            Else Begin
                // Show the attributes of the collection.
                // First, get the number of items in the set
                Get NodeListLength of hoAttributeCollection to iAttributeCount
                // Now, iterate through the list of items.
                For i From 0 to (iAttributeCount-1)
                    // Get each attribute (indexed by i) -
                    // a dynamic object is returned.
                    Get CollectionNode of hoAttributeCollection i to hoAttributeNode
                    // Get the name of the attribute.
                    Get psNodeName of hoAttributeNode to sAttributeName
                    // Get its value.
                    Get psText of hoAttributeNode to sAttributeValue
                    // Show on the screen.
                    Showln "Attribute " sAttributeName " has the value "  sAttributeValue
                    // Destroy the attribute object.
                    Send Destroy of hoAttributeNode
                Loop
                Send Destroy of hoAttributeCollection
            End
            Send Destroy of hoNode
        End

        // Cleanup. Destroy objects that were created.
        Send Destroy of hoRootNode
        Send Destroy of hoXML
    End_Procedure

End_Object

Send Test of oTest
Send Stop_Box "Program has completed"



Displaying data from a file

The following program accesses data from a datafile and writes it to an XML file. For full explanations and commented code, see the XML-Sample.src sample project in the 'Specialized Components' sample workspace.

 
Use Flexml.pkg
Use Customer.dd

ACTIVATE_VIEW Activate_oXMLSample2 FOR oXMLSample2
Object oXMLSample2 is a dbView
    Set Label to "XML - Sample 2"
    Set Size to 262 412
    Set Location to 7 5

    Object oSaveCustomertoXML is a BusinessProcess
        Property Integer pbAllowDuplicates False

        Set Location to 2 388
        Set Status_Panel_State to False

        Object Customer_DD is a Customer_DataDictionary
        End_object

        Procedure OnProcess
            Handle hoXML hoRoot hoList hoCust hoDD
            Integer iItems i bErr  bAllowDuplicates bOk
            String sDataPath
            Get pbAllowDuplicates to bAllowDuplicates
            Get Create (RefClass(cXMLDOMDocument)) to hoXML
            Get psDataPath of (phoWorkSpace(oApplication)) to sDataPath
            Set psDocumentName of hoXML to (sDatapath - "\Mycustomer.xml")
            Set pbValidateOnParse of hoXML To True
            Get LoadXMLDocument of hoXML to bOK
            Get DocumentElement of hoXML to hoRoot
            If not hoRoot ;
                Get CreateDocumentElement of hoXML "Customers" to hoRoot
            Move Customer_DD to hoDD
            Send Clear of hoDD
            Send Find of hoDD GT 1
            While (found)
                Send AddCustomer hoRoot bAllowDuplicates
                Send Find of hoDD GT 1
            end
            Send Destroy of hoRoot
            Get SaveXMLDocument of hoXML to bErr
            Send Destroy of hoXML
        End_Procedure
      
        Procedure AddCustomer handle hoRoot integer bAllowDuplicates
            handle hoCust hoAdd hoEle
            string sQuery
            If not bAllowDuplicates begin
             Move ("Customer[@Customer-Id='"+trim(Customer.Customer_Number)+"']") to sQuery
               Get  FindNode of hoRoot sQuery to hoCust
               If hoCust Begin
                    Send Destroy of hoCust
                    Procedure_return
               end
            end
            Get  AddElement of hoRoot "Customer" "" to hoCust
            Send AddAttribute of hoCust "Customer-Id" (trim(Customer.Customer_Number))
            Send AddElement   of hoCust "Name" (trim(Customer.Name))
            Get  AddElement   of hoCust "Address" "" to hoAdd
            Send AddElement   of hoAdd "Street" (trim(Customer.Address))
            Send AddElement   of hoAdd "City" (trim(Customer.City))
            Send AddElement   of hoAdd "State" (trim(Customer.State))
            Send AddElement   of hoAdd "Zip" (trim(Customer.Zip))
            Send Destroy of hoAdd
            Send AddElement   of hoCust "Telephone" (trim(Customer.Phone_Number))
            Send Destroy of hoCust
        End_Procedure
    End_Object

    Object oWriteCustomertoXML is a Button
        Set Label to "Write Customers to XML file"
        Set Size to 14 91
        Set Location to 210 208
        Procedure OnClick
            Send DoProcess of oSaveCustomertoXML
            Send Info_Box "XML File has been Created"
        End_Procedure
    End_Object
 
End_Object


Displaying data from several files

The following program accesses data from multiple related datafiles and writes it to an XML file. For full explanations and commented code, see the examples in the "..\DFx\Examples\XML-Sample\AppSrc" directory.

Use Flexml.pkg
Open customer
Open SalesP
Open vendor
Open Invt
Open OrderHea
Open OrderDtl

ACTIVATE_VIEW Activate_oXMLSample4 FOR oXMLSample4
Object oXMLSample4 is a dbView
        Set Label to "XML4"
        Set Size to 286 435
        Set Location to 1 2

        Object oBPOXMLWrite1 is a BusinessProcess
            Set Location to 196 96
            Set Display_Error_State to TRUE
            Set Status_Panel_State to FALSE

            Property Integer pbUseCData False

            Function Encode string sDat Returns string
               Move (Replaces("&",sDat,"&"))      to sDat
               Move (Replaces("<",sDat,"<"))           to sDat
               Move (Replaces(">",sDat,">"))          to sDat
               Move (Replaces('"',sDat,"""))        to sDat
               Function_Return sDat
            End_Function

            Procedure OnProcess
                Integer bTest
                Handle  hoRoot hoXML
                string sDataPath
                Get psDataPath of (phoWorkSpace(oApplication)) to sDataPath
                Get Create (RefClass(cXMLDOMDocument)) to hoXML
                Set psDocumentName of hoXML to (sDatapath - "\records-1.XML")
                Get LoadXMLDocument of hoXML to bTest
                Get DocumentElement of hoXML to hoRoot
                If Not hoRoot ;
                   Get CreateDocumentElement of hoXML "Tables" to hoRoot
                Showln "Writing XML"
                Send OutPutTable hoRoot Customer.File_number
                Send OutPutTable hoRoot SalesP.File_number
                Send OutPutTable hoRoot OrderHea.File_number
                Send OutPutTable hoRoot OrderDtl.File_number
                Send OutPutTable hoRoot Invt.File_number
                Send OutPutTable hoRoot Vendor.File_number
                Send Destroy Of hoRoot
                Get  SaveXMLDocument of hoXML to bTest
                Showln "Saving XML"
                Send Destroy Of hoXML
                Showln "Done"
            End_Procedure
            
            Procedure OutputTable handle hoRoot integer iFile
                String  sFile sQuery
                Handle  hoTable
                Integer bRetVal bUseCData
                Get pbUSeCData to bUseCData
                Get_Attribute DF_FILE_LOGICAL_NAME of iFile to sFile
                Move ("Table[@Name='" + sFile + "']") to sQuery
                Get FindNode of hoRoot sQuery to hoTable
                If hoTable Begin
                   Get YesNo_Box (sFile * "exists. Replace?") to bRetVal
                   If (bRetVal=MBR_No) Begin
                      Send destroy of hoTable
                      Procedure_return
                   end
                   Else Begin
                      Get RemoveNode of hoRoot hoTable to hoTable
                      Send destroy of hoTable
                   End
                End
            
                Showln "Writing " sfile
                Get  AddElement of hoRoot "Table" "" to hoTable
                Send AddAttribute    Of hoTable "Name" sFile
                Send AddAttribute    Of hoTable "File" iFile
                Clear iFile
                VFind iFile 0 GT
                While (Found)
                    Send OutputRows hoTable iFile bUseCData
                    VFind iFile 0 GT
                End
                Send Destroy of hoTable
            End_procedure
           
            Procedure OutPutRows ;
                      handle hoNode integer iFile integer bUseCData
                integer iField iFields bRetVal iType
                string sTag sField
                handle hoRow hoField
                Get AddElement of hoNode "Row" "" to hoRow
                Get_Attribute DF_FILE_NUMBER_FIELDS of iFile to iFields
                For iField from 1 to iFields
                    Get_Attribute DF_FIELD_TYPE of iFile iField to iType
                    If (iType<>DF_OVERLAP) Begin
                        Get_Field_Value iFile iField to sField
                        Move (trim(sField)) to sfield
                        Get_Attribute DF_FIELD_NAME of iFile iField to sTag
            
                        Get AddElement of hoRow "Field" "" to hoField
                        If bUseCData ;
                            Send AddCDataSection of hoField sField
                        Else Begin
                            Get Encode sField to sField // encode < > ; and "
                            Send AddChildTextNode of hoField sField
                        End
            
                        Send AddAttribute Of hoField "Field-number" iField
                        Send AddAttribute Of hoField "Name" sTag
                        Send Destroy of hoField
                    end
                Loop
                Send Destroy of hoRow
            End_procedure
        End_Object
 
        Object oWriteXml1 is a Button
            Set Label to "Write Tables to XML "
            Set Size to 14 82
            Set Location to 218 6
            Procedure OnClick
                send DoProcess of oBPOXMLWrite1
            End_Procedure
        End_Object
 
End_Object



Traversing a list of nodes forwards

The following program shows how to navigate a list of nodes from first to last.

Use DFAllent.pkg
Use Flexml.pkg
 
Object oTest Is A cObject
 
    Procedure ShowInformation Integer hoNode Integer iLineCount
        String sName
        Integer iType
        // If the node is an element (e.g. Customer), get the element's nodename and the attribute value for NAME
        // skip all non-element nodes
        Get piNodeType of hoNode to iType
        If (iType = NODE_ELEMENT) Begin
           Get AttributeValue of hoNode "NAME" to sName
           Showln iLineCount ": Node is [" (psNodeName(hoNode)) "] Name is [" sName "]"
        End
    End_Procedure
 
    Procedure Test
        Integer bOk              // Boolean to test return value.
        Integer hoXML            // Handle to XML Document object
        Integer hoRoot           // Handle to root node of document.
        Integer hoNode           // handle to a node for testing
        Integer hoNextNode       // used to find the previous node
        Integer iLineCount
 
        // Create document object
 
        Get Create (RefClass(cXmlDomDocument)) to hoXML
        Set psDocumentName of hoXML to ".\Customer.xml"
        // Turn on the xml parse test so errors are reported.
        Set pbValidateOnParse of hoXML to True
 
        // Load the document
        Get LoadXMLDocument of hoXml to bOK
 
        // If the document fails to load, abort the program
        If nOT bOK begin
            Send BasicParseErrorReport of hoXml
            Send Destroy of hoXML
            Procedure_Return
        End
 
        // Search from the root.
        Get DocumentElement of hoXml to hoRoot
        if (hoRoot=0) Begin
            Error 10001 "Cannot get the root node for the XML document test.xml"
            Send Destroy of hoXml
            Procedure_Return
        End
 
        // traverse through nodes. Start with first child and then
        // move through each sibling
        Move 0 to iLineCount
        Get FirstChild of hoRoot to hoNode // get the first node
        While (hoNode<>0)
            Increment iLineCount
            Send ShowInformation hoNode iLineCount
            Get NextNode of hoNode to hoNode // now get next sibling node, destroy current node
        Loop
 
        Send Destroy of hoRoot
        Send Destroy of hoXml
 
    End_Procedure
 
End_Object
 
Send Test of oTest
Send Stop_Box "Program has completed"


Traversing a list of nodes backwards


The following program demonstrates the use of phLastChild to traverse a list of nodes backwards.

Use DFAllent.pkg
Use Flexml.pkg
 
Object oTest Is A cObject
 
    Procedure ShowInformation Integer hoNode Integer iLineCount
        String sName
        Integer iType
        // If the node is an element (e.g. Customer), get the element's nodename and the attribute value for NAME
        // skip all non-element nodes
        Get piNodeType of hoNode to iType
        If (iType = NODE_ELEMENT) Begin
           Get AttributeValue of hoNode "NAME" to sName
           Showln iLineCount ": Node is [" (psNodeName(hoNode)) "] Name is [" sName "]"
        End
    End_Procedure
 
    Procedure Test
        Integer bOk              // Boolean to test return value.
        Integer hoXML            // Handle to XML Document object
        Integer hoRoot           // Handle to root node of document.
        Integer hoNode           // handle to a node for testing
        Integer hoNextNode       // used to find the previous node
        Integer iLineCount
 
        // Create document object
 
        Get Create (RefClass(cXmlDomDocument)) to hoXML
        Set psDocumentName of hoXML to ".\Customer.xml"
        // Turn on the xml parse test so errors are reported.
        Set pbValidateOnParse of hoXML to True
 
        // Load the document
        Get LoadXMLDocument of hoXml to bOK
 
        // If the document fails to load, abort the program
        If not bOK begin
            Send BasicParseErrorReport of hoXml
            Send Destroy of hoXML
            Procedure_Return
        End
 
        // Search from the root.
        Get DocumentElement of hoXml to hoRoot
        if (hoRoot=0) Begin
            Error 10001 "Cannot get the root node for the XML document test.xml"
            Send Destroy of hoXml
            Procedure_Return
        End
 
        // traverse through nodes in backwards order. Start with last child and then
        // move up through each sibling
        Move 0 to iLineCount
        Get LastChild of hoRoot to hoNode // get the last node
        While (hoNode<>0)
            Increment iLineCount
            Send ShowInformation hoNode iLineCount
            Get PreviousSibling of hoNode to hoNextNode // now get previous sibling node
            Send Destroy of hoNode     // Important: get rid of the previous node object
            Move hoNextNode to hoNode
        Loop
 
        Send Destroy of hoRoot
        Send Destroy of hoXml
 
    End_Procedure
 
End_Object
 
Send Test of oTest
Send Stop_Box "Program has completed"


Adding an XML Declaration to an XML Document


This sample shows how to insert an XML declaration that specifies an XML version of 1.0 and encoding of ISO8859-1 into an XML document. The inserted XML code will look like this:

<?xml version="1.0" encoding="ISO8859-1"?>

Sample Code:

Get CreateChildProcessingInstruction Of hoXMLDocumentRoot "xml" 'version="1.0" encoding="UTF-8" standalone="yes"' To hoNodeToInsert
If (hoNodeToInsert > 0) Begin
    Get InsertBeforeNode Of hoXML hoNodeToInsert hoXMLDocumentRoot To hoInsertedNode
    If ((hoInsertedNode <> hoNodeToInsert) and (hoInsertedNode > 0)) Begin
        Send Destroy Of hoInsertedNode
    End
    Send Destroy Of hoNodeToInsert
End


Creating a New XML Document


See AddElementNS for an example of creating a new XML document.

See Also

XML Namespaces Primer | cXmlDomAttribute | cXmlDomCDataSection | cXmlDomComment | cXmlDomDocumentFragment | cXmlDomDocumentType | cXmlDomElement | cXmlDomEntity | cXmlDomEntityReference | cXmlDomNamedNodeMap | cXmlDomNode | cXmlDomNodeList | cXmlDomNotation | cXmlDomProcessingInstruction | cXmlDomTextNode | BaseXmlDomParseError