Branch filtering

The branch filtering mechanism enables map authors to set filtering conditions for specific branches of a map. This makes it possible for multiple conditional-processing profiles to be applied within a single publication.

Conditional processing profiles are most often used for an entire root map, with rules applied to all content in that root map. The branch filtering mechanism uses the <ditavalref> element to apply rules from a single DITAVAL document against a subset of content.

The location of the <ditavalref> element determines the content to which filtering conditions are applied. The filtering conditions then are used to filter the map branch itself (that is, the map elements used to create the branch). In addition, it is used to filter local maps and topics that are referenced by that branch.

The <ditavalref> element also provides the ability to process a single branch of content multiple times, applying unique conditions to each instance of the branch.

Overview of branch filtering

Maps or map branches can be filtered by adding a <ditavalref> element that specifies the DITAVAL document to use for that map or map branch.

The <ditavalref> element is designed to manage conditional processing for the following use cases.

  1. A map branch needs to be filtered using conditions that do not apply to the rest of the publication. For example, a root map might contain content that is written for both novice and expert users. However, the authors want to add a section that targets only novice users. Using branch filtering, a map branch can be filtered so that it only includes content germane to a novice audience, while the content of the rest of the map remains appropriate for multiple audiences.
  2. A map branch needs to be presented differently for different audiences. For example, a set of software documentation might contain installation instructions that differ between operating systems. In that case, the map branch with the installation instructions needs to be filtered multiple times with distinct sets of conditions, while the rest of the map remains common to all operating systems.

In addition to filtering, applications MAY support flagging at the branch level based on the referenced DITAVAL documents.

How filtering rules interact

With branch filtering, it is possible to set include or exclude rules globally, within a map, and within an already filtered map branch. The general rule for conflicts is that once specified, "exclude" conditions are in effect for the entire map or branch.

Filtering rules often are specified globally in a conditional processing profile, outside of the content. When global conditions set a property value to "exclude", that setting overrides any other settings for the same property that are specified at a branch level. Global conditions that set a conditional property to "include" or "flag" do not override branch-level conditions that set the same property to "exclude".

Using <ditavalref> elements, it is possible to specify one set of conditions for a branch and another set of conditions for a subset of the branch. As with global conditions, properties set to "exclude" for a map branch override any other settings for the same property specified for a subset of the branch. Branch conditions that set a conditional property to "include" or "flag" do not override conditions on a subset of the branch that explicitly set the same property to "exclude".

Branch filtering: Single referenced DITAVAL document for a branch

Using a single <ditavalref> element as a child of a map or map branch indicates that the map or map branch is filtered using the rules specified in the referenced DITAVAL document.

The following rules outline how the filtering conditions that are specified in DITAVAL document are applied:

<ditavalref> element as a direct child of a map
The filtering conditions are applied to the entire map.
<ditavalref> element within a map branch
The filtering conditions are used to process the entire branch, including the parent element that contains the <ditavalref> element.
<ditavalref> element within a <topicref> reference to a local map
The filtering conditions are applied to the submap.
<ditavalref> element within a <topicref> reference to peer map
The reference conditions are not applied to the peer map.

Branch filtering: Multiple referenced DITAVAL documents for a branch

Using multiple <ditavalref> elements as the children of a map or map branch indicates that the map or map branch will be independently filtered using the rules that are specified in each referenced DITAVAL document.

When multiple <ditavalref> elements occur as children of the same element, the rules in the referenced DITAVAL documents are processed independently. This effectively requires a processor to maintain one copy of the branch for each <ditavalref>, so that each copy can be filtered using different conditions.

Note (non-normative):
In most cases, it is possible to create a valid, fully-resolved view of a map with branches copied to reflect the different <ditavalref> conditions. However, this might not be the case when multiple <ditavalref> elements occur as direct children of a root map. In this case, it is possible that the map could be filtered in a manner that results in two or more distinct versions of the <title> or metadata. How this is handled is processor dependent. For example, when a root map has three <ditavalref> elements as children of <map>, a conversion to EPUB could produce an EPUB with three versions of the content, or it could produce three distinct EPUB documents.

When a processor maintains multiple copies of a branch for different condition sets, it has to manage situations where a single resource with a single key name results in two distinct resources. Key names must be modified in order to allow references to a specific filtered copy of the resource; without renaming, key references could only be used to refer to a single filtered copy of the resource, chosen by the processor. See Branch filtering: Impact on resource and key names for details on how to manage resource names and key names.

