## Using GXML: Commands

by Josh Carter < josh@multipart-mixed.com >
May 10, 2001

## Commands Overview

Commands are special XML entities that affect your output depending on contains in the data. They are most often used in templates to add, remove, or repeat parts of the template depending on what's in the data file. Here's a quick overview of the commands available:

- ifexists: If a given attribute exists, or combination of attributes, then the stuff contained in the ifexists block will be included in the output.
- ifequals: If a given attribute's value equals the value specified in ifequals, the block will be included in the output.
- foreach: For each peer instance of an attribute, the block contained by foreach will be run, and variables asking for the attribute will get the current iteration's value.

Let's go through each command and demonstrate some ways to use it.

## ifexists

ifexists is the most straightforward: "if a given attribute exists, regardless of its value, include my stuff in the output." Syntax is:

        <gxml:ifexists expr="attribute">

        (stuff contained will only go into your output if the
        attribute exists.)

        </gxml:ifexists>

Here's an example:

        # In your source XML:

        <quote author="Robert T. Mann">
        If I were a dog, would gnawing on shoes hold
        the same appeal it holds for me now?
        </quote>

        # In your quote.xml template:

        <quote>
        %%%_BODY_%%%
        <gxml:ifexists expr="author">(<i>by %%%author%%%</i>)</gxml:ifexists>
        </quote>

Thus, if the quote has an author, it will get (by author) appended to it.

## A Detour to Boolean Expressions

Don't be terrified if you're not a programmer. "Boolean expressions" is just a complicated way of saying that you can combine attributes in your ifexists command, as such:

        <gxml:ifexists expr="author AND page"> . . . <gxml:ifexists>
        <gxml:ifexists expr="author OR book"> . . . <gxml:ifexists>
        <gxml:ifexists expr="book AND NOT page"> . . . <gxml:ifexists>

You can use AND, OR, and NOT freely in your expressions.

## ifequals

This is the same principle as ifexists, but the given attribute must exist and equal a given value. Syntax follows:

        <gxml:ifequals expr="attribute" equalto="value">

        (stuff contained will only go into your output if
        attribute equals the value.)

        </gxml:ifequals>

For an example, let's redo the dynamic template switching we saw in the "Templates" chapter, section "Variables Within Template Names," this time using ifequals:

        # document source file:

        <document
            name   = "Semi-annual Worm Preservation Report"
            author = "Bob the Man"

            photo-align  = "right"
            photo-source = "worms.jpg"
        >

        (document body text here)

        </document>

        # document.xml template file:

        <document
            name-default   = "Untitled Document"
            author-default = "Unknown Author"

            photo-align-default  = "none"
        >

        <gxml:ifequals expr="photo-align" equalto="right">
        (formatting for right-aligned photo goes here)
        </gxml:ifequals>
        <gxml:ifequals expr="photo-align" equalto="center">
        (formatting for center-aligned photo goes here)
        </gxml:ifequals>
        <gxml:ifequals expr="photo-align" equalto="none">
        (formatting for no photo goes here)
        </gxml:ifequals>

        %%%_BODY_%%%

        </document>

It's arguable that we didn't actually improve things with this change; it was simpler the way it was done before. But I'm sure there are some good uses for ifequals regardless.

## foreach

foreach is the most complicated command, and potentially the most useful. It lets you iterate over multiple values of an attribute. Here's the syntax:

        <gxml:foreach expr="attribute">

        (this block will get run once for each value of attribute.
        Variables in here calling %%%attribute%%% will get the proper
        value in each iteration.)

        </gxml:foreach>

Note that "multiple values" of an attribute implies the attribute must be specified as its own entity -- not one defined in a start tag -- since that's the only way you can have attributes that are peers with multiple values. It's easiest to see in an example:

        <number>1</number>
        <number>2</number>
        <number>3</number>

        <gxml:foreach expr="number">
        I see number %%%number%%%
        </gxml:foreach>

This will print the "I see" block three times, with %%%number%%% being 1, 2, and 3. Notice that all the numbers are peers of each other. If there are numbers somewhere else in the source file, e.g. in a higher-level entity, they won't be noticed. The "expr" will look for the closest match to itself.

Now let's do a more complicated example:

        <person>
            <name>Bob</name>
            <age>42</age>
        </person>

        <person>
            <name>Ned</name>
            <age>24</age>
        </person>

        <gxml:foreach expr="person">
        I see a person named %%%person:name%%%, age %%%person:age%%%
        </gxml:foreach>

This time we use the "drill down" syntax for accessing member attributes of the person entities. We'll get "Bob, 42" the first time the foreach block runs, and "Ned, 24" the second.

On to Other Features!

Back to the GXML Guide

Back to the gxml2html Guide

Copyright (c) 2001-2002 Josh Carter