PowerBuilder Authors: Chris Pollach, Yeshim Deniz, Jayaram Krishnaswamy, Kevin Benedict, Avi Rosenthal

Related Topics: PowerBuilder

PowerBuilder: Article

Taking PowerBuilder's PBDOM Out for a Spin

Taking PowerBuilder's PBDOM Out for a Spin

So you think, "Why bother using PBDOM?" Well, you can use PDOM to manipulate elements in an XML document. That means you can move elements in a document or from one document to another. You can add elements to a document or delete them from a document. And, with a little coding, you can import nested XML data into a DataWindow.

With the XML capabilities in the DataWindow introduced with Sybase's PowerBuilder 9, it's possible to import and export data very fast and easily. You might have glanced at the PBDOM definition in the PowerBuilder help and figured it looked hard to handle but, fear not, I'll introduce you to PBDOM and give you some code samples.

Importing & Exporting with DataWindows
Starting with PowerBuilder 9, the DataWindow can import and export data in XML. This powerful feature lets you exchange large amounts of data very fast. Importing and exporting is template-based. You can define several templates for one DataWindow. With the DataWindow painter, you assign a template for importing and one for exporting the data. At run-time, it's possible to change the template using the code. Figure 1 shows the definition of a template in the DataWindow painter used for export.

Loading data from the EAS Demo DB and saving it with the defined template generates the XML data in Listing 1.

PBDOM stands for PowerBuilder Document Object Model. It's similar to the World Wide Web Consortium's DOM API and the Java-based document object model for XML files JDOM. You can find a comparison of these three models in the PowerBuilder Help (PowerBuilder Extension Reference/PowerBuilder Document Object Model/PBDOM objects). Technically, PBDOM is implemented as a PBNI (PowerBuilder Native Interface) extension that makes use of the Apache/Xerces DLL.

PBDOM Classes
All PBDOM classes (except PBDOM_Builder and PBDOM_Exception) are inherited from PBDOM_Object.

  • PBDOM_Builder is used to create a PBDOM_Document from data sources like files, strings or DataStores.
  • PBDOM_Exception extends the PowerBuilder exception class and is used for exception handling.
  • PBDOM_Object represents any node in an XML node tree and serves as a base class for the different node types.
  • PBDOM_Document is the representation of the XML DOM document. It accesses document-level elements.
  • PBDOM_Element represents an XML element and accesses its attributes, children and text.
  • PBDOM_Attribute is the representation of an XML attribute and accesses its values and namespace information.
  • PBDOM_Text represents a DOM text node in a XML document.
  • PBDOM_Processinginstruction are the XML document's processing instructions.
When looking at Listing 1, the saved XML data from the DataWindow, you can see some of the described types. The class PBDOM_Document references all the data including the XML header. The PBDOM_Processinginstruction object references the data in the XML header (e.g., version).

[Processing instructions are used to send instructions to the application that is reading the XML. They begin with "". Technically, the XML Declaration is not a Processing Instruction, although it is often referred to as such and does has a similar format. - Editor.]

The items CUSTOMERS, CUSTOMER, FIRSTNAME etc. are PBDOM_Elements. The ID in the CUSTOMER tag is a PBDOM_Attribute and PBDOM_Text references the values in the tags like Michaels or Devlin.

A namespace in a document is used to distinguish between elements and attributes with the same name but belonging to different items. The element CUSTOMER and the element COMPANY could both have a child element named NAME. References to the element NAME would be ambiguous without a namespace. The solution with the prefix, the document, could look like this:

<comp:NAME>Sample LLC<comp:NAME>

You will find more details about namespaces on the W3C web site and many examples and answers on the XML Namespace FAQ at www.rpbourret.com/xml/NamespacesFAQ.htm.

Before you can start working with PBDOM, you have to add PBDOM100.PBD to the library list. In PowerBuilder's application search path the following files should be accessible: PBDOM100.DLL, PBXerces100.DLL and xerces-c_2_1_0.dll. You have to deploy these four files with your application. For PowerBuilder 9 choose the appropriate PBD and DLLs, whereas the Xerces DLL is the same as for PowerBuilder 10.