Branch filtering: Impact on resource and key names

When map branches are cloned by a processor in order to support multiple condition sets, processors must manage conflicting resource and key names. The DITAVALref domain includes metadata elements that authors can use to specify how resource and key names are renamed.

Note (non-normative):
While the processing controls that are described here are intended primarily for use with map branches that specify multiple condition sets, they also can be used with map branches that include only a single <ditavalref> element.

When a map branch uses multiple condition sets, processors create multiple effective copies of the branch to support the different conditions. This results in potential conflicts for resource names, key names, and key scopes. Metadata elements inside of the <ditavalref> element are available to provide control over these values, so that keys, key scopes, and URIs can be individually referenced within a branch.

For example, the following map branch references two DITAVAL documents:

<topicref href="productFeatures.dita" keys="features" keyscope="prodFeatures">
  <ditavalref href="novice.ditaval"/>
  <ditavalref href="admin.ditaval"/>
  <topicref href="newFeature.dita" keys="newThing"/>
</topicref>

In this case, the processor has two effective copies of productFeatures.dita and newFeature.dita. One copy of each topic is filtered using the conditions specified in novice.ditaval, and the other copy is filtered using the conditions specified in admin.ditaval.

If an author has referenced a topic using keyref="features" or keyref="prodFeatures.features", a processor cannot distinguish which filtered copy is the intended target. The metadata elements in the DITAVALref domain provide a way to control this scenario.

Using metadata elements in the DITAVAL reference domain

Metadata within the <ditavalref> element makes it possible to control changes to resource names and key scope names, so that each distinct filtered copy can be referenced in a predictable manner.

The DITAVALref domain defines four elements to control URI and key scope values within filtered map branches.

<dvrResourcePrefix>
The <dvrResourcePrefix> element specifies the prefix to use when constructing the effective file names or resource IDs of the resources that are referenced from within the map branch that is implied by the ancestor <ditavalref> element. This enables a map author to specify a prefix that is added to the start of resource names for each resource in the branch.
<dvrResourceSuffix>
The <dvrResourceSuffix> element specifies the prefix to use when constructing the effective file names or resource IDs of the resources that are referenced from within the map branch that is implied by the ancestor <ditavalref> element. This enables a map author to specify a suffix that is added to the end of resource names (before any extension) for each resource in the branch.
<dvrKeyscopePrefix>
The <dvrKeyscopePrefix> element specifies the prefix to use when constructing the effective key scope names for the map branch that is implied by the ancestor <ditavalref> element. This enables a map author to specify a prefix that is added to the start of key scope names for each key scope in the branch. If no key scope is specified for the branch, this can be used to establish a new key scope, optionally combined with a value specified in <dvrKeyscopeSuffix>.
<dvrKeyscopeSuffix>
The <dvrKeyscopeSuffix> element specifies the suffix to use when constructing the effective key scope names for the map branch that is implied by the ancestor <ditavalref> element. This enables a map author to specify a suffix that is added to the end of key scope names for each key scope in the branch.

For example, the previous code sample can be modified as follows to create predictable resource names and key scopes for the copy of the branch that is filtered using the conditions that are specified in admin.ditaval.

<topicref href="productFeatures.dita" keys="features" keyscope="prodFeatures">
  <ditavalref href="novice.ditaval"/>
  <ditavalref href="admin.ditaval">
    <ditavalmeta>
      <dvrResourcePrefix>admin-</dvrResourcePrefix>
      <dvrKeyscopePrefix>adminscope-</dvrKeyscopePrefix>
    </ditavalmeta>
  </ditavalref>
  <topicref href="newFeature.dita" keys="newThing"/>
</topicref>

The novice branch does not use any renaming, which allows it to be treated as the default copy of the branch. As a result, when the topics are filtered using the conditions that are specified in novice.ditaval, the resource names and key names are unmodified, so that references to the original resource name and key name will resolve to topics in the novice copy of the branch. This has the following effect on topics that are filtered using the conditions specified in admin.ditaval:

  • The prefix admin- is added to the beginning of each resource name in the admin branch.
    • The resource productFeatures.dita becomes admin-productFeatures.dita
    • The resource newFeature.dita becomes admin-newFeature.dita
  • The prefix adminscope- is added to the existing key scope "prodFeatures".
    • The attribute value keyref="adminscope-prodFeatures.features" refers explicitly to the admin copy of productFeatures.dita
    • The attribute keyref="adminscope-prodFeatures.newThing" refers explicitly to the admin copy of newFeature.dita
