An easier way to build XML in UniVerse
October 25, 2010 9 Comments
The process of creating an XML document in UniVerse BASIC is quite laborious. It takes a number of steps to add a new element node, and similar steps to add attributes to a node.
The sequence is something like this:
- Create new XDOM.ELEMENT.NODE
- Add new node to existing XML document
- If the element is to have a value
- Create new XDOM.TEXT.NODE with the element node value
- Add text node to new element node
- If the element is to have attributes
- Create new XDOM.ATTR.NODE with attribute name and value
- Add attribute node to new element node
- Repeat for all required attributes
All this has create just on element. To create multiple elements requires performing the above sequence multiple times. This makes for a very messy and hard to maintain program.
An Easier way
Ordinarily, such a piece of logic would be placed into an external subroutine. That does work, but there is a way to provide a more intuitive solution: Functions!
UniVerse BASIC supports the creation and use of functions. By creating a function that performs this sequence, the process of building an XML document becomes a lot easier to code, and to read and maintain.
The Add_XMLElement function
The following code is a function that performs all the above steps:
function Add_XMLElement( domHandle, NODE.name, NODE.value, NODE.attr, NODE.ns, nodeHandle) * This function adds a new element node to the domHandle XML doc. * It also adds any attributes supplied. * * domHandle [IN] Single Value * Handle to an XML node or document * * NODE.name [IN] Single Value * Name of the element node to be added * * NODE.value [IN] Single Value * The value of the new element node * * NODE.attr [IN] Two attributes, with Multi values * Dynamic array of names and values to be used to define the * attributes on this node. * <1> Contains the attribute name * <2> Contains the attribute value * * NODE.ns [IN] Single Value * The namespace to use for this node. * * nodeHandle [OUT] Single Value * A handle to the added node * * Return Value * An XML return code: XML.SUCCESS, XML.ERROR, XML.INVALID.HANDLE $include UNIVERSE.INCLUDE XML.H xmlStatus = XML.SUCCESS * Create the new ELEMENT node xmlStatus = XDOMCreateNode( domHandle, NODE.name, "", XDOM.ELEMENT.NODE, nodeHandle) if xmlStatus = XML.SUCCESS then xmlStatus = XDOMAddChild( domHandle, "", NODE.ns, nodeHandle, XDOM.NODUP) end if NODE.value # '' and xmlStatus = XML.SUCCESS then * If a value has been supplied, add a nameless child TEXT element xmlStatus = XDOMCreateNode(nodeHandle, '', NODE.value, XDOM.TEXT.NODE, newText) if xmlStatus = XML.SUCCESS then xmlStatus = XDOMAddChild( nodeHandle, "", NODE.ns, newText, XDOM.NODUP) xmlStatus = XDOMClose(newText) end end if NODE.attr # '' and xmlStatus = XML.SUCCESS then * If there are attribute to be added, do them now qty.ATTR = dcount( NODE.attr<1>, @VM) for num.ATTR = 1 to qty.ATTR while xmlStatus = XML.SUCCESS name.ATTR = NODE.attr<1,num.ATTR> if name.ATTR # '' then value.ATTR = NODE.attr<2,num.ATTR> xmlStatus = XDOMCreateNode( nodeHandle, name.ATTR, value.ATTR, XDOM.ATTR.NODE, attrHandle) if xmlStatus = XML.SUCCESS then xmlStatus = XDOMAddChild( nodeHandle, "", NODE.ns, attrHandle, XDOM.NODUP) xmlStatus = XDOMClose(attrHandle) end end next num.ATTR end return (xmlStatus)
Once compiled and cataloged, this function is available to be used.
A Working Example
This program uses the above function to create a sample XML document:
* manual build of xml using XDOM $include UNIVERSE.INCLUDE XML.H * Define the function we are going to use deffun Add_XMLElement(a,b,c,d,e,f) * Trying to build xml: * <PurchaseHistory> * <PurchaseItem Ref="ABC123">Learning the Ropes</PurchaseItem> * <PurchaseItem Ref="CODE86">Getting Smarter</PurchaseItem> * <PurchaseItem Ref="CODE007" Security="High">Bonding the James Way</PurchaseItem> * </PurchaseHistory> * Create the doc xmlStatus = XDOMCreateRoot(domHandle) * Add the root element xmlStatus = Add_XMLElement( domHandle, "PurchaseHistory", "", "", "", newnode) * add the PurchaseItem elements attrNode = "Ref": @AM: "ABC123" xmlStatus = Add_XMLElement( newnode, "PurchaseItem", "Learning the Ropes", attrNode, "", subnode) xmlStatus = XDOMClose(subnode) attrNode = "Ref": @AM: "CODE86" xmlStatus = Add_XMLElement( newnode, "PurchaseItem", "Getting Smarter", attrNode, "", subnode) xmlStatus = XDOMClose(subnode) attrNode = "Ref":@VM:"Security": @AM: "CODE007": @VM: "High" xmlStatus = Add_XMLElement( newnode, "PurchaseItem", "Bonding the James Way", attrNode, "", subnode) xmlStatus = XDOMClose(subnode) * Output the XML xmlStatus = XDOMWrite( domHandle, doc.XML, XML.TO.STRING) crt "XML = " crt "[":doc.XML:"]" xmlStatus = XDOMClose(newnode) xmlStatus = XDOMClose(domHandle)
As you can see, this is a much easier way of coding the manual build of XML, whilst maintaining the XDOM API-type function interface.
Compile and run this program, and it will produce the following output:
XML =
[<PurchaseHistory>
<PurchaseItem Ref=”ABC123″>Learning the Ropes</PurchaseItem>
<PurchaseItem Ref=”CODE86″>Getting Smarter</PurchaseItem>
<PurchaseItem Ref=”CODE007″ Security=”High”>Bonding the James Way</PurchaseItem>
</PurchaseHistory>
]