Key-based (indirect) addressing

The DITA key reference facility provides a layer of abstraction so that the resources addressed by references throughout a document may be defined globally at the map level.

When using content in the context of different maps, it is often necessary to have the same semantic or rhetorical relationship resolve to different resources in different map contexts. For example, a content reference to a phrase element containing the product name needs to resolve to different phrase elements in different product-specific maps. The DITA key reference facility satisfies this requirement by providing an indirect addressing mechanism that separates references (topicrefs, conrefs, cross references, etc.) from the direct address of the target. Linking elements can refer to "key names" that are then bound to specific resources by maps. Different maps can bind the same key names to different resources. This form of indirection is "late bound" because the binding of key names to resources is determined at processing time based on the current set of key definitions for the map context rather than from a static binding created when a topic or map is authored.

Defining keys

Keys are defined within maps. Key names are defined using the @keys attribute on <topicref> elements (or specializations of topicref, such as <keydef>).

The value of the @keys attribute is one or more space-separated key names. Key names consist of characters that are legal in a URI. The case of key names is significant. The following characters are prohibited in key names: "{", "}", "[", "]", "/", "#", "?", and whitespace characters.

Note: The @keys attribute in any <topicref> element may be used to define keys, regardless of any other purpose it may serve in the map. However, common practice is to define most or all keys separately from the topic references used to establish navigation hierarchies and relationships. If a separate submap is created that contains only key definitions, it should have the value "resource-only" on the @processing-role attribute. The standard map group vocabulary module includes the <keydef> element, a specialization of <topicref> in which the value of the @processing-role attribute is pre-set to "resource-only".

Key binding

A key may be bound simultaneously to several resources:

Key spaces

A root map and its directly-addressed local-scope descendant maps establish a unique "key space" within which each unique key name has exactly one binding to a set of resources.
Note: Maps addressed by <navref> do not contribute to the key space of a map tree. Maps referenced by <navref> are equivalent to maps referenced with a scope of "peer" or "external" and therefore need not be present or available at the time the referencing map is processed for purposes of key space construction.

For the purposes of determining the effective key definitions for the key space represented by a given root map, a map tree is determined by considering only directly-addressed, local-scope maps descending from the root map. The order of subordinate maps is determined by the document order of the topicrefs that point to them. Indirect references to maps with key references are necessarily ignored until after the key space is determined.

Effective key definitions

For a given key there is at most one effective definition within a key space. A key definition is the effective definition for a given key if it is the first, in document order, within the map document that contains it, and is the first in the map tree in breadth-first order. It is not an error for the same key name to be defined more than once within a map or map tree, and duplicate key definitions should be ignored without warning.

Note: A given <topicref> element that defines more than one key may be the effective definition for some of its keys but not for others. It is the duplicate binding of a key name to its definition that is ignored, not the key-defining topic reference as a whole.

Key definitions are not scoped by the map document within which they occur or by the element hierarchy of their containing map document. Keys do not have to be declared before they are referenced. The key space is effective for the entire document, so the order of key definitions and key references relative to one another within the map hierarchy is not significant, and keys defined in any map in the map tree are available for use with key references from all maps and topics processed in the context of the root map.

Note: These rules mean that key definitions higher in the map tree hierarchy take precedence over key definitions lower in the map tree and that key definitions in referencing maps always take precedence over key definitions in referenced maps. These rules also mean that the entire key space must be determined before any keys can be resolved to their ultimately-addressed resources (if any).
Note: Because keys are defined in maps, all key-based processing must be done in the context of a root map that establishes the effective key space.

For key definitions in a submap to be included in the key space, there must be a direct URI reference to that submap from another directly-addressed map in the map tree. However, if that same submap is referenced indirectly and has no direct URI reference as a backup (using @keyref without providing a fallback @href value, or using @conkeyref without providing a fallback @conref value), that reference is ignored for purposes of constructing the key space, and the definitions in that submap consequently do not enter into the construction of the key space at that point.

Keys and conditional processing

The effective keys for a given map may be affected by conditional processing (filtering). Filtering should be applied before determining effective key definitions. However, processors may determine effective key bindings before filtering. Consequently, different processors may produce different effective bindings for the same map when there are key definitions that may be filtered out based on their select attributes.

