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:

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