Conditional Attribute Groups


Is anyone making use of conditional attribute groups in their doc sets?

From my reading of:
that it can provide a way to structure conditional attribute values so that <props> specialization is not required. Even if a filtering specialization is needed eventually, it appears that attribute groups could be used to see if the use case is common enough to justify a specialization.

I didn't initially realize that a DITAVAL <prop> @att value can be either
  • a name of specialization of the <props> attribute (audience, product, platform, etc) OR
  • the name of an attribute group
Specializations empower rock-solid validation, content completion, subjectscheme controlled values, and easier editor features to display and apply filters. Attribute groups would rely on writer conventions and would be relatively impossible to control. It's the basic tradeoff of flexibility against "strongly-typed" conditionalization.

Will attribute groups continue to be supported in DITA 2.0?

Chris Papademetrious

Hi John,

We use them quite extensively. We have multiple product families, each with multiple products. This feature allows us to use a single attribute - the @product attribute - to write conditional content such as

<p product="family1(PROD_A)">...</p>
<p product="family1(PROD_B)">...</p>

As a convention, our product family group names are lowercase and the product name values are uppercase.

Then in our DITAVAL, we can select just an individual product out of a family without affecting other product families:

   <!-- hide all family1 products, then include only @product="family1(PROD_A)" -->
   <prop att="family1" action="exclude"/>
   <prop att="family1" val="PROD_A" action="include"/>

(And we *do* have books that involve multiple product groups, which gets interesting and fun to edit and publish!)

It initially took some time to grok that in @att can refer to both attribute names and group names used within that attribute, but it makes sense now. It's like referencing the whole tree of possible values or just a subtree of possible values.

And in the Oxygen editor, when you apply profiling conditions to content, the dialog shows an extra expandable/collapsible hierarchy for the group names, which is pretty cool:


 - Chris


Thanks Chris,

Do you use other group names in the product attribute besides familyN?

I’m assuming that if you wanted to also filter by a product variant, you could also add:

product=“family1(PROD_A) variant(ONPREM CLOUD_NATIVE)”

and create DITAVAL props to filter product variants within a family, for example?

Ive seen writers use otherprops as a catch all, but if attribute groups were used, it would namespace them so orthogonal facets were obvious.

Chris Papademetrious

Hi John,

Currently we just have product families for groups. I suppose you could create a separate group for variants, although you'd want to take care that the AND/OR filtering rules work the way you want them to.

Regarding the idea of prototyping attribute specializations, there's also subject schemes. I have yet to look at them, and I don't know how they relate to/work with/conflict with conditional attribute groups.

 - Chris


The only thing I've done with subjectschemes is to demo a proof of concept to control valid values for conditional attributes. The subjectscheme maps can then be shared so all writers are honoring the same conditional processing logic for common cases, which is particularly relevant when content is reused across independent product repos using Git Submodules or other means. Oxygen uses the subjectscheme maps to control which values are presented in content completion popups and the Attributes view.

Besides DITA's provisions for filtering attributes for conditional content processing, have you also had the desire to filter by any of the topic metadata elements, such as category, featnum, or even othermeta? Has anyone added this capability to their own workflow, either in a pre or post processing phase to DITA-OT?

Metadata elements make their way into HTML output to allow the reader to filter or do faceted search at "browse time". It would seem natural to  allow a writer to have the option to do the same at build time to define specific deliverables.

Metadata elements have their own attributes. For example, <audience> has @type, @job, @experiencelevel, etc., which wouldn't quite fit the conditional attribute model. Without resorting to specialization, perhaps conditional attribute groups could be used to emulate these cases with @audience="job(operator) experiencelevel(advanced)". It would be possible to then use Schematron or the Oxygen SDK to keep the metadata elements and attribute groups in sync to some degree, where a change in one updates the other and any differences could be caught and quickfixes offered.

It could be handy if these currently orthogonal uses of "metadata" could be unified.

Michael McLoughlin

Out of interest John, what's the benefit of using subject scheme maps in Oxygen over customizing the Oxygen cc_config,xml? We use the latter to control element, attribute and attribute value choice.

Radu Coravu

Hi Michael,

My take on this:

One thing better about using subject schemes to impose attribute values is that you automatically receive a validation error in Oxygen if you set the wrong value to an attribute, so the subject scheme controlled set of values is imposed when editing your content.

It's also beneficial I think to have the controlled values defined inside the DITA Project's content, so even if you do not use a special framework in Oxygen you get the same benefits from the controlled values.

Also Subject Scheme map defined values can influence the filtering stage when you publish:



Radu Coravu
Oxygen XML Editor
On 4/27/21 10:53, Michael McLoughlin wrote:

Out of interest John, what's the benefit of using subject scheme maps in Oxygen over customizing the Oxygen cc_config,xml? We use the latter to control element, attribute and attribute value choice.


Michael McLoughlin

Thanks for that Radu. You clearly have more fine-grained control with Subject Scheme maps.