Note: If filtering is not done first, the same root map may result in different effective key spaces for different sets of conditions. For processors that provide sets of available keys within an information set, such as authoring support systems, keys may need to be associated with the conditions specified on their key definitions. For example, given a map that defines the key "os-name" twice with different conditions, an author may need to know both that the key has two possible bindings within the key space and what the conditions are under which those bindings are effective. It also means that processors may need both a root map and a set of active conditions (e.g., a ditaval document) in order to correctly determine the effective key space.

A relative URI reference in a key definition is resolved relative to the base URI established for the location of the key definition rather than relative to the various locations of references using the key.

Addressing DITA resources and elements with keys

For topic references, image references, and navigation link relationships (<link>, <xref>, and elements that take @keyref but not @href), resources may be addressed by key using the @keyref attribute. For content reference relationships, resources may be addressed by key using the @conkeyref attribute.

If both @keyref and @href are specified, the @href value is used as a fallback address when the key reference cannot be resolved to a resource. If both @conkeyref and @conref are specified, the @conref value is used as a fallback address when the key cannot be resolved.

For references to topics, maps, and non-DITA resources, the value of the @keyref attribute is simply a key name: keyref="topic-key".

For references to non-topic elements within topics and non-topicref elements within maps, the value of the @keyref attribute is a key name, a solidus ("/"), and the ID of the target element: keyref="topic-key/some-element-id".

Note:
For example, consider this topic in the document "file.dita":
<topic id="topicid">
 <title>Example referenced topic</title>
 <body>
  <p id="para-01">Some content.</p>
 </body>
</topic>
and this key definition:
<map>
  <topicref keys="myexample"
    href="file.dita"
  />
</map>

A keyref of the form "myexample/para-01 resolves to the <p> element in the topic. The key reference would be equivalent, in the context of this map, to the URI reference file.dita#topicid/para-01.

A key reference to a topicref element where the linking element specifies a format value of "ditamap" addresses the topicref element itself as though the topicref element had been addressed by ID. In particular, a topicref with a key reference to another topicref and a format value of "ditamap" is a use of the map branch rooted at the referenced topicref.

Processing key references

When a key definition is bound to a resource addressed by @href or @keyref and does not specify "none" for the @linking attribute, all references to that key definition become navigation links to the bound resource. When a key definition is not bound to a resource or specifies "none" for the @linking attribute, references to that key do not become navigation links.

When a key definition has a <topicmeta> subelement, elements that refer to that key and that are empty may get their effective content from the first matching subelement of the <topicmeta> subelement of the key-defining topicref.

When a key definition has no @href value, references to that key will not result in a link, even if they do contain an @href attribute of their own. If the key definition also does not contain a <topicmeta> subelement, empty elements that refer to the key (such as <link keyref="a"/> or <xref keyref="a" href="fallback.dita"/>) are removed.

Matching element content for key references contained in @keyref or @conkeyref attributes falls into one of two categories:
  1. For elements on which no @href attribute is available (cite, dt, keyword, term, ph, indexterm, index-base, and indextermref, and their specializations), matching content is taken from the <keyword> or <term> elements within <keywords> within <topicmeta>. If more than one <keyword> or <term> is present, the matching content is taken from the first of them.
  2. For elements that in addition to @keyref or @conkeyref do specify an @href attribute (author, data, data-about, image, link, lq, navref, publisher, source, topicref, xref, and their specializations), matching content includes all elements from within the key definition element that are in valid context within the key reference. Elements that are invalid within the key reference element directly or after generalization are not included or are filtered out.

For key reference elements that become navigation links, if there is no matching element in the key definition, normal link text determination rules apply as for <xref>.

If a referencing element contains a key reference with an undefined key, it is processed as if there were no key reference, and the value of the @href attribute is used as the reference. If the @href attribute is not specified either, the element is not treated as a navigation link. If it is an error for the element to be empty, an implementation may give an error message, and may recover from this error condition by leaving the key reference element empty.

