Displaying Foreign Tags with <xtag>

There may be times when you wish to use an LXP variable value within the contents of an HTML tag. For example, you may have a graphic with a dynamically assigned width. Since LXP only performs variable value substitution within LXP tags, you cannot substitute an LXP variable within an HTML tag as you would with an LXP tag. In other words, the $width variable reference in the following example will not work:

<lxp>
  <!-- WRONG: LXP variable will not be substituted in non-LXP tag -->
  <img src="/images/spacer.gif" width="$width" />
</lxp>

You might think an obvious solution would be to place the LXP <putvar> tag inside of the HTML tag. There is a problem with this approach, however. Specifically, such syntax breaks the integrity of the mark-up of the document. For a mark-up language to be well formed, tags must not be nested within the actual contents of another tag as shown in this example:

<lxp>
  <!-- Not recommended: Tags should not be nested in one another -->
  <img src="/images/spacer.gif" width="<putvar name="width" />">
</lxp>

Note that nesting LXP tags within non-LXP tags can work in some circumstances, though it is not recommended. The LXP well-formedness requirements will probably grow more stringent in the future, and this kind of nesting is an easy way to make your LXP mark-up both lose its readability, as well as its mark-up integrity.

The LXP solution to this problem is the <xtag> element. The <xtag> is used as a wrapper to display any foreign (non-LXP) tag. It has one required attribute, which is xname. This attribute determines what tag will be output in place of <xtag> when the <xtag> is processed by LXP. For example, <xtag xname="a"> will be displayed as <a>.

Optionally, the xappend attribute may be used to append an arbitrary character string to the end of the generated tag. For example, using xappend=" checked" for an HTML checkbox input tag will create an <input type="checkbox" checked> tag.

Any other attributes will be passed through to the wrapped tag, directly. This is the key to the usefulness of the <xtag>, because variable values may be substituted within an <xtag>, and are then directly embedded within the resulting foreign tag. As an example, the correct way to wrap an HTML <img> tag in LXP is shown in Example 13-31.

Example 13-31. Using <xtag> for empty elements

<lxp>
  <xtag xname="img" src="images/spacer.gif" width="$width" />
</lxp>

Here is the displayed output from this document, once processed by LXP, assuming that the width variable has a value of 10:

  
  <img src="images/spacer/gif" width="10" />

Notice the trailing slash used in the <xtag> element within Example 13-31. An <xtag> may be an opening, closing, or empty-element tag, depending on what tag you ultimately wish to display. A vital nuance to the nature of <xtag> is that LXP keeps track of what opening <xtag> elements have been left open, and chooses the appropriate tag name to use when it reaches a closing </xtag>.

If you are wrapping a foreign tag that does not close (e.g., the HTML <img> tag), you must adhere to document strictness and make that <xtag> an empty-element tag with a trailing slash. If you do not, LXP will name the next closing </xtag> with the xname assigned to the last opening <xtag> (e.g., img), which in this case will result in mismatched tag output.

Consider the following piece of mark-up:

<lxp>
  <xtag xname="table" width="$table_width">
    <tr>
      <-- WRONG: The following Empty-element requires trailing slash -->
      <td><xtag xname="img" src="images/spacer.gif" width="$width"></td>
    </tr>
  </xtag>
</lxp>

This code uses three <xtag> elements; one opening and one closing (corresponding to a wrapped <table> element), and one opening <xtag> used to wrap an <img> tag. Since the <img> tag does not have a closing tag in HTML, this <xtag> should instead be an empty-element tag, but it will not be read that way by LXP (notice the lack of a trailing slash). The problem with this mark-up is that since LXP keeps track of open <xtag> elements, when it reaches the first closing</xtag>, it expects to close not the intended<table> tag, but the <img> tag.

Assuming the table_width variable has a value of 100, and the width variable has a value of 10, the incorrect output looks like this:

  
  <table width="100">
    <tr>
      <-- WRONG: Empty-element requires trailing slash -->
      <td><img src="images/spacer.gif" width="10"></td>
    </tr>
  </img>

Example 13-32 shows the correct way to mix opening, empty-element, and closing <xtag> elements.

Example 13-32. Using nested <xtag> elements

<lxp>
  <xtag xname="table" width="$table_width">
    <tr>
      <-- RIGHT: Empty-element has required trailing slash -->
      <td><xtag xname="img" src="images/spacer.gif" width="$width" /></td>
    </tr>
  </xtag>
</lxp>

Since the second <xtag> element in Example 13-32 uses a trailing slash, as is required when you wrap a tag that does not explicitly close, LXP does not anticipate a closing tag for the <img> tag, and the output looks (correctly) like this:

  
  <table width="100">
    <tr>
      <-- RIGHT: Empty-element has required trailing slash -->
      <td><img src="images/spacer.gif" width="10" /></td>
    </tr>
  </table>