How to Analyze NDS.DTD to Construct XDS Documents for DirXML
Articles and Tips: article
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
- Elements in the DTD
- Building an Empty Input XDS Document
- Building an Add Event XDS Document
- Conclusion
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.
-
First, create an nds element, since that is the parent element in every XDS document.
<nds> </nds>
-
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>
-
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>
-
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.