For topic references that use the @keyref attribute, the effective value of the <topicref> element is determined as follows:
  • The effective resource bound to the <topicref> element is determined by resolving all intermediate key references. Each key reference is resolved either to a resource addressed directly by URI reference in an @href attribute, or to no resource. Processors may impose reasonable limits on the number of intermediate key references they will resolve. Processors should support at least three levels of key references.

    Note: This rule applies to all topic references, including those that define keys. Thus, the effective bound resource for a key definition that uses the @keyref attribute cannot be determined until the key space has been constructed.

    The attributes that are common to a key definition element and a key reference element using that key, other than the @keys and @id attributes, are combined as for content references, including the special processing for the @xml:lang, @dir, and @translate attributes. There is no special processing associated with either the @locktitle or the @lockmeta attributes when attributes are combined.

    When attributes are combined, the attributes on a key definition element take precedence over the attributes on a key reference element. For a chain of key reference elements, the priority for combining attributes is:
    • First key-defining element
    • Second key-defining element
    • ...
    • last key-defining element
    • key reference element
  • Content from a key reference element and a key-defining element is combined following the rules for combining metadata between maps and other maps and between maps and topics. The @lockmeta attribute is honored when metadata content is combined.
  • The combined attributes and content cascade from one map to another or from a map to a topic, but this is controlled by existing rules for cascading, which are not affected by the use of key references.

Examples

(Non normative)

Figure 1. A generic topicref element used to define a key bound to a topic:
<map>
  ...
  <topicref keys="apple-definition"
    href="topics/glossary/apple-gloss-en-US.dita"
  />
  ...
</map>

In this example, the topicref is acting as both a key definition and contributing to the navigation structure of the map, meaning the topic apple-gloss-en-US.dita will be processed as it would be if the @keys attribute were not present.

Figure 2. The same key definition using the <keydef> specialization of <topicref>:
<map domains="(map mapgroup)">
  ...
  <keydef keys="apple-definition"
    href="topics/glossary/apple-gloss-en-US.dita"
  />
  ...
</map>

Because the <keydef> element sets the default value of the @processing-role attribute to "resource-only", the key definition does not contribute to the map's navigation structure, but only serves to establish the key-to-resource binding for the key "apple-definition".

Figure 3. Duplicate definition of the same key:
<map domains="(map mapgroup)">
  ...
  <keydef keys="load-toner"
    href="topics/tasks/model-1235-load-toner-proc.dita"
  />
  <keydef keys="load-toner"
    href="topics/tasks/model-4545-load-toner-proc.dita"
  />
  ...
</map>

In this example, only the first definition in document order of the "load-toner" key is effective, so all references to the key within the scope of the root map will resolve to the topic model-1235-load-toner-proc.dita, not topic model-4545-load-toner-proc.dita.

Figure 4. Duplicate definitions with different conditions:
<map domains="(map mapgroup)">
  ...
  <keydef keys="file-chooser-dialog"
    href="topics/ref/file-chooser-osx.dita"
    platform="osx"
  />
  <keydef keys="file-chooser-dialog"
    href="topics/tasks/file-chooser-win7.dita"
    platform="windows7"
  />
  ...
</map>

In this example, both key definitions use the @platform metadata attribute to indicate that they apply to different operating system platforms. In this case, the effective key definition is determined not just by the order in which the definitions occur but whether the active value of @platform is "osx" or "windows7" when the key space is determined or the key is resolved. In this case both key definitions are potentially effective because they have distinct values for conditional attributes. Note that if no active value is specified for the @platform condition when determining the effective keys, then both of the definitions are effective and thus the first one in document order is the effective definition.

If the DITA value configuration were defined such that the default behavior is "exclude" rather than the normal default of "include", then neither definition would be effective and the key would be undefined. That case can be avoided by specifying an unconditional key definition after any conditional key definitions, e.g.:
<map domains="(map mapgroup)">
  ...
  <keydef keys="file-chooser-dialog"
    href="topics/ref/file-chooser-osx.dita"
    platform="osx"
  />
  <keydef keys="file-chooser-dialog"
    href="topics/tasks/file-chooser-win7.dita"
    platform="windows7"
  />
  <keydef keys="file-chooser-dialog"
    href="topics/tasks/file-chooser-generic.dita"
  />
  ...
