2. Examples

Example 4.1. Using sequence and choice

<command name="addListItem">
  <macro undoable="true">
    <choice>
      <sequence>
        <command name="selectNode" 
                 parameter="ancestor[implicitElement] 
                            {http://www.w3.org/1999/xhtml}ul 
                            {http://www.w3.org/1999/xhtml}ol" />
        <command name="selectNode" parameter="child" />
        <command name="insertNode" parameter="sameElementAfter" />
      </sequence>

      <sequence>
        <choice>
          <sequence>
            <command name="selectNode" 
                     parameter="ancestorOrSelf[implicitElement] 
                                {http://www.w3.org/1999/xhtml}dt" />
            <!-- Assumes that a dt is followed by a dd. -->
            <command name="selectNode" parameter="nextSibling" />
          </sequence>
          <command name="selectNode" 
                   parameter="ancestorOrSelf[implicitElement] 
                              {http://www.w3.org/1999/xhtml}dd" />
        </choice>
        <command name="insert"
                 parameter="after {http://www.w3.org/1999/xhtml}dt" />
        <command name="insert"
                 parameter="after {http://www.w3.org/1999/xhtml}dd" />
        <command name="selectNode" parameter="previousSibling" />
      </sequence>
    </choice>
  </macro>
</command>

In the above example , the macro command addListItem, which is used to add a li to a ul or ol or to add a dt/dd pair to a dl, can be described as follows:

  • Select ancestor ul or ol and then

    • Select previously select child which is always a li when the document is valid.

      (The selectNode command selects all the ancestors one after the other until it reaches the searched ancestor. This is equivalent to interactively typing Ctrl+Up until the desired ancestor is selected.)

    • AND insert element of same type (a new li) after selected element (a li).

  • OR select

    • next sibling of ancestor dt (assumes that a dt is always followed by a dd);

    • OR ancestor dd.

    Then

    • Insert a dt after the selected element (a dd).

    • AND insert a dd after the selected element (the newly inserted dt).

    • AND select previous sibling (the newly inserted dt) of selected element (the newly inserted dd).


Example 4.2. Macro-variables

<command name="convertToLink">
  <macro undoable="true" repeatable="true" label="Convert to &lt;a&gt;">
    <sequence>
      <command name="convert" parameter="{http://www.w3.org/1999/xhtml}a" />
      <command name="putAttribute" parameter="%0 %1" />
    </sequence>
  </macro>
</command>

<binding>
  <keyPressed code="F3" />
  <command name="convertToLink" parameter="href ???" />
</binding>

<binding>
  <keyPressed code="F3" modifiers="shift" />
  <command name="convertToLink" parameter="name XXX" />
</binding>

In the above example, macro-command convertToLink must be passed two arguments which specify which type of XHTML a element is to be created: is it target or is it a link? These arguments are referenced in the parameter of the putAttribute command using variables %0 and %1.


Example 4.3. The "%_" macro-variable

<command name="insertCommandOutput">
  <macro>
    <sequence>
      <command name="run" />
      <command name="insertString" parameter="%_" />
    </sequence>
  </macro>
</command>

In the above example, the output of the external program executed by the run command is referenced in the parameter of the insertString command using the %_ variable. (The run command having no parameter will prompt the user to specify which external program is to be executed.)


Example 4.4. Using the fail construct

<command name="preview">
  <macro>
    <sequence>
      <pass>
        <match context="/*" pattern="html:html" 
               xmlns:html="http://www.w3.org/1999/xhtml" />
        <fail><command name="XXE.save" /></fail>
      </pass>
      <command name="start" parameter="helper(defaultViewer) '%D'" />
    </sequence>
  </macro>
</command>

Start the web browser to preview the current document if it has an html root element and if it does not need to be saved.


Example 4.5. Using the XPath-based constructs match and set

<command name="moveListItemUp">
  <macro undoable="true" label="Move List Item Up">
    <sequence>
      <command name="selectNode" 
        parameter="ancestorOrSelf[implicitElement] listitem callout step" />
      <match context="$selected" pattern="*[position() &gt; 1]" />
      <set variable="anchor" context="$selected" 
           expression="./preceding-sibling::*[1]" />
      <command name="cut" />
      <set variable="selected" expression="$anchor" />
      <command name="paste" parameter="before" />
    </sequence>
  </macro>
</command>

Move a list item up in the list. That is, the preceding sibling of the explicitly or implicitly selected list item becomes its following sibling.


Example 4.6. A contextual drop

<binding>
  <appEvent name="drop" />
  <command name="dropURL" parameter="%{value}" />
</binding>

<command name="dropURL">
  <macro>
    <choice>
      <sequence>
        <match context="$clickedElement" pattern="html:a[@href]" 
               xmlns:html="http://www.w3.org/1999/xhtml" />
        <set variable="selected" expression="$clickedElement" />
        <get expression="relativize-uri('%0')" />
        <command name="putAttribute" parameter="href '%_'" />
        <command name="status" parameter="Changed href."/>
      </sequence>

      <command name="XXE.open" parameter="%0" />
    </choice>
  </macro>
</command>

When a string is dropped on an XHTML <a href="..."> element, this string is assigned to the href attribute (after considering this string as an URL and trying to make it relative to the base URL of the a element). When a string is dropped on any other element, XXE default action is used instead: consider the string as the URL or filename of a document to be opened.

The above macro uses the following XPath extension function: relativize-uri.


Example 4.7. Insert nodes copied from another document

<binding>
  <keyPressed code="F7" />
  <command name="insertFromOtherDoc" 
           parameter="into" />
</binding>

<property name="templateFile"
          url="true">VATrates.html</property>

<command name="insertFromOtherDoc">
  <macro>
    <sequence>
      <command name="prompt"
        parameter="Question 
                   'ID of the element to be inserted at¬
caret position (e.g. germany_vat):'" />
      <set variable="elementId" expression="%_"
           plainString="true" />
      <get expression="serialize(document(system-property(¬
'templateFile'))//*[@id=$elementId])"/>
      <command name="paste" parameter="%0 %_" />
    </sequence>
  </macro>
</command>

The nodes are copied from file VATrates.html. Notice how a property configuration element having attribute url=true is used to make sure that the URL of the source document VATrates.html is resolved against the URL of the configuration file containing the macro.

The above macro uses the following XPath extension function: serialize.


Example 4.8. Convert a DocBook 4 para to a formalpara

<command name="paraToFormalpara">
  <macro>
    <sequence>
      <command name="selectNode" 
               parameter="ancestorOrSelf[implicitElement] para" />1
      <get expression="serialize($selectedElement)"/>2
      <transform source="%_">3
        <xsl:stylesheet version="1.0" xmlns=""
          xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
          4
          <xsl:template match="/para">
            <formalpara>
              <xsl:for-each select="@*">
                <xsl:copy/>
              </xsl:for-each>

              <title></title>
              <para>
                <xsl:apply-templates select="node()"/>
              </para>
            </formalpara>
          </xsl:template>

          <xsl:template match="@*|node()">
            <xsl:copy>
              <xsl:apply-templates select="@*|node()"/>
            </xsl:copy>
          </xsl:template>

        </xsl:stylesheet>
      </transform>
      <command name="paste" parameter="to %_"/>5
    </sequence>
  </macro>
</command>

1

Ensure that explicitly or implicitly selected element is a para or has a para ancestor. Select this para element.

2

Serialize this para element and return it in string form in the %_ variable.

3

Transform the para element to a formalpara element and return the result of the transformation in string form in the %_ variable.

4

Notice that there is no need to specify something like:

<xsl:output method="xml" encoding="UTF-8" />

as the xsl:output element has a sensible implicit specification.

5

Replace the selected para by pasting the formalpara element returned by transform.

Note that the above macro may be implemented less efficiently by replacing the transform child element of macro by the invocation of a process command. See Section 2.1, “Convert explicitly or implicitly selected para to a formalpara.