DITA TC FAQ about keys
The OASIS DITA Technical Committee has realized that parts of the DITA 1.2 specification do not unambigiously cover important questions about keys. We offer the following FAQ items in advance of an DITA 1.2 errata:
Q2: What should rendering tools display in the place of elements which have a keyref attribute?
Q1: Given multiple key definitions, how does a processor determine which key definition is effective?
(Drafted by Eliot Kimber, edited by Kris Eberlein, approved by the DITA TC)
A root map and its referenced submaps can contain multiple different definitions for a key. How does a processor determine which definition of the key name is effective?
The DITA 1.2 specification outlines two things that a processor must accomplish:
- Determine the root map
- Construct the map tree
A processor cannot perform key resolution until the appropriate resolution context has been defined. To do this, the processor must first determine the root map that establishes the key space. For processors such as the DITA Open Toolkit, the root map is obvious – it is the DITA map to which a transformation is applied – but for authoring tools and component content management systems, the root map is not necessarily obvious; such processors might require that a user explicitly select the root map.
Second, the processor must construct the map tree. The map tree consists of all maps referenced from the root map by @href attributes, all maps referenced from submaps by @href attributes, and so on down the map hierarchy.
Processors must construct the map tree by the document order of the references to the maps in a depth-first traversal of the element tree in each map.
Note:
-
The term document order is formally defined in the XPath Recommendation: http://www.w3.org/TR/xpath/#dt-document-order
-
The term map tree refers to the tree of maps constructed in the manner described here, not the XML element tree for the elements within a single map document.
Overview of key-binding precedence
In general, key-binding precedence follows the principle of “earlier and higher.” This means that the “earliest definition within a DITA map” and the “highest map in the map tree” takes precedence. The intent of this is to ensure the following:
- A key definition located earlier in a single DITA map will override a key definition located later in that DITA map. (Within a single DITA map key precedence is determined by document order.)
- A key definition located in a map referenced closer to the root map will override a key definition located farther away from the root map. (Within the map tree, precedence order is determined by a breadth-first traversal in which processes evaluate all children of a given map before evaluating the descendants of those children.)
For example, to find the effective binding for a given key name, processors will start with the root map of the map tree, look for the first binding in document order within that map, then look at each child map of the root map, and then all the children of the first child of the root map, then all the children of the second child of the root map, and so on until a binding for the key is found.
This design ensures that information architects can reuse maps created by others and override the key definitions used by the original authors and architects. In short, if a team wants to override key definitions in effect in a DITA information set, they can do so by declaring a new key-definition submap at the beginning of the root map. Because the key definitions in such a submap come first after all key definitions in the root map, that submap's key definitions will take precedence over all key definitions except those defined in the root map itself. To override a key definition that is declared in the root map, they must declare a new key definition in the root map; the new key definition must be closer to the beginning of the root map.
Example #1
Consider the following root map:
This map contains three <topicref> elements that define the key name "key-01". The effective definition is the binding to topic-1A.dita, because that is the first key definition in document order. The breadth-first rule only applies to the map tree, not to the tree of elements within the DITA map.
Now, consider the root map with a reference to submap 1 added:
If Submap 1 also defines a key name "key-01," that definition cannot be effective. By the breadth-first map tree traversal rule, any definition in the root map takes precedence over definitions in submaps, even though the reference to the submap occurs before any of the key definitions in the root map.
Example #2
Consider a slightly more complicated DITA map with the following characteristics:
- The root map references two submaps.
- One of the submaps references another map.
- The maps contain definitions for two keys–key-01 and key-02–each of which are defined multiple times.
Here is the content of the DITA maps:
Figure: Root map
Figure: Submap-01.ditamap
Figure: Submap-02.ditamap
Figure: Submap-03.ditamap
How are the keys resolved in this example? The processor begins by constructing the following map tree:
When the map tree is traversed in breadth-first order, here is the order in which the DITA maps are encountered:
- Root map
- Submap-01
- Submap-02
- Submap-03
To determine the effective value of “key-01," the processor traverses the map tree until it encounters a definition. Since the root map has at least one definition for that key, the processor stops there; the key name “key-01” is bound to topic-1A.dita.
To determine the effective value of "key-02," the processor traverses the map tree until it encounters a definition. The root map does not contain a key definition nor does Submap-01. Both Submap-02 and Sub-map 03 contain definitions for key-02, but because Submap 2 comes first in the map tree, the definition that it contains is effective. The keyname key-02 is bound to the topic-2A.dita .Example #3
A writing team wants to reuse the set of DITA maps outlined in example #2; however, they want to define different values for the key names “key-01” and “key-02. They intend to use root map 2 as their root map
In order to ensure that the two keys are bound to different resources, the information architect must define new values for the keys at a place higher in the map tree than that used in for example #2. The following code samples would product a different effective value for the two keys:
Figure: Root map
Figure: Key-definition.ditamap
Because key-01 is defined in the root map, the information architect must redefine that key at a point earlier in the root map than the existing key definition. Because the first key definition for key-02 exists in submap-01.ditamap, the information architect can redefine key-02.dita in a key definition map that is referenced at the top of the submap.
Q2: What should rendering tools display in the place of elements which have a keyref attribute?
(Drafted by Su-Laine Yeo, approved by the DITA TC)
The DITA 1.2 release contains a section on "Processing key references" (http://docs.oasis-open.org/dita/v1.2/os/spec/archSpec/processing_key_references.html). This section attempts to specify how elements with keyrefs should be rendered, however the section needs clarification and is missing some important details. The details below will be included in an erratum to the DITA 1.2 specification.
In the following sets of rules, the term "keyref-bearing element" refers to the element within a topic which has a value in its @keyref attribute, and the term "key-defining element" refers to the topic reference whose @keys attribute has the same value. For example, if a map contains:
and a topic contains:
<keyword keyref="product-name"></keyword>
then <keyword> is the keyref-bearing element, and <keydef> is the key-defining element.
Rules for keyref resolution apply only if the key is defined. If the keyref for a particular keyref-bearing element uses an undefined key, these rules should be ignored and the element should be rendered as if does not have a keyref attribute.
A processor must use the first rule that it can apply to the keyref-bearing element. If it cannot apply a rule, it must skip it and consider the next rule. For example, if a rule says to use the contents of the <linktext> element in <topicmeta> in the key-defining element, but <linktext> does not exist, or it is excluded through conditional filtering, then skip that rule and consider the next rule. Where rules refer to a particular element type, they also refer to all specializations of that element type. For example, if a rule refers to the <image> element, it applies equally to specializations of <image>.
There are four sets of rules, for different element types:
1. Elements (except for <abbreviated-form>) which cannot specify a value for @href
2. Elements which can specify a value for @href
3. The <abbreviated-form> element
4. The <image> element
1. Cannot specify a value for @href
For keyref-bearing elements which cannot specify a value for @href, processors should display any content within the keyref-bearing element. If the keyref-bearing element is empty, processors should use the following rules:
-
First choice: Use the contents of the first <keyword> or <term> within <keywords> within <topicmeta> in the key-defining element.
-
Second choice: Use the contents of the <linktext> element within <topicmeta> in the key-defining element.
-
Third choice: Use the contents of the <navtitle> element within <topicmeta> in the key-defining element.
-
Fourth choice: Use the link text determination rules that are used for <xref> elements. For example, if a topic has <term keyref="foo"></term> where the key is resolved using <keydef keys="foo" href="foo.dita"/>, the link text should be the same as the link text used in rendering <xref href="foo.dita"></xref>.
(Examples of elements in topics which can have both a @keyref value but not a @href value are <cite>, <dt>, <keyword>, <term>, <ph>, <indexterm>, <index-base>, <indextermref>, and their specializations.)
2. Can specify a value for @href
For keyref-bearing elements which can specify a value for @href, processors should display any content within the keyref-bearing element. If the keyref-bearing element is empty, processors should use the following rules:
-
First choice: Use the contents of the <linktext> element in <topicmeta> in the key-defining element.
-
Second choice: Resolve the indirect reference as if it were a direct one. For example, if a topic has <xref keyref="foo"></xref> where the key is resolved using <keydef keys="foo" href="foo.dita"/>, it should be rendered as if it were <xref href="foo.dita"></xref>.
(Examples of elements in topics which can have both a @keyref value and a @href value are <author>, <data>, <data-about>, <link>, <lq>, <navref>, <publisher>, <source>, <topicref>, <xref>, and their specializations.)
Some elements can contain a <desc> element, which is typically used as alt text for a link. If the element contains a <desc> element, it should not be overridden. However, if the key-defining element includes a <shortdesc> within <topicmeta>, process the <shortdesc> contents the same way that <desc> would be processed, e.g. treat the <shortdesc> contents as alt text for the link.
3. The <abbreviated-form> element
Processors should follow special rules for this element, detailed in http://docs.oasis-open.org/dita/v1.2/os/spec/langref/abbreviated-form.html#abbreviated-form. If the specific rules for <abbreviated-form> do not produce any content that can be rendered, processors may follow the general processing rules above for keyref-bearing elements which cannot specify a value for @href.
4. The <image> element
Processors should follow special rules for this element, as described in http://docs.oasis-open.org/dita/v1.2/os/spec/langref/image.html, which says, "The image addressed by the keyref or href is brought into the main flow of the content as rendered." If the keyref-bearing <image> contains an <alt> element and/or any attributes (e.g. for indicating the size and placement of the image), processors should use them. Processors are not expected to display <topicmeta> from the key-defining element.
Note that keyref processing does not provide a way to centrally manage alt text for images. DITA adopters who want to have a particular alt text string be reused wherever a particular image is reused should use the conref or conkeyref mechanisms instead of keyref.
Notes:
When displaying content from <topicmeta> in the place of a keyref-bearing element, markup that is valid in the context of the keyref-bearing element should be kept. If <topicmeta> contains markup that is not valid in the new context, the invalid markup may be removed. The content within invalid markup may also be removed.
Note that processors are not required to display any elements from <topicmeta> other than <keyword>, <term>, <linktext>. and <navtitle>. The sentence in the DITA 1.2 specification which says, "matching content includes all elements from within the key definition element that are in valid context within the key reference." (http://docs.oasis-open.org/dita/v1.2/os/spec/archSpec/processing_key_references.html) is ambiguous and can be ignored.
About keyword
Hi Kris,
I worked with some folks who made an intuitive assumption that somehow the keyword element is part of the keys mechanism. Solely based on the fact that the name includes 'key'. Sure, they hadn't read the Spec., nor the helpful DITA Adoption TC article. But two guys independently came to the same wrong conclusion.
I mention this simply because Q2 happens to use the keyword element.
David
Hi, considering
Hi,
considering Example#1, when will the second or next definition for Key-01 be used? What's a use case for more then one keydef in a (root)map?
Regards,
iDTP
<
Response to your question about example #1
The example simply is designed to illustrate the principles of key precedence. However, here is a very simple use case for having more than one key definition in a root map:
Yes, there are other ways to accomplish the same result, for example, team A could have simply modified the @href attribute for the <topicref> element in question.
I think it will be fascinating to watch best practices for the use of keys and keyref evolve.
Kris