</map>

In this case, with an explicitly-configured default behavior of "exclude", if no active value for the platform condition is specified, the third definition will be the effective definition, binding the key "file-chooser-dialog" to the topic file-chooser-generic.dita.

Figure 5. Duplicate key definitions using subordinate maps
Root map:

<map domains="(map mapgroup)">
  <keydef keys="toner-specs"
   href="topics/reference/toner-type-a-specs.dita"
  />
  <mapref href="submap-01.ditamap"/>
  <mapref href="submap-02.ditamap"/>
</map>

submap-01.ditamap:

<map domains="(map mapgroup)">
  <keydef keys="toner-specs"
   href="topics/reference/toner-type-b-specs.dita"
  />
  <keydef keys="toner-handling"
   href="topics/concepts/toner-type-b-handling.dita"
  />
</map>

submap-02.ditamap:

<map domains="(map mapgroup)">
  <keydef keys="toner-specs"
   href="topics/reference/toner-type-c-specs.dita"
  />
  <keydef keys="toner-handling"
   href="topics/concepts/toner-type-c-handling.dita"
  />
  <keydef keys="toner-disposal"
   href="topics/tasks/toner-type-c-disposal.dita"
  />
</map>
In this example the effective key space is:
Key Bound resource
toner-specs toner-type-a-specs.dita
toner-handling toner-type-b-handling.dita
toner-disposal toner-type-c-disposal.dita

The binding for the key "toner-specs" in the root map is effective because it is the first encountered in a breadth-first traversal of the map tree. The binding for the key "toner-handling" to the definition in submap-01.ditamap is effective because submap-01 is included before submap-02 and therefore comes first in the map tree. The binding for the key "toner-disposal" is effective because it is the only definition of the key in the map tree.

Figure 6. A key definition that uses elements within the key definition rather than a separately-addressed resource
<map domains="(map mapgroup)">
  <keydef keys="product-name">
    <topicmeta>
     <keywords>
       <keyword>Thing-O-Matic</keyword>
     </keywords>
    </topicmeta>
  </keydef>
</map>
This form of key definition would normally be used from a <keyword> element in order to use the value defined in the key definition:
<topic id="topicid">
  <title>About the <keyword keyref="product-name"/> product</title>
</topic>

Normal processing results in the effective title text "About the Thing-O-Matic product".

Figure 7. A key definition that uses both elements within the key definition and points to a resource
<map domains="(map mapgroup)">
  <keydef keys="yaw-restrictor"
    href="parts/subassem/subassm-9414-C.dita"
  >
    <topicmeta>
     <keywords>
       <keyword>yaw restrictor assembly</keyword>
     </keywords>
    </topicmeta>
  </keydef>
</map>

When referenced from a <keyword> element with no directly-specified content, normal processing sets the effective content of the keyword to "yaw restrictor assembly" and makes the keyword a navigation link to the topic subassm-9414-C.dita.

Figure 8. Redirect a link or xref
  1. Author 1 creates a map that associates keys with each topic, for example <topicref keys="a" href="a1.dita"/>
  2. Author 1 creates topic c.dita that contains a related link to a0.dita - but uses the keyref attribute: <link keyref="a" href="a0.dita"/>
  3. Author 2 reuses c.dita, but wants to redirect the link, so applies a different map with <topicref keys="a" href="a2.dita"/>. The link in c.dita now resolves to a2.dita when author 2 builds it (it continues to resolve to a1.dita when author 1 builds it)
  4. Author 3 also reuses c.dita, but wants the link to point to an external resource, so creates an external-pointing topicref to resolve the key:
    <topicref  keys="a" href="http://www.a..." scope="external">
      <topicmeta>
        <linktext>This links to A2</linktext>
        <shortdesc>Because it does.</shortdesc>
      </topicmeta>
    </topicref>

    The link in c.dita now resolves to an external URI reference when author 3 builds it (without affecting how it resolves for the other two reusers).

  5. Author 4 wants to get rid of the link, so creates an explicitly empty topicref to get rid of it: <topicref keys="a"/>. This gets rid of the link for author 4 without affecting the other reusers.
  6. Author 5 wants to turn the link into just plain text (not hypertext) - for example a citation of a print-only magazine article.
    <topicref  keys="a">
      <topicmeta>
        <linktext>This is just text.</linktext>
      </topicmeta>
    </topicref>
  7. Author 6 reuses c.dita, but does not include a topicref that defines the key “a” in the map. Topic a0.dita is used as the “fallback” related link.