Note (non-normative):
In general, the best way to reference a topic that will be modified based on branch filtering is to use a key rather than a URI. Key scopes and key names (including those modified based on the elements above) must be calculated by processors before other processing. This means that in the example above, a key reference to adminscope-prodFeatures.features will always refer explicitly to the instance of productFeatures.dita filtered against the conditions in admin.ditaval, regardless of whether a processor has performed the filtering yet. References that use the URI productFeatures.dita or admin-productFeatures.dita could resolve differently (or fail to resolve), as discussed in Branch filtering: Implications of processing order.

Renaming based on multiple <ditavalref> elements

It is possible for a branch with <ditavalref> already in effect to specify an additional <ditavalref>, where each <ditavalref> includes renaming metadata.

When renaming, metadata on the <ditavalref> nested more deeply within the branch appears closer to the original resource or key name. For example:

<topicref href="branchParent.dita">
  <ditavalref href="parent.ditaval">
    <ditavalmeta>
      <dvrResourcePrefix>parentPrefix-</dvrResourcePrefix>
    </ditavalmeta>
  </ditavalref>
  <!-- additional topics or layers of nesting -->
  <topicref href="branchChild.dita">
    <ditavalref href="child.ditaval">
      <ditavalmeta>
        <dvrResourcePrefix>childPrefix-</dvrResourcePrefix>
      </ditavalmeta>
    </ditavalref>
  </topicref>
</topicref>

In this situation, the resource branchChild.dita is given a prefix based on both the reference to parent.ditaval and the reference to child.ditaval. The value childPrefix- is specified in the <ditavalref> that is nested more deeply within the branch, so it appears closer to the original resource name. The resource branchChild.dita would result in parentPrefix-childPrefix-branchChild.dita. Suffixes (if specified) would be added in a similar manner, resulting in a name like branchChild-childSuffix-parentSuffix.dita. Note that the hyphens are part of the specified prefix; they are not added automatically.

Handling resource name conflicts caused by branch filtering

It is possible to construct a root map where the branch filtering mechanism results in resource name conflicts.

It is an error if <ditavalref>-driven branch cloning results in multiple copies of a topic that have the same resolved name. Processors SHOULD report an error in such cases. Processors MAY recover by using an alternate naming scheme for the conflicting topics.

In rare cases, a single topic might appear in different branches that set different conditions, yet still produce the same result. For example, a topic might appear in both the admin and novice copies of a branch but not contain content that is tailored to either audience; in that case, the filtered copies would match. A processor MAY consider this form of equivalence when determining if two references to the same resource should be reported as an error.

Branch filtering: Implications of processing order

The branch filtering mechanism can result in changes to the global key space for a root map. As a result, processors are required to evaluate branch filtering in order to construct the key space.

The full effects of the branch filtering process MUST be calculated by processors before they construct the effective map and key scope structure. This requirement comes from the fact that the branch filtering process can result in new or renamed keys, key scopes, or URIs that make up the key space.

Note (non-normative):
The @keyref attribute and related attributes are explicitly disallowed on <ditavalref>. This prevents any confusion resulting from a @keyref that resolves to additional key- or resource-renaming metadata.

In general, the DITA specification refrains from mandating a processing order; thus publication results can vary slightly depending on the order in which processes are run. With branch filtering, processors are not required to apply filter conditions specified outside of the map and filter conditions specified with <ditavalref> at the same time in a publishing process.

For example, a processor might use the following processing order:

  1. Apply externally-specified filter conditions to maps
  2. Apply filtering based on <ditavalref> elements

Because externally-specified "exclude" conditions always take precedence over branch-specific conditions, content excluded based on external conditions will always be removed, regardless of the order in which processors evaluate conditions.

