 |
|
|
 |
| 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:
- First, create an nds element since that is the parent element in every XDS document.
<nds> </nds>
- 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>
- 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>
- 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
|