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] ul ol" />
              <command name="selectNode" parameter="child" />
              <command name="insertNode" parameter="sameElementAfter" />
            </sequence>

            <sequence>
              <choice>
                <sequence>
                  <command name="selectNode"
                           parameter="ancestorOrSelf[implicitElement] dt" />
                  <!-- Assumes that a dt is followed by a dd. -->
                  <command name="selectNode" parameter="nextSibling" />
                </sequence>
                <command name="selectNode"
                         parameter="ancestorOrSelf[implicitElement] dd" />
              </choice>
              <command name="insert" parameter="after dt" />
              <command name="insert" parameter="after dd" />
              <command name="selectNode" parameter="previousSibling" />
            </sequence>
          </choice>
        </macro>
      </command>

In example 1, 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="a" />
            <command name="putAttribute" parameter="%0 %1" />
          </sequence>
        </macro>
      </command>

      <binding>
        <keyPressed code="ESCAPE" />
        <charTyped char="t" />
        <command name="convertToLink" parameter="name XXX" />
      </binding>

      <binding>
        <keyPressed code="ESCAPE" />
        <charTyped char="l" />
        <command name="convertToLink" parameter="href ???" />
      </binding>

In example 2, 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 example 3, 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="publish">
        <macro>
          <sequence>
            <pass>
              <match context="/*[1]" pattern="html" />
              <fail><command name="XXE.save" /></fail>
            </pass>
            <command name="doPublish" />
          </sequence>
        </macro>
      </command>

Execute command `doPublish` if current document has an `html` root element and if this document does not need to be saved.

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

      <command name="moveListItemUp">
        <macro undoable="true">
          <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="xhtml.fileDrop" parameter="%{value}" />
      </binding>

      <command name="xhtml.fileDrop">
        <macro>
          <choice>
            <sequence>
              <match context="$clickedElement" pattern="a[@href]" />
              <set variable="selected" expression="$clickedElement" />
              <get expression="relativize-uri('%0')" />
              <command name="putAttribute" parameter="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. Paste nodes copied from another document

    <binding>
      <keyPressed code="F5" />
      <command name="pasteElementFromOtherDoc"
               parameter="after[implicitElement]" />
    </binding>

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

    <command name="pasteElementFromOtherDoc">
      <macro trace="true">
        <sequence>
          <command name="prompt"
            parameter="Question 'ID of Element to be Pasted:'" />
          <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.

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