Processors should consider the following points when determining a processing order:

  • If links are generated based on the map hierarchy, those links should be created using the renamed keys and URIs that result from evaluating the <ditavalref> filter conditions, to ensure that the links are consistent within the modified branches. For example, sequential links based on a map hierarchy should remain within the appropriate modified branch.
  • If URI-based content references are resolved in topics before the <ditavalref> filtering conditions are evaluated, content that applies to multiple audiences can be brought in and (later in the process) selectively filtered by branch. For example, if a set of installation steps is pulled in with conref (from outside the branch), it might contain information that is later filtered by platform based on <ditavalref>. This results in copies of the steps that are specific to each operating system. If conref is processed after the <ditavalref>, content might be pulled in that has not been appropriately filtered for the new context.
  • The same scenario applies to conref values that push content into the branch.
    • Pushing content into a branch before resolving the <ditavalref> conditions allows content for multiple conditions to be pushed and then filtered by branch based on the <ditavalref> conditions.
    • If the branch using <ditavalref> pushes content elsewhere, resolving <ditavalref> first could result in multiple copies of the content to be pushed (one for each branch), resulting in multiple potentially conflicting copies pushed to the new destination.

Examples of branch filtering

This section is non-normative.

The branch filtering examples illustrate the processing expectations for various scenarios that involve <ditavalref> elements. Processing examples use either before and after sample markup or expanded syntax that shows the equivalent markup without the <ditavalref> elements.

Example: Single <ditavalref> on a branch

This section is non-normative.

In this scenario, a single <ditavalref> element is used to supply filtering conditions for a branch.

Example

This section is non-normative.

Consider the following DITA map and the DITAVAL document that is referenced from the <ditavalref> element:

Example 1. input.ditamap:

<map>
  <topicref href="intro.dita"/>
  <topicref href="install.dita">
    <ditavalref href="novice.ditaval"/>
    <topicref href="do-stuff.dita"/>
    <topicref href="advanced-stuff.dita" audience="admin"/>
    <!-- more topics -->
  </topicref>
  <!-- Several chapters worth of other material -->
</map>
Example 2. Contents of novice.ditaval
<val>
  <prop att="audience" val="novice" action="include"/>
  <prop att="audience" val="admin" action="exclude"/>
</val>

When this content is published, the following processing occurs:

  • The first topic (intro.dita) does not use any of the conditions that are specified in novice.ditaval. It is published normally, potentially using other DITAVAL conditions that are specified externally.
  • The second topic (install.dita) is filtered using any external conditions as well as the conditions that are specified in novice.ditaval.
  • The third topic (do-stuff.dita) is filtered using any external conditions as well as the conditions that are specified in novice.ditaval.
  • The fourth topic (advanced-stuff.dita) is removed from the map entirely, because it is filtered out with the conditions that are specified for the branch.

In this example, no resources are renamed based on the <ditavalref> processing.

Note (non-normative):
In cases where the original resource names map directly to names or anchors in a deliverable, the absence of renaming ensures that external links to those topics are stable regardless of whether a DITAVAL document is used.

Example: Multiple <ditavalref> elements on a branch

This section is non-normative.

In this scenario, multiple <ditavalref> elements are used on a single map branch to create multiple distinct copies of the branch.

Example

This section is non-normative.

Consider the following DITA map that contains a branch with three peer <ditavalref> elements. Because topics in the branch are filtered in three different ways, processors are effectively required to handle three copies of the entire branch. Sub-elements within the <ditavalref> elements are used to control how new resource names are constructed for two copies of the branch; one copy (based on the conditions in win.ditaval) is left with the original file names.

Example 3. input.ditamap
<map>
  <topicref href="intro.dita"/>
  <!-- Begining of installing branch -->
  <topicref href="install.dita">
    <ditavalref href="win.ditaval"/>
    <ditavalref href="mac.ditaval">
      <ditavalmeta>
        <dvrResourceSuffix>-apple</dvrResourceSuffix>
      </ditavalmeta>
    </ditavalref>
    <ditavalref href="linux.ditaval">
      <ditavalmeta>
        <dvrResourceSuffix>-linux</dvrResourceSuffix>
      </ditavalmeta>
    </ditavalref>
    <topicref href="do-stuff.dita">
    <!-- more topics and nested branches -->
      <topicref href="mac-specific-stuff.dita" platform="mac"/>
    </topicref>
    <!-- End of installing branch -->
    <topicref href="cleanup.dita"/>
  </topicref>
</map>
Example 4. Contents of win.ditaval
<val>
  <prop att="platform" val="win" action="include"/>
  <prop att="platform" action="exclude"/>
