Novell is now a part of Micro Focus

How to Analyze NDS.DTD to Construct XDS Documents for DirXML

Articles and Tips: article

Larry Fisher
Senior Software Engineer
DeveloperNet University
lfisher@novell.com

01 Feb 2001


This article discusses how to use NDS.DTD to construct XDS documents describing events for DirXML.

Introduction

The DirXML engine communicates with your driver using XDS documents (DirXML's XML vocabulary for directory event information). Everything your driver tells the DirXML engine to do in the directory and everything the directory tells your driver to do will be in the form of an XDS document.

XDS documents must be appropriate both syntactically and semantically in order for the DirXML engine to process them. Just as a blueprint describes the construction of a building, the NDS.DTD document is used to describe the allowable content in XDS documents. The NDS.DTD is like a recipe book for all allowable XDS statements. It is where the grammar for XDS is defined.

This article demonstrates how to use NDS.DTD to construct XDS documents describing events from a sample application called PBXSimulator.

DTDs are a very complicated topic. To stay as simple as possible, this article will only discusses concepts and tasks that are directly relevant to using NDS.DTD to construct appropriate XDS documents.

Elements in the DTD

The DTD (document type definition) used by DirXML to define XDS has three main elements to be concerned with, ENTITY, ELEMENT, and ATTLIST. Here are descriptions for each:


<!ENTITY>

Defines a selection of allowable items.

<!ELEMENT>

Specifies an element that is eligible to be added to an XDS document.

<!ATTLIST>

Specifies the attributes that can be added to an ELEMENT.

<!ENTITY> Elements

The <!ENTITY> element defines a list of possible items. For example, the <!ENTITY Assoc-State> element shown below (taken from NDS.DTD) defines several potential string values that can replace the term "Assoc-State" whenever it is encountered in an XDS document.

<!ENTITY % Assoc-State"not-associated | associated | disabled | migrate | pending
| manual">

The <!ENTITY> element can also describe the location of an external file full of DTD stuff that can be inserted into the DTD document whenever the particular <!ENTITY> symbol occurs, kind of like a C compiler/preprocessor would do with an #include file. However, we won<t go into that feature because it is not useful to this discussion.

<!ELEMENT> Elements

In NDS.DTD, the <!ELEMENT nds> element describes an XDS element that can be installed into an XDS document. For example, the <!ELEMENT nds> below is the parent element in all XDS documents in DirXML.

<!ELEMENT nds (source?, (input | output))>

Notice that more than just the name of the element is described. The source?, (input | output) values inside of the <!ELEMENT nds> parenthesis define what kind of children it can have, how many of those children it can have, and its relationship to them. By the way, DTD is case sensitive.

First of all, notice that source has a ? symbol following it. The ? symbol means that an <!ELEMENT nds> is allowed to have zero or one child nodes with the name source.

Below is a table showing the other characters used to define child node count in an <!ELEMENT>:


Child Count
Explanation

?

specifies zero or one child node

+

specifies one or more child nodes

*

specifies zero or more child node

none

specifies exactly one child node

Next, notice the nested subexpression, (input | output). This simply means that an <!ELEMENT nds> can also have either an input or an output child.

So, an <!ELEMENT nds> can have zero or one source node and then must have either a single input child node or a single output child node. An input operation would look like this:

<nds>
    <source>
    </source>
    <input>
    </input>
</nds>

<!ATTLIST> Elements

As you know, XML elements often have attributes. The <!ATTLIST< element describes the particular attribute names and values that are allowed for a particular <!ELEMENT<. For example, NDS.DTD defines the <!ATTLIST< below for <!ELEMENT nds<.

<ELEMENT nds (source?, (input | output))>
<ATTLIST nds
    ndsversion  CDATA   #REQUIRED
    dtdversion  CDATA   #REQUIRED>

Notice that the ndsversion and dtdversion attributes in the <!ELEMENT nds< example above are defined as #REQUIRED. This means that these attributes are required in each <!ELEMENT nds<, which of course will always be in an XDS document, because it is the topmost element defined in the NDS.DTD. The possible attribute default specifiers that we are concerned with are listed in the table below.


#REQUIRED

Specifies that the parser must insist that the specified attribute always be in the element.

#IMPLIED

Specifies that the parser should allow the attribute to exist without a value so that the XML application can add one later (if it so chooses).

#FIXED

Specifies that all attribute values of this kind must equal the value specified by this declaration.

Also notice that both of these attributes are defined to be of type CDATA, or character data. The attribute types in NDS.DTD that we need to be concerned with here are the following:


CDATA

Specifies character data (a similar type is PCDATA or parsed character data). For our purposes CDATA and PCDATA can be treated identically.

ENTITY

Specifies a reference to an entity (see <!ENTITY< declaration above) to be inserted as a constant value for the attribute.

ID or IDREF

Specifies that the attribute must have a unique value associated with it. For example, an attribute describing an automobile part might be defined in a DTD like this: !ATTLIST part number IDREFS #REQUIRED/ . ... which could then describe some XML that might look something like this: part number="35"/ Every other part attribute in the XML document would then be required to have a different number than "A35".

NMTOKEN

Specifies that there can be no spaces in the attribute value. A DTD using NMTOKENS might look like this: !ATTLIST part number NMTOKEN #REQUIRED/ ... which might then describe some XML like this: <part number="A35"/< A similar type is NMTOKENS which is used to indicate multiple values, each with white space delimiting it. A DTD using NMTOKENS might look like this: !ATTLIST part numbers NMTOKENS #REQUIRED/ ... which might then describe some XML like this:part numbers="A35 S231 E17"/

Building an Empty Input XDS Document

This section shows how to format a simple input XDS document from sample data.


dtd version

1.0

nds version

8.5

asn1 id

2 16 840 1 113719 1 x

version

1.0b3

product

DirXML

contact

Novell, Inc.

NDS.DTD Excerpts
<ELEMENT nds (source?, (input | output))>
<ATTLIST nds
            ndsversion          CDATA       #REQUIRED
            dtdversion          CDATA       #REQUIRED>

<ELEMENT source (product?,contact?)>

<ELEMENT product (#PCDATA)>
<ATTLIST product
            version         CDATA       #IMPLIED
            asn1id          CDATA       #IMPLIED>
<ELEMENT contact (#PCDATA)>

<ELEMENT input (add|modify|delete|rename|move|query|query-schema
                add-association|modify-association|remove-association|
                init-params|status)*>

How to Build an Empty XDS Document

Follow the steps below.

  1. First, create an nds element, since that is the parent element in every XDS document.

    <nds>
    </nds>
    
  2. Next, we know (from the Sample Data) that we need to add DTD and NDS version information to the document. The DTD line below tells us that an <!ELEMENT nds> must have this information added to it as attributes.

    <ATTLIST nds
        ndsversion  CDATA   #REQUIRED
        dtdversion  CDATA   #REQUIRED>
    

    So, we add those two attributes to the nds element and the resulting document now looks like this:

    <nds dtdversion="1.0" ndsversion="8.5">
    </nds>
    
  3. Next, we know from the Example sample data that we need to add product name, product version, and contact information to the document. The optional source element is designated to contain product and contact information and the <!ELEMENT nds (source?, (input | output))> DTD line tells us that an <!ELEMENT nds> can have zero or one source node.

    So, to include that information we must add these nodes and their attributes to the document.

    <nds dtdversion="1.0" ndsversion="8.5">
        <source>
            <product asn1id="2 16 840 1 113719 1 x" version="1.0b3">DirXML</product>
            <contact>Novell, Inc.</contact>
        </source>
    </nds>
  4. Finally, we know from the <!ELEMENT nds (source?, (input | output))> DTD line, that an nds element must have either a single input child node or a single output child node. So, we'll add an input node to the document.

    <nds dtdversion="1.0" ndsversion="8.5">
        <source>
            <product asn1id="2 16 840 1 113719 1 x" version="1.0b3">DirXML</product>
            <contact>Novell, Inc.</contact>
        </source>
        <input>
        </input>
    </nds>

Q.

How many immediate children can <input< have?

A.

As many as you need.The inside of the parenthetical statement for NDS.DTD's input element declaration (shown below) says that an input element must have exactly one of any of the elements named as possible children.

However, the '*' character after the closing parenthesis says that once the parenthetical statement is resolved, you can have from zero to as many as you want of those resolved parenthetical statements.

<ELEMENT input   (add|modify|delete|rename|move|query|query-schema
        add-association|modify-association|remove-association|
        init-params|status)*>

Note: All of the input elements shown in the DTD line above are possible events that can be sent either from eDirectory to the external system or from the external system to eDirectory for synchronization. If the receiving system needed to send a response to the event, it would build an XDS document containing an output element and send it the opposite direction.

Building an Add Event XDS Document

Now, it's your turn to build an add event XDS document from some sample data using some excerpts from NDS.DTD.

Hints:

  • Do not use a component element.

  • The association element will not have attributes.


dtd version

1.0

nds version

8.5

asn1 id

2 16 840 1 113719 1 x

version

1.0b3

product

DirXML

contact

Novell, Inc.

event

add

class

user

association

0199

src-dn

0199

firstName

Lab1Engineer

lastName

CodeBrain

department

Engineering

location

Provo

phone

222-1234

title

Implementor of Piciune Software Details

NDS.DTD Excerpts
<ENTITY % Assoc-State
   "not-associated|associated|disabled|migrate|pending|manual">
<ENTITY % Attr-type
   "string|teleNumber|int|state|counter|dn|interval|octet|time|structured">
<ENTITY % Boolean   "true | false">

<ELEMENT nds    (source?, (input | output))>
<ATTLIST nds
      ndsversion   CDATA   #REQUIRED
      dtdversion   CDATA   #REQUIRED>

<ELEMENT source    (product?,contact?)>

<ELEMENT product    (#PCDATA)>
<ATTLIST product
      version   CDATA   #IMPLIED
      asn1id    CDATA    #IMPLIED>

<ELEMENT contact (#PCDATA)>

<ELEMENT input (add|modify|delete|rename|move|query|query-schema|
      add-association|modify-association|remove-association|
      init-params|status)*>

<ELEMENT add       (association?, add-attr*, password?)>
<ATTLIST add
      src-dn   CDATA   #IMPLIED
      src-entry-id   CDATA   #IMPLIED
      dest-dn   CDATA   #IMPLIED
      dest-entry-id   CDATA   #IMPLIED
      class-name   CDATA   #REQUIRED
      template-dn   CDATA   #IMPLIED
      event-id   CDATA   #IMPLIED>

<ELEMENT association       (#PCDATA)>
<ATTLIST association
      state    (%Assoc-State;)   #IMPLIED>

<ELEMENT add-attr      (value+)>
<ATTLIST add-attr
      attr-name   CDATA   #REQUIRED>

<ELEMENT value       (<PCDATA | component)*>
<ATTLIST value
      type   (%Attr-type;)   #IMPLIED
      association-ref   CDATA   #IMPLIED
      naming   (%Boolean;)   "false">
<ELEMENT component      (#PCDATA)>
<ATTLIST component
      name   CDATA   #REQUIRED
      association-ref   CDATA   #IMPLIED>
<ELEMENT password      (#PCDATA)>

Exercise

Use the NTS.DTD excerpts above to construct an input XDS document which communicates the information in the Sample Data section above. Try to develop the document without referring to the following answer.

<nds dtdversion="1.0" ndsversion="8.5">
      <source>
            <product asn1id="2 16 840 1 113719 1 x" version="1.0b3">
			DirXML</product>
            <contact>Novell, Inc.</contact>
      </source>
      <input>
         <add class-name="User" src-dn="0199">
            <association"0199"</association>
            <add-attr attr-name="firstName">
               <value type="string">Lab1Engineer</value>
            </add-attr>
            <add-attr attr-name="lastName">
               <value type="string">CodeBrain</value>
            </add-attr>
            <add-attr attr-name="department">
               <value type="string">Engineering</value>
            </add-attr>
            <add-attr attr-name="location">
               <value type="string">Provo</value>
            </add-attr>
            <add-attr attr-name=<phone">
               <value type="telenumber">001-5565</value>
            </add-attr>
            <add-attr attr-name="title">
               <value type="string">Software Engineer</value>
            </add-attr>
         </add>
      </input>
   </nds>

Conclusion

Well, now you are able to use NDS.DTD to write XDS documents to communicate directory event information. This ability is essential so that you can determine the legitimate composition of XDS documents before you write code to build them using DirXML stylesheets or driver shims.

You will find an updated version of this article in the form of a lab in the DirXML Custom Driver Development course on the DeveloperNet web site at: http://developer.novell.com/servlet/devnet/education/index.html.

* 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