2. Examples
Prev | Chapter 4. Macro commands | Next

## 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 5 para` to a `formalpara`

    <command name="paraToFormalpara">
      <macro>
        <sequence>
          <command name="selectNode"
                   parameter="ancestorOrSelf[implicitElement]
                              {http://docbook.org/ns/docbook}para" />

          <get expression="serialize($selectedElement)"/>

          <transform source="%_">
            <xsl:stylesheet version="1.0"
              xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
              xmlns:db="http://docbook.org/ns/docbook">

              <xsl:template match="/db:para">
                <db:formalpara>
                  <xsl:for-each select="@*">
                    <xsl:copy/>
                  </xsl:for-each>

                  <db:title></db:title>
                  <db:para>
                    <xsl:apply-templates select="node()"/>
                  </db:para>
                </db: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 %_"/>
        </sequence>
      </macro>
    </command>

| Ensure that explicitly or implicitly selected element is a `para` or has a `para` ancestor. Select this `para` element.
| Serialize this `para` element and return it in string form in the `%_` variable.
| Transform the `para` element to a `formalpara` element and return the result of the transformation in string form in the `%_` variable.

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.

| 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``”.

Prev | Up | Next
1.3. XPath variables | Home | Chapter 5. Process commands