Using CSS instead of XPath in Xopus config to set placeholder text in Xopus

We have URLs that are generated from the main topic’s title element and we wanted the authors to be aware of this when they created a page in Xopus. I thought it would be a simple update to the Xopus config.xml file but it turned out not to be. In the end, we added content using CSS instead of using the Xopus config like this:

/* This adds text to Xopus specifically on the first page title*/
#xopus-xsl-root div h1.topic-title:first-of-type .xopus-placeholder:after {
  content: ' (used for generating page URL)';
}

I believe this could do with a little more refinement but it’s worked in all the cases we’ve tested so we are happy.

If you are interested in what didn’t work, keep reading.

One of the limitations of the Xopus placeholder configuration option is that it is not really XPath so it only matches on the element name, attribute name or a class name.  This is documented on the Xopus Use of XPath in configuration FAQ page.

So we first tried:

<x:node match="class('topic/title')" preferElementsOnlyParent="true">
  <x:name xml:lang="en">Title (used to generate URL)</x:name>
  <x:placeholder xml:lang="en">{name}</x:placeholder>
</x:node>

But this added the message ‘ (used to generate URL)’ to the titles on figures, sections and other elements. My next thought was to do add the longer placeholder only to actual descendants of the topic element (and go back and add concept, etc. later) like this:

<x:node match="topic/title" preferElementsOnlyParent="true">
  <x:name xml:lang="en">Title (used to generate URL)</x:name>
  <x:placeholder xml:lang="en">{name}</x:placeholder>
</x:node>
<x:node match="class('topic/title')" preferElementsOnlyParent="true">
  <x:name xml:lang="en">Title</x:name>
  <x:placeholder xml:lang="en">{name}</x:placeholder>
</x:node>

This resulted in not showing the additional text message anywhere because the Xopus config doesn’t use full XPath, as I mentioned earlier so a match of topic/title matches all titles and since class(‘topic/title’) also matches the element and it comes later in the file, that is the version that was used.

Looking for XML elements in Javascript with e4x

If you are manipulating XML in Javascript then E4X is one of the options available to you. The problem is that the documentation is a little thin and the examples only show you how to find things that definitely exist. So here’s some help in trying to see if elements exist or not.

In this example, I’m processing DITA and trying to find the “title” of the document. This can be in a variety of locations in DITA and can be a <title> in a topic, concept, etc. or a <mainbooktitle> element in a bookmap. So how do you see if you have a mainbooktitle in e4x?

var concept = new XML("...my dita concept xml...");
var mainbooktitle = concept..mainbooktitle;
if (mainbooktitle.length() > 0) {
    // we have a mainbooktitle
}

The concept..mainbooktitle construct finds all children elements in the document named mainbooktitle and returns them in an XMLList. Crucially the documentation does not tell you that an XMLList is always returned and can either be:

  1. A list of length zero meaning no elements named mainbooktitle were found
  2. A list of length one meaning only one element was found. When this happens, you can refer to the item as if it were not in a list. For example, to get the id attribute you could just say mainbooktitle.@id instead of mainbooktitle[0].@id.
  3. A list of length greater than one. You should then use a for each loop or access items by index like this mainbooktitle[1].@id

I hope this saves somebody some time because I had to figure it out by trial and error!