Skip to main content
ShakewellContact

Explainer

DITA Conditional Processing and DITAVAL

One source, many deliverables: mark content with profiling attributes, then let a DITAVAL profile decide what each build includes, excludes, or flags. How it works, and where it goes wrong.

The Short Answer

Mark It Once, Decide at Build Time

Conditional processing, which the DITA specification also calls profiling, lets one set of topics serve several audiences, products, platforms, or outputs. You classify elements with metadata attributes. At publish time you supply a conditional processing profile, a DITAVAL file, that says what to do with each value: include it, exclude it, flag it, or pass it through.

It is one of the four mechanisms behind DITA reuse. The other three, maps, keys, and content references, are covered in DITA maps, keys, and conref. This piece goes deeper on the fourth.

The Attributes

What You Can Profile On

DITA 1.3 names six attributes for filtering, available on most elements. The same six, plus @rev, are used for flagging.

@product
The product the content is about.
@platform
The platform on which the product is deployed.
@audience
The intended reader.
@deliveryTarget
The intended output, such as html, pdf, or epub. It replaces the deprecated @print.
@otherprops
Anything else that needs no semantic name of its own.
@props
The generic base that can be specialized into new, named conditions.

Each attribute holds one or more space-delimited values, so product="model-2000 model-3000" means the content applies to both. Values can also be grouped, such as database(dbA dbB), so that independent subcategories inside one attribute are evaluated separately. An empty attribute counts as no attribute.

Worked Example

A Small DITAVAL, Step by Step

Illustrative DITA 1.3 markup. A list in a topic, with conditions on its items:

<ul>
  <li product="model-2000">Open the front cover.</li>
  <li product="model-2000 model-3000">Check the filter.</li>
  <li audience="administrator">Reset the counter.</li>
  <li>Close the cover.</li>
</ul>

The profile for one particular build:

<val>
  <prop att="product" val="model-2000" action="exclude"/>
  <prop att="audience" val="administrator" action="flag">
    <startflag><alt-text>ADMIN</alt-text></startflag>
  </prop>
  <prop att="platform" val="linux" action="passthrough"/>
</val>

The first item is excluded, because it applies only to the model the profile removes. The second stays: it also applies to model-3000, which was not excluded, and an attribute excludes an element only when every one of its values excludes. The third is included and flagged ADMIN. The fourth carries no conditions and is always included.

The passthrough rule keeps any platform="linux" value in the output stream so a runtime engine can filter later, such as a help portal that shows content by user setting. Other values are removed from the output even though their content stays.

Actions

Include, Exclude, Flag, Passthrough

include
The content is in the output. This is the default for any value the profile does not mention.
exclude
The content is removed, provided every value in that attribute is excluded. If any one attribute excludes the element, it is excluded.
flag
The content is included and marked with a color, style, image, or text. A flag never hides anything, and if the same element is also filtered, the filter wins.
passthrough
The content is included and the attribute value is kept in the output for a runtime engine.

A prop with no attribute sets a default for every value, and a prop with an attribute but no value sets the default for that one attribute. A profile that opens by setting the default to exclude turns the model around: only what you list is published.

Controlled Values

Keep the Vocabulary Closed

Attribute values are free text. A subject scheme map can enumerate the allowed values and bind them to an attribute, so a validating processor warns about anything else:

<subjectScheme>
  <subjectdef keys="os" navtitle="Operating system">
    <subjectdef keys="linux" navtitle="Linux"/>
    <subjectdef keys="windows" navtitle="Windows"/>
  </subjectdef>
  <enumerationdef>
    <attributedef name="platform"/>
    <subjectdef keyref="os"/>
  </enumerationdef>
</subjectScheme>

A scheme can also nest values. If Red Hat Linux sits under Linux and the profile excludes Linux, content marked for Red Hat is excluded too. That is useful, and it is also a reason to design the hierarchy before anyone writes a condition.

Maps

Filtering a Branch With ditavalref

A single DITAVAL applied to a whole build is too blunt when only part of a publication varies. A ditavalref element in a map applies a profile to one branch:

<topicref href="install.dita">
  <ditavalref href="linux.ditaval"/>
  <ditavalref href="windows.ditaval"/>
</topicref>

Two peer references imply two copies of the branch, one filtered by each profile, while the rest of the map is untouched. Exclusions win at every level: a global exclude overrides a branch include, and a branch exclude overrides an include set on a smaller part of the branch.