</val>
Example 5. Contents of mac.ditaval
<val>
  <prop att="platform" val="mac" action="include"/>
  <prop att="platform" action="exclude"/>
</val>
Example 6. Contents of linux.ditaval
<val>
  <prop att="platform" val="linux" action="include"/>
  <prop att="platform" action="exclude"/>
</val>
When a processor evaluates this markup, it results in three copies of the installing branch. The following processing takes place:
  • The first topic (intro.dita) is published normally, potentially using any other DITAVAL conditions that are specified externally.
  • The installing branch appears three times, once for each DITAVAL document. The branches are created as follows:
    • The first branch uses the first DITAVAL document (win.ditaval). Resources use their original names as specified in the map. The mac-specific-stuff.dita topic is removed. The resulting branch, with indenting to show the hierarchy, matches the original without the mac topic:
      install.dita
         do-stuff.dita
           ...more topics and nested branches...
         cleanup.dita
      
    • The second branch uses the second DITAVAL document (mac.ditaval). Resources are renamed based on the <dvrResourceSuffix> element. The mac-specific-stuff.dita topic is included. The resulting branch, with indenting to show the hierarchy, is as follows:
      install-apple.dita
         do-stuff-apple.dita
            mac-specific-stuff-apple.dita
            ...more topics and nested branches...
         cleanup-apple.dita
      
    • The third branch uses the last DITAVAL document (linux.ditaval). Resources are renamed based on the <dvrResourceSuffix> element. The mac-specific-stuff.dita topic is removed. The resulting branch, with indenting to show the hierarchy, is as follows:
      install-linux.dita
         do-stuff-linux.dita
           ...more topics and nested branches...
         cleanup-linux.dita
      

The example used three DITAVAL documents to avoid triple maintenance of the installing branch in a map; the following map is functionally equivalent, but it requires parallel maintenance of each branch.

Example 7. input.ditamap
<map>
  <topicref href="intro.dita"/>
  <!-- Windows installing branch -->
  <topicref href="install.dita">
    <ditavalref href="win.ditaval"/>
    <topicref href="do-stuff.dita">
      <!-- more topics and nested branches -->
    </topicref>
    <topicref href="cleanup.dita"/>
  </topicref>
  <!-- Mac installing branch -->
  <topicref href="install.dita">
    <ditavalref href="mac.ditaval">
      <ditavalmeta><dvrResourceSuffix>-apple</dvrResourceSuffix></ditavalmeta>
    </ditavalref>
    <topicref href="do-stuff.dita">
      <topicref href="mac-specific-stuff.dita" platform="mac"/>
      <!-- more topics and nested branches -->
    </topicref>
    <topicref href="cleanup.dita"/>
  </topicref>
  <!-- Linux installing branch -->
  <topicref href="install.dita">
    <ditavalref href="linux.ditaval">
      <ditavalmeta><dvrResourceSuffix>-linux</dvrResourceSuffix></ditavalmeta>
    </ditavalref>
    <topicref href="do-stuff.dita">
      <!-- more topics and nested branches -->
    </topicref>
    <topicref href="cleanup.dita"/>
  </topicref>
  <!-- Several chapters worth of other material -->
</map>

Example: Single <ditavalref> as a child of <map>

This section is non-normative.

In this scenario, a <ditavalref> element is a direct child of the <map> element, which is equivalent to setting global filtering conditions for the map.

Example

This section is non-normative.

The following map is equivalent to processing all the contents of the map with the conditions in the novice.ditaval document. If additional conditions are provided externally (for example, as a parameter to the publishing process), those conditions take precedence.

<map>
  <title>Sample map</title>
  <ditavalref href="novice.ditaval"/>
  <!-- lots of content -->
</map>

Example: Single <ditavalref> in a reference to a map

This section is non-normative.

In this scenario, a <ditavalref> element is used when referencing a map. This is equivalent to setting filtering conditions for the referenced map.

Example

This section is non-normative.

In the following example, other.ditamap is referenced by a root map. The <ditavalref> element indicates that all of the content in other.ditamap is filtered using the conditions specified in the some.ditaval document.

Example 8. Map fragment
<topicref href="parent.dita">
  <topicref href="other.ditamap" format="ditamap">
    <ditavalref href="some.ditaval"/>
  </topicref>
</topicref>
Example 9. Contents of other.ditamap
<map>
  <topicref href="nestedTopic1.dita">
    <topicref href="nestedTopic2.dita"/>
  </topicref>
  <topicref href="nestedTopic3.dita"/>