Figure 9. Redirect conref
  1. Author 1 creates a map that associates a key with a topic that contains reusable elements, for example <topicref keys="reuse" href="prodA/reuse.dita"/>
  2. Author 1 uses the key instead of the full href whenever creating conrefs - for example <p conkeyref="reuse/para1"/>
  3. Author 2 wants to reuse author 1's content, but swap in a different set of reusable content. So Author 2 associates the key "reuse" with a different topic: <topicref keys="reuse" href="prodB/mytopic.dita"/>. So now <p conkeyref="reuse/para1"/> will resolve to a paragraph with the id “para1” in prodB/mytopic.dita when author 2 builds the content, while continuing to resolve to the para with the id “para1” in prodA/reuse.dita for author 1.
Note: The reusing author must create a parallel set of elements and IDs in the replacement topic; the element IDs within the topic are not remapped, only the pointer to the topic container.
Figure 10. Create links from keywords, terms, or other elements
  1. Author 1 creates a map that contains glossary entries, and associates keys for each entry: <topicref keys="myterm" href="myterm.dita"/>
  2. Author 1 then uses the keys to create links to the appropriate glossary entry from occurrences of terms in content: <term keyref="myterm">my term</term>.
Figure 11. Swap out variable content
  1. Author 1 creates a map for key words and phrases that tend to change, such as UI labels and product names. The topicrefs do not in this case contain any actual hrefs, just the text that should be used:
    <topicref keys="prodname">
      <topicmeta>
        <linktext>My Product</linktext>
      </topicmeta>
    </topicref>
  2. Author 1 then uses the keys to draw text into empty keywords: <keyword keyref="prodname"/>
  3. Author 2 reuses the content but wants to use a different product name, so associates prodname with a different string:
    <topicref keys="prodname">
      <topicmeta>
        <linktext>Another Product</linktext>
      </topicmeta>
    </topicref>

    The keyword now resolves to "Another Product" for author 2, while continuing to resolve to "My Product" for author 1.

Note: A processor should generate a warning message when a key reference on an empty element cannot be resolved, resulting in the element effectively being removed.
Figure 12. Splitting or combining targets
  1. Author 1 creates a map in which most branches have the same structure: intro, example, reference. Two branches have only very little content in them, because the product support is only minimal. In anticipation of future elaboration, author 1 assigns 4 keys to the container under which more topics are expected in the future:
    <topicref keys="blat-overview blat-intro blat-example blat-reference" 
              href="blat-overview.dita"/>
  2. Author 2 references blat-example, and in the future when Author 1 moves blat-example into a separate topic, author 2's link remains appropriate and valid and does not need to be reworked.
  3. Author 3 is reusing a bunch of author 1's content, but in a context where blats are not available, and are instead replaced by foobars. So author 3 simply adds the blat keys to their own foobar topicref:
    <topicref keys="blat-overview blat-intro blat-example blat-reference foobar" 
              href="foobar.dita"/>
Figure 13. Removing a link
  1. Author 1 creates a map which defines the key "overview":
    <topicref keys="overview" 
              href="blat-overview.dita"/>
  2. Author 1 adds a link to the topic productInfo.dita using they keyref attribute, and using the href as a fallback:
    <link keyref="overview" href="blat-overview.dita"/>
  3. Author 2 wishes to reuse productInfo.dita, but does not want a link to overview information. So, author 2 creates a new definition for the key overview that does not have a target:
    <topicref keys="overview"/>

    The link element which uses keyref="overview" is now removed, because there is no target and no link text.

Return to main page.

DITA v1.2 CD 03
Copyright © OASIS Open 2005, 2010. All Rights Reserved.