In the DITA Open Toolkit, a profile for the whole build is passed with the args.filter parameter. Several files are allowed, separated by the system path separator, and earlier files take precedence over later ones. Our DITA Open Toolkit guide covers the engine itself.

Reuse vs Variation

How It Differs From Conref and Keyref

DimensionConref and keyrefConditional processing
Question it answersWhere does this text come from?Should this text appear in this deliverable?
MechanismConref pulls an element by address; keyref and conkeyref go through a key the map defines.Profiling attributes on elements, evaluated against a DITAVAL profile.
What changes between outputsWhich source an element resolves to.Whether an element is present at all, or flagged.
Typical useOne approved warning, one product name, one shared procedure.A step that applies to one model, or a paragraph for one audience.

Reuse says what the text is; conditions say whether it appears. A mature library uses both, and the common failure is using one to do the other's job: conditions to hold alternate wordings of text that should be a shared reference, or references to hold text that is only sometimes true. The broader pattern is in single-source publishing.

Failure Modes

Where It Goes Wrong

Condition explosion
Every new product, audience, and platform adds attributes, and every attribute multiplies the ways content can combine. Ten independent yes/no conditions allow 1,024 combinations. When no writer can say what a given reader will see, the model needs fewer, better-named conditions, not more.
Untestable combinations
A condition that no profile ever selects is never built, never reviewed, and quietly rots. Decide the deliverables first, list the profile that produces each one, and build and review every one of them before release.
Undefined values leak in
By default, a value the profile does not mention evaluates to include. A typo such as modle-2000 is not an error; the content simply ships to everyone. Setting a default of exclude, or binding the values to a subject scheme, turns the silent failure into a visible one.
Flags mistaken for filters
Flagging marks content that is still in the output. It does not hide anything. If an element is both flagged and filtered, the filter wins and the content is removed, so a flag cannot be used as a soft exclusion.
Conditions used as a substitute for structure
When half of a topic is excluded in every build, it is two topics. Split it, or move the difference into a key, and keep conditions for the cases where text really is shared.

The specification asks processors to report attribute values found in content that have no action in the profile. Read that report on every build; it is the cheapest test the system gives you.

The S1000D Counterpart

DITA Conditions and S1000D Applicability

The same business need, one library serving many configurations, is met in S1000D by applicability. The mechanism is more formal. Our guide to S1000D applicability explains the ACT, CCT, and PCT; the comparison below puts the two side by side.

DimensionDITA conditionsS1000D applicability
Where the vocabulary livesAttribute values on elements. Free text unless a subject scheme map enumerates them.The ACT defines the testable product attributes, the CCT the conditions.
What describes the real productA DITAVAL file chosen for the build.The PCT lists the actual product instances and their values.
Controlled vocabularyOptional: a validating processor can warn on values outside a subject scheme.Content refers to attributes and conditions defined in the ACT and CCT.
Typical resultA deliverable per audience, product, or output.A filtered view for a specific product configuration.

If your content must be tied to real product configurations and checked against them, that is a reason to weigh S1000D; see S1000D vs DITA. If the variation is audiences, products, and outputs, DITA conditions are usually enough.

FAQ

Questions We Hear

What is DITA conditional processing?

Marking elements with profiling attributes such as @product, @audience, and @platform, then using a DITAVAL profile at publish time to include, exclude, flag, or pass through the content that carries each value. The specification also calls it profiling.

What is a DITAVAL file?

A conditional processing profile, conventionally saved with a .ditaval extension. Its val root holds prop elements, each naming an attribute and value and an action: include, exclude, passthrough, or flag. A prop with no attribute sets the default for everything else.

What is the difference between filtering and flagging?

Filtering decides whether content is in the output. Flagging adds text, an image, or styling to content that is in the output. When the same element is flagged by one condition and excluded by another, it is excluded.

What does passthrough do?

It keeps the content and preserves the attribute value in the output so a runtime engine can filter later, for example on an individual user's settings. Values not passed through are removed from the output even though the content stays.

How is conditional processing different from conref?

Conref and keyref reuse content by pulling it from a source. Conditional processing varies content by deciding whether it appears. Most libraries use both: shared text through references, and variants through conditions.

Is S1000D applicability the same thing?

It solves the same problem for a different world. Applicability is a formal model, with the ACT, CCT, and PCT, that ties content to real product configurations. DITA conditions are lighter attribute filters that you can bind to controlled values if you choose.

Get In Touch

Get the Conditions Right Before You Scale

Send us a sample of your topics and the variants you publish. We will tell you how many conditions the content really needs.