</map>
This markup is functionally equivalent to applying the conditions in some.ditaval to the topics that are referenced in the nested map. For the purposes of filtering, it could be rewritten in the following way. The extra <topicgroup> container is used here to ensure filtering is not applied to parent.dita, as it would not be in the original example:
<topicref href="parent.dita">
  <topicgroup>
    <ditavalref href="some.ditaval"/>
    <topicref href="nestedTopic1.dita">
      <topicref href="nestedTopic2.dita"/>
    </topicref>
    <topicref href="nestedTopic3.dita"/>
  </topicgroup>
</topicref>

For the purposes of filtering, this map also could be rewritten as follows.

<topicref href="parent.dita">
  <topicref href="nestedTopic1.dita">
    <ditavalref href="some.ditaval"/>
    <topicref href="nestedTopic2.dita"/>
  </topicref>
  <topicref href="nestedTopic3.dita">
    <ditavalref href="some.ditaval"/>
  </topicref>
</topicref>

Filtering based on the <ditavalref> element applies to the containing element and its children, so in each case, the files nestedTopic1.dita, nestedTopic2.dita, and nestedTopic3.dita are filtered against the conditions specified in some.ditaval. In each version, parent.dita is not a parent for the <ditavalref>, so it is not filtered.

Example: Multiple <ditavalref> elements as children of <map> in a root map

This section is non-normative.

In this scenario, multiple instances of the <ditavalref> element are specified as direct children of the <map> element in a root map. This is equivalent to setting multiple sets of global filtering conditions for the root map.

Example

This section is non-normative.

Note (non-normative):
Unlike most other examples of branch filtering, this example cannot be rewritten using a single valid map with alternate markup that avoids having multiple <ditavalref> elements as children of the same grouping element.

Processing the following root map is equivalent to processing all the contents of the map with the conditions in the mac.ditaval file and again with the linux.ditaval file. If additional conditions are provided externally (for example, as a parameter to the publishing process), those global conditions take precedence.

Example 10. input.ditamap
<map>
  <title>Setting up my product 
on <keyword platform="mac">Mac</keyword><keyword platform="linux">Linux</keyword></title>
  <topicmeta>
    <othermeta platform="mac"   name="ProductID" content="1234M"/>
    <othermeta platform="linux" name="ProductID" content="1234L"/>
  </topicmeta>
  <ditavalref href="mac.ditaval"/>
  <ditavalref href="linux.ditaval"/>
  <!-- lots of content, including relationship tables -->
</map>
Example 11. Contents of mac.ditaval
<val>
  <prop att="platform" val="mac"   action="include"/>
  <prop att="platform" val="linux" action="exclude"/>
</val>
Example 12. Contents of linux.ditaval
<val>
  <prop att="platform" val="mac"   action="exclude"/>
  <prop att="platform" val="linux" action="include"/>
</val>

Because the title and metadata each contain filterable content, processing using the conditions that are referenced by the <ditavalref> element results in two variants of the title and common metadata. While this cannot be expressed using valid DITA markup, it is conceptually similar to something like the following.

<!-- The following wrapperElement is not a real DITA element.
     It is used here purely as an example to illustrate one possible 
     way of picturing the conditions. -->
<wrapperElement>
  <map>
    <title>Setting up my product on <keyword platform="mac">Mac</keyword></title>
    <topicmeta>
      <othermeta platform="mac"   name="ProductID" content="1234M"/>
    </topicmeta>
    <ditavalref href="mac.ditaval"/>
    <!-- lots of content, including relationship tables -->
  </map>
  <map>
    <title>Setting up my product on <keyword platform="linux">Linux</keyword></title>
    <topicmeta>
      <othermeta platform="linux" name="ProductID" content="1234L"/>
    </topicmeta>
    <ditavalref href="linux.ditaval"/>
    <!-- lots of content, including relationship tables -->
  </map>
</wrapperElement>

How this map is rendered is implementation dependent. If this root map is rendered as a PDF, possible renditions might include the following:

  • Two PDFs, with one using the conditions from mac.ditaval and another using the conditions from linux.ditaval
  • One PDF, with a title page that includes each filtered variant of the title and product ID, followed by Mac-specific and Linux-specific renderings of the content as chapters in the PDF
  • One PDF, with the first set of filter conditions used to set book level titles and metadata, followed by content filtered with those conditions, followed by content filtered with conditions from the remaining <ditavalref> element.

