> DNU home > online course > DirXML Driver Development
April 2001
DeveloperNet University Course

Lab 2: Analyzing NDS.DTD to Construct XDS Trees


Module Objective: After performing this lab, you should be able to use NDS.DTD to write XDS documents to communicate directory event information so that you can write Java, C++, or XSLT code to construct them properly.

The DirXML engine communicates with your driver using XDS documents. Everything your driver's rules tell the engine to do to the directory and everything the engine tells your driver shims to do will be in this form.

XDS documents must be appropriate syntactically 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 the grammar definition for XDS.

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

Explanations

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

<!ENTITY> Specifies an element which serves as kind of a combination of a #define and a #include.
<!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 describes a set of allowable values when that can be used.

For example, the <!ENTITY Assoc-State> element shown in bold below (taken from NDS.DTD) defines several potential string values.

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

The <!ENTITY Assoc-State> states that whenever the parser sees (%Assoc-State) in a DTD definition, it should refer to its previous declaration to determine the allowable values.

For example, in the state attribute definition for the <!ATTLIST association> element below, the (%Assoc-State;) declaration states that any of the values listed in the previously defined <!ENTITY Assoc-State> element (i.e., "not-associated", or "associated", etc.) are allowable as values as an <association> element's state attribute. (Don't worry, you'll learn more about <!ELEMENT> and
<!ATTLIST> elements later).

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

<!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
<!ELEMENT nds>
's 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, case is important.

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 none or one "source" node and then must have either a single "input" child node or a single "output" child node. For an input operation, that would look like this:


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

But wait, there's more...

<!ATTLIST> ELEMENTs

As you know, XML elements often have attributes. The <!ATTLIST> element describes the particular attribute names and values that are allowable 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:

#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:

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 IDREF #REQUIRED/>
... which could then describe some XML that might look something like this:

<part    number="A35"/>
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"/>


Ok, so we've defined the elements in the DTD. Now, what do we do? Well, let's interpret some excerpts from NDS.DTD to tell us how to format a simple input XDS document from some sample data:

Exercise Example: Building an Empty Input XDS Tree

Example Sample Data

dtd version 1.0
nds version 8.5
asn1 id 2 16 840 1 113719 1 x
version 1.0
product DirXML
contact Novell, Inc.

Example 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)* >

Here is How to Build an Empty XDS Tree:

  1. First, create an nds element since that is the parent element in every XDS document.
<nds>
</nds>
  1. Next, we know from the Example sample data that we need to add dtd and nds version information to the tree. 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 tree now looks like this:

<nds dtdversion="1.0" ndsversion="8.5">
</nds>
  1. 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 none 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.0">
PBXSimulator
</product>
<contact> PBXs_R_Us, Inc.</contact>
</source>
</nds>
  1. 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.0">
PBXSimulator
</product>
<contact> PBXs_R_Us, Inc.</contact>
</source>
<input>
</ input >
</nds>

QUESTION: What kind of child event elements and how many can you put into the <input> element? (HINT: Refer to the DTD excerpts above to help you...)

ANSWER

Well, on to a little tougher quiz...

Exercise 1: Building an Add Event XDS Tree

Now, 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.

Exercise 1 Sample Data

dtd version 1.0
nds version 8.5
asn1 id 2 16 840 1 113719 1 x
version 1.0
product PBXSimulator
contact PBXs_R_Us.
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

Exercise 1 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)>

Do This

Use the NTS.DTD excerpts above to construct an input XDS document which communicates the information in the Exercise 1 sample data above. Construct the document with a word processor or on paper before you look at the answer.

ANSWER

Exercise 2: Building a Modify Event XDS Tree

Now, build a modify event XDS document from some sample data using some excerpts from NDS.DTD:

HINTS:

  • Do not use a component element.
  • Assume that all attributes are single-valued.

Exercise 2 Sample Data


dtd version 1.0
nds version 8.5
asn1 id 2 16 840 1 113719 1 x
version 1.0
product PBXSimulator
contact PBXs_R_Us.
class user
src-dn 0199
association 0199
event modify -> change firstName to Fred
firstName Lab1Engineer

<!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 modify (association?, modify-attr+)>
<!ATTLIST modify
src-dn CDATA #IMPLIED
src-entry-id CDATA #IMPLIED
dest-dn CDATA #IMPLIED
dest-entry-id CDATA #IMPLIED
class-name CDATA #IMPLIED
event-id CDATA #IMPLIED>

<!ELEMENT modify-attr (remove-value | remove-all-values | add-value)+>
<!ATTLIST modify-attr
attr-name CDATA #REQUIRED>

<!ELEMENT remove-all-values EMPTY>

<!!ELEMENT remove-value (value+)>

<!ELEMENT add-value (value+)>

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

<!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>

Do This

Use the NTS.DTD excerpts above to construct an input XDS document which communicates the information in the Exercise 2 sample data above. Construct the document with a word processor or on paper before you look at the answer.

ANSWER

Previous Contents Next
download sample file