Creating an XML Document
An XML document can be created from scratch or from an existing file, string or DataStore. In Listing 2 the XML output from Listing 1 is used to generate an XML DOM document. Only minimal error handling is implemented in this listing. The BuildFromFile method from the PBDOM_Builder class reads and parses the XML Document. The method returns a reference to the PBDOM_Document.

The next few lines of code lines show some details about the first level of the document. The method GetContent from the PDBOM_Document returns an array of objects in the document. In our sample, the method will return an array of two elements. The first element is of type PBDOM_Processinginstructions, the second of type PBDOM_Element and references the element CUSTOMERS. Calling the method GetRootElement returns the root element of the document, which is also CUSTOMERS.

To visualize a XML document in PowerBuilder you can use a TreeView. Listing 3 shows a recursive function that takes an array of PBDOM_Objects and displays it in a TreeView. The function loops through all elements of the array. Depending on the type of element different information besides the object name is displayed. In the case of a PBDOM_Element, the function loops over all the attributes of this element and creates name/value pairs of each. The name of the PBDOM_Object plus the display information is added to the TreeView. Should the PBDOM_Object have children, the same function is called with an array of these children and the handle of the inserted TreeView item.

Manipulating the XML Document
The big advantage with PBDOM is the possibility of manipulating a single node in a document.

For the following example, I'll add some information for customer ID 102.

Using the default EAServer Demo DB, I'll add an order to the customer. Listing 4 shows how we search for the customer with an ID of 102. The function is recursive and loops through all the elements and attributes until the element with the required attribute value is found.

Note that the search is case-sensitive.

Starting with the first element, its content is loaded into an array. The method loops over the items of this array. If the item is of type PBDOM_Element the name of it - returned with the method GetName - is compared with the name to search for (CUSTOMER in our example). When an element with the name to search for is found, the method GetAttributes loads all the attributes of this element into an array. The function then loops over the attributes and - as soon as the attribute with the name to search for is found - the value is checked. When the value matches, the element is returned. If there is no match and the element has children, the method calls itself passing that element.

[There are W3C standard methods for searching XML documents known as XPath and XQuery. However, at least when this article was written, PBDOM does not support XPath or XQuery type operations. - Editor]

After the appropriate element is found, I add a sales order header (see Listing 5). At first I create a sales order with CREATE PBDOM_Element. Then I set the name of this instance to SALESORDER with the method SetName. The SetName method validates the name (e.g., for spaces in the element name). I then add an attribute with the name ID and the value 111. For the sales order, I need an order date and region. I create them, set their name and put the value into it with SetText. After all these elements are prepared, I put them together with the method AddContent, which checks the data for structure (e.g., no loops in a tree) and consistency of namespace to ensure there is only one root element. To catch the run-time errors, I put a TRY...CATCH statement around the call.

To demonstrate some additional data manipulation, I also remove the customer with ID equals 104. The search for that customer is done using the same method shown in Listing 4. To remove that element the method Detach is used:


After the manipulation is done, the XML document can be saved with the method SaveDocument of the PBDOM_Document. Unfortunately, as of this writing, there was no method to save it to a string or blob. Instead, you must save the XML to a temporary file and then read it back into a string or blob, as applicable.

The PDBOM interface is a powerful way to manipulate complex XML documents. There are various usages possible. We can use it to customize style sheets for an application. Another possible use would be in an EAServer component to manipulate XML before returning it to the client. This article has provided you with a base to start from. For additional information, refer to chapter 14 of Application Techniques in the PowerBuilder. In addition, you can also download other examples at the CodeXchange site of the Sybase Developer Network.

More Stories By Arthur Hefti

Arthur Hefti is CEO of CATsoft Development GmbH in Zurich. He has been working with PowerBuilder since version 3 and taught dozens of PowerBuilder training classes. He and his team create custom-made client/server and Web applications using XML, Web Services, and encryption.

Comments (0)

Share your thoughts on this story.

Add your comment
You must be signed in to add a comment. Sign-in | Register

In accordance with our Comment Policy, we encourage comments that are on topic, relevant and to-the-point. We will remove comments that include profanity, personal attacks, racial slurs, threats of violence, or other inappropriate material that violates our Terms and Conditions, and will block users who make repeated violations. We ask all readers to expect diversity of opinion and to treat one another with dignity and respect.