cObject
---BaseXmlDomNode
------BaseXmlDomDocument
---------cXMLDOMDocument
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.
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.
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.
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.
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.)
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.
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.
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 XML classes are derived from one of two super-classes - a cXmlDom Node class, or a cXmlDom Collection class.
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 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).
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.
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.
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
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"
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
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
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"
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"
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
See AddElementNS for an example of creating a new XML document.
XML Namespaces Primer | cXmlDomAttribute | cXmlDomCDataSection | cXmlDomComment | cXmlDomDocumentFragment | cXmlDomDocumentType | cXmlDomElement | cXmlDomEntity | cXmlDomEntityReference | cXmlDomNamedNodeMap | cXmlDomNode | cXmlDomNodeList | cXmlDomNotation | cXmlDomProcessingInstruction | cXmlDomTextNode | BaseXmlDomParseError