Novell is now a part of Micro Focus

DirXML Drivers, Engine and Story--Part 2

Articles and Tips: article

Kevin Burnett
Senior Research Engineer
Novell AppNotes

01 Dec 2001


In the November issue, we started giving a little background into the DirXML engine and DirXML drivers. As we continued, we ran out of room in our hardcopy magazine for the complete explanation. Instead of having the hardcopy and web version out of sync, we decided to break up our discussion of the DirXML engine and DirXML drivers into two parts.

So let's finish up the question and answer session about the DirXML engine and the DirXML driver interface. Then we will have the basic understanding necessary to begin tackling how to debug a DirXML driver. For a refresher course on what was discussed last month, please see: http://developer.novell.com/ research/sections/netmanage/dirprimer/2001/November/p011001.htm

What Do I Need to Know to Implement a Rule Using an XSLT Stylesheet?

  1. Understand XSLT and the XML you will be transforming. A good working knowledge of XSLT is a good place to start. Obtain the XSLT and XPath specifications.

    Make sure any tutorial or book reference on the subject is based on the final November 16, 1999 W3C Recommendation. A good recommendation would be the XSLT Programmer's Reference, by Michael Key, published by Wrox Press (ISBN 1-861003-12-9). You'll also need a good working understanding of the XML as specified by NDS.DTD.

  2. Understand the goal of the rule you are implementing. Each kind of rule accomplishes specific kinds of tasks as outlined in a general fashion as stated in last month's column. Additional things you might need to know about each rule type are as follows:

    Input Transformation Rule:

    • This rule performs any pre-processing of XML issued to DirXML from the driver.

    • It is a good place to perform data format mapping.

    • Names are in the application namespace.

    • This rule can change event types, generate extra events, and remove events.

    Output Transformation Rule:

    • This rule does any post-processing of XML that is issued from DirXML to the driver before the XML is sent to the driver.

    • This is a good place to perform data format mapping.

    • Names are in the application namespace as well.

    • You can change event types, generate extra events, and remove events using this rule.

    Event Transformation Rule:

    • This rule has its names in the NDS namespace.

    • You can also change event types, generate extra events, and remove events.

    Matching Rule:

    • This rule only operates on <add> events.

    • Names are in the NDS namespace.

    • On the Subscriber channel, you must add an <association> parameter to the <add> command for any matches that are found in the application.

    • On the Publisher channel, you must fill in the dest-dn (Destination Domain Name) attribute of the <add> command if a match is found in eDirectory. (The special value of a single unicode character &#xFFFD; signals that multiple matches were found.)

    • You cannot change event types or generate extra events, but you can remove events.

    Create Rule:

    • This rule only operates on <add> events.

    • Names are in the NDS namespace.

    • You can add attributes and values to the <add> command as appropriate.

    • You can remove events as well (this is how add is vetoed).

    Placement Rule:

    • This rule only operates on <add> events.

    • Names are in the NDS namespace.

    • This rule fills in the dest-dn attribute of the <add>.

    • For the Subscriber channel, this must be in the application namespace.

    • For the Publisher channel, this must be in the NDS namespace.

    • It can also remove events. Start out with the identity transformation. Unless you are translating to or from an XML format that is completely different from the DirXML format in the Input and Output Transformation Rules, you will want to start your stylesheet with templates that implement the identity transformation. This is so that anything in the document that you don't specifically try to intercept and change will be passed through as it is.

    The following two templates together implement the identity transform:

    <xsl:template match="/" >
    		<xsl:apply-templates select="node()|@*"/>
    </xsl:template>
    	
    <xsl:template match=node()|@*" >
    		<xsl:copy>
    			<xsl:apply-templates select="node()|@*"/>
    		</xsl:copy>
    </xsl:template>
  3. Use the parameters that are passed into the stylesheet. Except for the Input and Output Transformation Rules, rules implemented as stylesheets are passed several parameters from DirXML that the stylesheet can use:

    • fromNDS - boolean value that is true if the rule being processed by the Subscriber channel and false if the rule is being processed by the Publisher channel.

    • srcQueryProcessor - a Java object of class.com.novell.nds.dirxml.driver.XdsQueryProcessor. This allows the stylesheet to query the event source for more information.

    • destQueryProcessor - a Java object class from com.novell.nds.dirxml.driver.XdsQueryProcessor. This allows the stylesheet to query the event target for more information.

    To use these parameters, include the following information at the top level of your stylesheet:

    
    <xsl:param name="fromNDS"/>
    <xsl:param name="srcQueryProcessor"/>
    <xsl:param name="destQueryProcessor"/>

    Use of query processors depends on the Novell XSLT implementation of extension functions. In order to make a query, you need to declare a namespace for the XdsQueryProcessor interface. This is done by adding xmlns:query= "http://www.novell.com/nxsl/java/com. novell.nds.dirxml.driver.XdsQueryProcessor " to the <xsl:stylesheet> or <xsl:transform> element of the stylesheet. An example of using one of the query processors follows:

    <!-- query object name queries NDS for the passed object-name. Ideally, this would   -->
    <!-- not depend on "CN": to do this, add another parameter that is the name of the   -->
    <!-- naming attribute.                                                                                                 -->
       
    <xsl:template name="query-object-name">
       <xsl:param name="object-name"/>
       
       <!-- build an xds query as a result tree fragment -->
       <xsl:variable name="query">
          <nds ndsversion="8.5" dtdversion="1.0">
             <input>
                <query>
                   <search-class class-name="
                   {ancestor-or-self::add/@class-name}"/>
                   <!-- NOTE: depends on CN being the naming attribute -->
                   <search-attr attr-name="CN">
                      <value><xsl:value-of
                      select="$object-name"/></value>
                   </search-attr>
                   <!-- put an empty read attribute in so that we
                   don't get the whole object back -->
                   <read-attr/>
                </query>
             </input>
          </nds>
       </xsl:variable>
       
       <!-- query NDS -->
       <xsl:variable name="result" select="query:query($destQueryProcessor,$query)"/>
    <!-- return an empty or non-empty result tree fragment depending on result of query -->
       <xsl:value-of select="$result//instance"/>
    </xsl:template>
  4. Use extension functions as needed. XSLT is an excellent tool for performing some kinds of transformations and a rather poor tool for other types of transformations (such as non-trivial string manipulation, iterative processes, etc.). Fortunately the Novell XSLT processor implements extension functions that allow the stylesheet to call a function that is implemented in Java (and by extension any other language that can be accessed through JNI).

Additional documentation on using extension functions with Novell's XSLT implementation can be found elsewhere. For specific examples, see the above example that uses the query processor. The following example illustrates how to use Java for string manipulation:

<!-- get-dn-prefix places the part of the passed dn that precedes the   -->
<!-- last occurrence of '\' in the passed dn in a result tree fragment   -->
<!-- meaning that it can be used to assign a variable value   -->
<xsl:template name="get-dn-prefix" xmlns:jstring=
   "http://www.novell.com/nxsl/java/java.lang.String">
   <xsl:param name="src-dn"/>
   <!-- use java string stuff to make this much easier -->
   <xsl:variable name="dn" select="jstring:new($src-dn)"/>
   <xsl:variable name="index" select="jstring:lastIndexOf($dn,'\')"/>
   <xsl:if test="$index != -1">
      <xsl:value-of select="jstring:substring($dn,0,$index)"/>
   </xsl:if>
</xsl:template>

How Do I Invoke the Novell XSLT Processor Directly?

Drivers can invoke the Novell XSLT processor directly by using the com.novell.xsl.StyleSheet class. There are various ways in which this can be set up and invoked, so it pays to read all of the documentation. A typical invocation is illustrated by the following code fragment:

import com.novell.nds.dirxml.driver.*;
import com.novell.xsl.*;
import com.novell.xsl.result.*;
import org.w3c.dom.*;
   
.
.
.
   try
   {
      XmlDocument inputDoc = new XmlDocument();
      XmlDocument stylesheetDoc = new XmlDocument();
   
      // load the input and stylesheet documents from a file
      inputDoc.readDocument(new FileInputStream("input.xml"));
      stylesheetDoc.readDocument(new FileInputStream("stylesheet.xsl"));
   
      // create the stylesheet processor and give it the stylesheet
      Stylesheet  styleSheet = new Stylesheet();
      styleSheet.load(stylesheetDoc.getDocument());
   
      // pass in any stylesheet parameters that the stylesheet might need
      st   yleSheet.setParameter("fromNds", new Boolean(fromNDS));
   
      // setup a result handler to get a DOM tree
      Document resultDoc =
        com.novell.xml.dom.DocumentFactory.newDocument();
      DOMResultHandler resultHandler = new DOMResultHandler(resultDoc);
      styleSheet.setResultHandler(resultHandler);
   
      // apply the stylesheet
      styleSheet.process(doc, null);
   
      // result will be in resultDoc
   
}
catch( XSLException xsle )
{
   // handle any exception thrown
}

Are There Other Utility Classes Available?

There are a number of utility classes provided by DirXML or nxsl.jar that are useful to driver writers. Among the most useful are:

  • com.novell.xml.dom.DOMQuery - A class that uses Xpath expressions to find nodes in a DOM tree.

  • com.novell.xml.dom.DOMUtil - This is a utility class for implementing things that XSLT and DirXML need for DOM that are not defined by the 1.0 DOM specification (such as namespaces, serialization, whitespace stripping, id resolution, etc.)

  • com.novell.xml.dom.DOMWriter - This is a class for serializing DOM trees that are used by XmlDocument and DOMUtil. Using this class allows for finer control of the serialization process.

  • com.novell.xsl.util.Util - This utility has a method called getXSLStringValue(), which evaluates the string value of a Node according to the Xpath definition. This is useful for the text content of an element.

  • com.novell.nds.dirxml.driver.DriverFilter and com.novell.nds.dirxml.driver.ClassFilter - These filters allow for easy use of the Publisher Event Filter or the Subscriber Event Filter that is passed to the shim through the init() method.

  • com.novell.nds.dirxml.driver.Trace - This is a facility for drivers to use in order to output debugging trace messages to the DSTRACE console and to the DirXML log file.

  • com.novell.nds.dirxml.driver.DelimitedText - You can use this class for representing a delimited text file as XML.

  • com.novell.nds.dirxml.driver.ThreadBridge - This class implements a method of calling methods on a different thread.

  • com.novell.xml.util.Base64Codec - This class implements encoding and decoding of binary data using the Base64 encoding method. DirXML uses Base64 encoding to encode binary data in command and event notification documents.

Next Month

With this DirXML Engine/Driver explanation now completed, you will be ready for next month's exercise in debugging DirXML drivers using DSTRACE. As to how to set this up, the following will hopefully whet your appetite:

Messages originating from DirXML show up in DSTRACE if you enable the DirXML Drivers events (DVRS on NetWare). By default very little information is given--mostly just the status of events.

To enable more verbose output, add the DirXML-DriverTraceLevel attribute to the DirXML-DriverSet object using the Other tab on the ConsoleOne Properties dialog.

Until next issue...

* Originally published in Novell AppNotes


Disclaimer

The origin of this information may be internal or external to Novell. While Novell makes all reasonable efforts to verify this information, Novell does not make explicit or implied claims to its validity.

© Copyright Micro Focus or one of its affiliates