2.9 Dealing with XML Documents

All communication between the DirXML engine and the application driver takes the form of XML documents (with the exception of DriverShim getSubscriptionShim and getPublicationShim methods).

DirXML SDK provides several methods of dealing with XML documents:

Typically your driver will deal with XML documents using the DOM or XDS libraries, but there may be drivers for which it is more convenient to use SAX or even a serialized document.

All XML document arguments and returns for interface methods use an abstraction named XmlDocument to encapsulate the underlying XML representation. This allows the DirXML engine to supply the document in one form and the driver to consume the document in another form. The converse is also true. For example, the driver could receive a serialized XML document from the application and supply it in that form to the XmlDocument object. The DirXML engine would then consume it as a DOM tree.

2.9.1 Java Sample Code

The XmlDocument abstraction has the following methods for obtaining the underlying XML document in the desired form.

The XmlDocument abstraction is implemented as a class in Java (com.novell.nds.dirxml.driver.XmlDocument). The following examples illustrate the most common ways of obtaining the document representation and setting the document representation. There are additional methods. See the online javadocs.

DOM

The following code illustrates obtaining an XML document as a DOM tree from the XmlDocument object.

  void example(XmlDocument doc)
  {
     Document inputDocument = doc.getDocument();
  }
  

The following code illustrates creating a DOM document and setting the XmlDocument object from the DOM document.

  XmlDocument example()
  {
     //create a DOM Document using the document factory
  Document returnDoc = com.novell.xml.dom.DocumentFactory.newDocument();
     //create the <nds> root element
     Element nds = returnDoc.createElement("nds");
     returnDoc.appendChild(nds);
     //set the various xds attributes
     nds.setAttribute("ndsversion","8.5");
     nds.setAttribute("dtdversion","1.0");
     return   new XmlDocument(returnDoc);
  }
  

SAX

The following sample illustrates obtaining the XML document as a series of SAX events from the XmlDocument object.

  class Handler implements DocumentHandler
  {
     ...
  };
  void example(XmlDocument doc)
  {
  Parser parser = doc.getDocumentSAX();
  InputSource inputSource = doc.getDocumentInputSource();
  parser.setDocumentHandler(new Handler());
  parser.parse(inputSource);
  }
  

The following sample illustrates setting the XmlDocument object from objects that implement the SAX Parser and SAX InputSource interfaces.

class MyParser implements Parser { ... } XmlDocument example() { MyParser parser = new MyParser(); InputSource inputSource = new InputSource("file.xml"); return new XmlDocument(parser,inputSource); }

Serialized XML

The following sample illustrates obtaining the XML document in a serialized form.

  void example(XmlDocument doc)
  {
     byte[] bytes = doc.getDocumentBytes("UTF-8");
  }
  

The following sample illustrates setting the XmlDocument object from a serialized XML document contained in a byte array:

  XmlDocument example(byte [] bytes)
  {
     return new XmlDocument(bytes);
  }
  

2.9.2 C++ Sample Code

The XmlDocument abstraction has the following C++ methods for obtaining the underlying XML document in the desired form.

     DOM::Document * METHOD_CALL getDocument();   SAX::Parser * METHOD_CALL getDocumentSAX();   SAX::InputSource * METHOD_CALL getDocumentInputSource();   const unsigned char * METHOD_CALL getDocumentBytes(const
        unicode * encoding, int endian, int * length);
  

The XmlDocument abstraction is implemented as an interface in C++ (defined in NativeInterface.h). Methods are also defined in the following header files.

Table 2-2 XmlDocument header files

File

Description

dom.h

Defines interfaces and methods which are patterned after the Java implementation of the W3C DOM (Document Object Model) Level 1.

InterfaceFactory.h

Defines the factories and the destructors.

sax.h

Defines interfaces and methods for receiving information about XML documents. They are patterned after the Java implementation of version 1 of the Simple API for XML (SAX) event interface.

OutputStream.h

Defines an interface modeled on java.io.OutputStream for writing to a byte sink.

XMLWriter.h

Creates an XMLWriter.

The following examples illustrate the most common ways of obtaining the document representation and setting the document representation. There are additional methods. See the NativeInterface.h file.

DOM

The following code illustrates obtaining the XML document as a DOM tree from the XmlDocument interface:

  XmlDocument *
  SubscriptionShimImpl::execute(
  XmlDocument * inputDoc
  XmlQueryProcessor * query)
  {
  DOM::Document * document = inputDoc->getDocument();
      ...
  }
  

The following illustrates creating an XmlDocument as a DOM tree. (The factory methods are defined in InterfaceFactory.h)

  //create a document using DirXML factory method
  DOM::Document * document = Document_new();
  //create the document tree
  DOM::Element * ndsElement = document->createElement(NDS_ELEMENT_NAME);
   ...
  //create the XmlDocument instance
  XmlDocument * returnDoc = XmlDocument_newFromDOM(document);
  ...
  //sometime later, after returnDoc is no longer being used:
  XmlDocument_destroy(returnDoc);
  document->destroy();
  

SAX

The following code illustrates obtaining the XML document as a series of SAX events.

  XmlDocument *
  SubscriptionShimImpl::execute(
  XmlDocument * inputDoc, 
  XmlQueryProcessor * query)
  {
  SAX::Parser * eventGenerator;
  SAX::InputSource * inputSource;
  eventGenerator = inputDoc->getDocumentSAX();
  inputSource = inputDoc->getDocumentInputSource();
  //my event handler is a class that implements the DocumentHandler interface
  //declared in sax.h
  eventGenerator->setDocumentHandler(myEventHandler);
  //this call causes the SAX events to be sent to the document handler
  eventGenerator->parse(inputSource);
  ...
  }
  

The following code illustrates creating an XmlDocument using SAX events. For ease of illustration, the SAX event source is the DirXML supplied XML parser, using a file as input.

  SAX::InputSource * inputSource = InputSource_new();
  inputSource->setSystemId("tempfile.xml");
  SAX::Parser * parser = Parser_new();
  XmlDocument * xmlDoc = XmlDocument_newFromSAX(parser, inputSource);
  ...
  //sometime later, after xmlDoc is no longer being used:
  XmlDocument_destroy(xmlDoc);
  Parser_destroy(parser);
  InputSource_destroy(inputSource);
  

Serialized XML

The following code illustrates obtaining a serialized representation of the XML document.

  XmlDocument *
  SubscriptionShimImpl::execute(
  XmlDocument * inputDoc
  XmlQueryProcessor * query)
  {
  static const unicode ENCODING[] = {’U’,’T’,’F’,’-’,’8’,0};
  const unsigned char * bytes;
  int length;
  bytes = inputDoc->getDocumentBytes(ENCODING, LITTLE_ENDIAN, &length);
  ...
  }
  

The following code illustrates creating an XmlDocument from a byte array.

  static const unicode ENCODING[] = {’U’,’T’,’F’,’-’,’8’,0};
  //make a driver-specific call to get the serialized XML from somewhere
  int length;
  unsigned char * bytes = get_bytes_from_somewhere(&length);
  //create the XmlDocument from the serialized XML
  XmlDocument * xmlDoc = XmlDocument_newFromBytes(bytes,length,ENCODING,LITTLE_ENDIAN);
  ...
  //sometime later, when xmlDoc is no longer in use...
  XmlDocument_destroy(xmlDoc);
  release_bytes_from_somewhere(bytes);