Example: Multiple <ditavalref> elements in a reference to a map

This section is non-normative.

In this scenario, multiple instances of the <ditavalref> element are specified in a reference to a map. This is equivalent to referencing that map multiple times, with each reference nesting one of the <ditavalref> elements.

Example

This section is non-normative.

In the following example, other.ditamap is referenced by a root map. The <ditavalref> elements provide conflicting sets of filter conditions.

Example 13. Map fragment
<topicref href="parent.dita">
  <topicref href="other.ditamap" format="ditamap">
    <ditavalref href="audienceA.ditaval"/>
    <ditavalref href="audienceB.ditaval"/>
    <ditavalref href="audienceC.ditaval"/>
  </topicref>
</topicref>

This markup is functionally equivalent to referencing other.ditamap three times, with each reference including a single <ditavalref> elements. The fragment could be rewritten as:

Example 14. Map fragment
<topicref href="parent.dita">
  <topicref href="other.ditamap" format="ditamap">
    <ditavalref href="audienceA.ditaval"/>
  </topicref>
  <topicref href="other.ditamap" format="ditamap">
    <ditavalref href="audienceB.ditaval"/>
  </topicref>
  <topicref href="other.ditamap" format="ditamap">
    <ditavalref href="audienceC.ditaval"/>
  </topicref>
</topicref>

Example: <ditavalref> within a branch that already uses <ditavalref>

This section is non-normative.

In this scenario, a branch is filtered because a <ditavalref> element is present, and another <ditavalref> deeper within that branch supplies additional conditions for a subset of the branch.

Example

This section is non-normative.

In the following map fragment, a set of operating system conditions applies to installation instructions. Within that common branch, a subset of content applies to different audiences.
<topicref href="install.dita">
  <ditavalref href="linux.ditaval"/>
  <ditavalref href="mac.ditaval">
    <ditavalmeta>
      <dvrResourceSuffix>-mac</dvrResourceSuffix>
    </ditavalmeta>
  </ditavalref>
  <ditavalref href="win.ditaval">
    <ditavalmeta>
      <dvrResourceSuffix>-win</dvrResourceSuffix>
    </ditavalmeta>
  </ditavalref>
  <topicref href="perform-install.dita">
    <!-- other topics-->
  </topicref>
  <!-- Begin configuration sub-branch -->
  <topicref href="configure.dita">
    <ditavalref href="novice.ditaval">
      <ditavalmeta>
        <dvrResourceSuffix>-novice</dvrResourceSuffix>
      </ditavalmeta>
    </ditavalref>
    <ditavalref href="advanced.ditaval">
      <ditavalmeta>
        <dvrResourceSuffix>-admin</dvrResourceSuffix>
      </ditavalmeta>
    </ditavalref>
    <!-- Other config topics -->
  </topicref>
  <!-- End configuration sub-branch -->
</topicref>

In this case, the effective map contains three copies of the complete branch. The branches are filtered by operating system. Because topics in the branch are filtered in different ways, processors are effectively required to handle three copies of the entire branch. The map author uses the <dvrResourceSuffix> elements to control naming for each copy. The Linux branch does not specify a <dvrResourceSuffix> element, because it is the default copy of the branch; this allows documents such as install.dita to retain their original names.

