Difficulty: ★☆☆ (easy)
Keywords: PI, processing instructions, pseudo-attributes

Problem

You need an own processing instruction (not one from the DocBook XSL stylesheets) to fine-tune your transformation.

Solution

The DocBook XSL stylesheet offers the pi-attribute template for this purpose. It expects a processing instruction node and a “pseudo-attribute” name. For example, the following processing instruction is given:

<?toms-html background-color="blue"?>

Call pi-attribute to extract the content of the pseudo-attribute name:

<xsl:call-template name="pi-attribute">
  <xsl:with-param name="pis" select="processing-instruction('toms-html')"/>
  <xsl:with-param name="attribute" select="'background-color'"/>
</xsl:call-template>

This gives you the result blue.

Discussion

Processing instructions (PIs) are usually needed to fine-tune your output formats, e.g., to add page break information, background color, or other stylistic hints. PIs should not be used to insert data that should normally reside inside a DocBook element! As a general rule of thumb: Use PIs if you want to provide layout specific information for your output format unless there is another method.

The following example uses the PI <?toms-html?> which is included inside a para element to insert background color in HTML:[6]

  1. Invent a target name for your processing instruction. This name should be unique and must not conflict with existing PIs (like <?dbhtml?>, <?dbfo?>, etc.) For example, you could use your abbreviated name and the output format to distinguish it from other processing instructions.

  2. Insert your PI into a para that has a different background color:

    <para><?toms-html background-color="blue"?>
      ...
    </para>
  3. Create a customization layer as shown in Section 2.3, “Writing Customization Layers”.

  4. Customize the para template and add the following code to your customization layer. The customized template calls pi-attribute with the relevant parameters. If no PI was set, apply the original template:

    <xsl:template match="d:para">
      <xsl:variable name="bg">
        <xsl:call-template name="pi-attribute">
          <xsl:with-param name="pis" select="processing-instruction('toms-html')"/>
          <xsl:with-param name="attribute" select="'background-color'"/>
        </xsl:call-template>
      </xsl:variable>
      <xsl:choose>
        <xsl:when test="$bg != ''">
          <div style="background-color:{$bg}">
            <xsl:apply-imports/>
          </div>
        </xsl:when>
        <xsl:otherwise>
          <xsl:apply-imports/>
        </xsl:otherwise>
      </xsl:choose>
    </xsl:template>

    1

    Fill the variable bg with the result of pi-attribute. Note, the select only matches for PIs inside a para.

    2

    Decide what to do when background color is found.

    3

    Wrap our paragraph around div with the corresponding background-color inside a style attribute.

    4

    Delegate the default handling to the original para template.

  5. Build your document with your customization layer.

The previous example recognizes a PI inside a para only. If you also want to recognize PIs before, use the following XPath expression in the select attribute of pi-attribute:

( processing-instruction('toms-html') |
  preceding-sibling::processing-instruction('toms-html')[1]
)[last()]

If two PIs are available (one inside, another outside), the inside one takes precedence.

See Also


[6] Usually, such a requirement would be satisfied by CSS and not PIs. However, this example just shows the principle so it is a perfect use case.


Project@GitHubIssue#7