Within each operating system instance, the configuration sub-branch is repeated; it is filtered once for novice users and then again for advanced users. As a result, there are actually six instances of the configuration sub-branch. Additional <dvrResourceSuffix> elements are used to control naming for each instance.

  1. The first instance is filtered using the conditions in linux.ditaval and novice.ditaval. For this instance, the resource configure.dita is treated as the resource configure-novice.dita. There is no renaming based on linux.ditaval, and the <ditavalref> the references novice.ditaval adds the suffix -novice.
  2. The second instance is filtered using the conditions in linux.ditaval and advanced.ditaval. For this instance, the resource configure.dita is treated as the resource configure-admin.dita. There is no renaming based on linux.ditaval, and the <ditavalref> that references advanced.ditaval adds the suffix -admin.
  3. The third instance is filtered using the conditions in mac.ditaval and novice.ditaval. For this instance, the resource configure.dita is treated as the resource configure-novice-mac.dita. The <ditavalref> that references novice.ditaval adds the suffix -novice, resulting in configure-novice.dita, and then the <ditavalref> that references mac.ditaval adds the additional suffix -mac.
  4. The fourth instance is filtered using the conditions in mac.ditaval and advanced.ditaval. For this instance, the resource configure.dita is treated as the resource configure-admin-mac.dita. The <ditavalref> that references admin.ditaval adds the suffix -admin, resulting in configure-admin.dita, and then the <ditavalref> that references mac.ditaval adds the additional suffix -mac.
  5. The fifth instance is filtered using the conditions in win.ditaval and novice.ditaval. For this instance, the resource configure.dita is treated as the resource configure-novice-win.dita. The <ditavalref> that references novice.ditaval adds the suffix -novice, resulting in configure-novice.dita, and then the <ditavalref> that references win.ditaval adds the additional suffix -win.
  6. The sixth instance is filtered using the conditions in win.ditaval and advanced.ditaval. For this instance, the resource configure.dita is treated as the resource configure-admin-win.dita. The <ditavalref> that references admin.ditaval adds the suffix -admin, resulting in configure-admin.dita, and then the <ditavalref> that references win.ditaval adds the additional suffix -win.

Example: <ditavalref> error conditions

This section is non-normative.

In this scenario, multiple, non-equivalent copies of the same resource name are created as a result of branch filtering. In addition, the process results in duplicate key names, making it impossible to reliably reference individual result topics.

Example

This section is non-normative.

The following map fragment contains several error conditions that result in name clashes:

<topicref href="a.dita" keys="a">
  <ditavalref href="one.ditaval"/>
  <ditavalref href="two.ditaval"/>
  <topicref href="b.dita" keys="b"/>
</topicref>
<topicref href="a.dita"/>
<topicref href="c.dita" keys="c">
  <ditavalref href="one.ditaval">
    <ditavalmeta>
      <dvrResourceSuffix>-token</dvrResourceSuffix>
    </ditavalmeta>
  </ditavalref>
  <ditavalref href="two.ditaval">
    <ditavalmeta>
      <dvrResourceSuffix>-token</dvrResourceSuffix>
    </ditavalmeta>
  </ditavalref>
</topicref>
In this sample, the effective map that results from evaluating the filter conditions has several clashes. In some cases the same document must be processed with conflicting conditions, using the same URI. In addition, because no key scope is added or modified, keys in the branch are duplicated in such a way that only one version is available for use. When the branches are evaluated to create distinct copies, the filtered branches result in the following equivalent map:
<topicref href="a.dita" keys="a"> <!-- a.dita to be filtered by one.ditaval -->
  <topicref href="b.dita" keys="b"/>  <!-- b.dita to be filtered by one.ditaval -->
</topicref>
<topicref href="a.dita" keys="a"> <!-- a.dita to be filtered by two.ditaval; key "a" ignored -->
  <topicref href="b.dita" keys="b"/>  <!-- b.dita to be filtered by two.ditaval; key "b" ignored -->
</topicref>
<topicref href="a.dita"/>
<topicref href="c-token.dita" keys="c"> 
  <!-- c-token.ditaval to be filtered by one.ditaval -->
</topicref>
<topicref href="c-token.dita" keys="c"> 
  <!-- c-token.ditaval to be filtered by two.ditaval, key "c" ignored -->
</topicref>
The equivalent map highlights several problems with the original source:
  • The key names "a" and "b" are present in a branch that will be duplicated. No key scope is introduced for either version of the branch, meaning that the keys will be duplicated. Because there can only be one effective key definition for "a" or "b", it only is possible to reference one version of the topic using keys.
  • The key name "c" is present on another branch that will be duplicated, resulting in the same problem.
  • The file c.dita is filtered with two sets of conditions, each of which explicitly maps the filtered resource to c-token.dita. This is an error condition that processors need to report.
  • In situations where resource names map directly to output file names, such as an HTML5 rendering that creates files based on the original resource name, the following name conflicts also occur. In this case a processor would need to report an error, use an alternate naming scheme, or both:
    1. a.dita generates a.html using three alternate set of conditions. One version uses one.ditaval, one version uses two.ditaval, and the third version uses no filtering.
    2. b.dita generates b.html using two alternate set of conditions. One version uses one.ditaval, and the other version uses two.ditaval.