page 95
With the
key
function, we can search on anything, including the contents of an element. See
Section 5.3 for an example of this. For this reason, our call to the
key
function asking for all the
term
elements with an
id
attribute equal to
wildcard-char DMZlong pattern- matching
returns nothing. Any attribute with a datatype of
ID
cant contain spaces, so we get no results.
There are several ways to deal with this problem; well go through our choices next.
5.2.3.2 Solution 1: Replace the IDREFS datatype
If you consider this a problem and refuse to use the
id
function, there are several approaches you can take. The most drastic but probably the simplest to implement is to not
use the
IDREFS
datatype at all. You could change the
seealso
element so that it contains a list of references to other elements:
seealso item refid=wildcard-character
item refid=DMZlong item refid=pattern-matching
seealso
This approach has the advantage that we can use the value of all the
refid
attributes of all
item
elements with the
key
function. That means we can search on anything, not just values of attributes. The disadvantage, of course, is that we had to change the structure of our
XML document to make this approach work. If you have control of the structure of your XML document, thats possible; its entirely likely, of course, that you cant change the XML
document at all. A variation on this approach would be to use a stylesheet to transform the
IDREFS
datatype into the previous structure.
5.2.3.3 Solution 2: Use the XPath contains function
A second approach is to leave the structure of the XML document unchanged, then use the XPath
contains
function to find all
term
elements whose
id
attributes are contained in the value of the
refids
attribute of the
seealso
element. Heres how that would work:
xsl:template match=seealso b
xsl:textSee also: xsl:text b
xsl:variable name=id_list select=refids xsl:for-each select=term
xsl:if test=containsid_list, id a href={id}
xsl:choose xsl:when test=xreftext
xsl:value-of select=xreftext xsl:when
xsl:otherwise xsl:value-of select=.
xsl:otherwise xsl:choose
a xsl:if test=notposition=last
xsl:text, xsl:text xsl:if
xsl:if xsl:for-each
xsl:text. xsl:text xsl:template
page 96
Weve done a couple of things here: First, weve saved the value of the
refids
attribute of the
seealso
element in the variable
id_list
. Thats because we cant access it within the
for- each
element. We can find a given
seealso
element from within a given
term
element, but its too difficult to find that element generically from every
term
element. The simplest way to find the element is to save the value in a variable.
Second, we look at all of the
term
elements in the document. For each one, if our variable containing the
refids
attribute of the
seealso
element contains the value of the current
term
elements
id
attribute, then we process that
term
element. Here are the results our stylesheet generates:
html head
titleGlossary Listing: applet - wildcard charactertitle head
body h1Glossary Listing: applet - wildcard characterh1
p ba name=appletaapplet: b
An application program, written in the Java programming language, that can be
retrieved from a web server and executed by a web browser. A reference to an applet appears in the markup for a web
page, in the same way that a reference to a graphics file appears; a browser retrieves an applet in the same
way that it retrieves a graphics file. For security reasons, an applets access rights are limited
in two ways: the applet cannot access the file system of the client upon which it is executing, and the applets
communication across the network is limited to the server from which it was downloaded.
Contrast with a href=servletservleta. bSee also: ba
href=DMZlongdemilitarized zonea, a href=DMZ DMZa, a href=pattern-matchingpattern-matching
charactera, a href=wildcard-charwildcard charactera.
p ...
There are a couple of problems here. The most mundane is that in our stylesheet, we dont know how many
term
elements have
id
attributes contained in our variable. That means its difficult to insert commas correctly between the matching
term
s. In the output here, we were lucky that the last match was in fact the last term, so the results here are correct. For any
seealso
element whose
refid
attribute doesnt contain the
id
attribute of the last
term
element in the document, this stylesheet wont work. The more serious problem is that one of the matches is, in fact, wrong. If you look closely at
the output, we get a match for the term
DMZ
, even though there isnt an exact match for its
id
in our variable. Thats because the XPath
contains
function says correctly that the value
DMZlong
contains the
id
s
DMZlong
and
DMZ
. So our second attempt at solving this problem doesnt require us to change the structure of the
XML document, but in this case, we have to change some of our
ID
s so that the problem we just mentioned doesnt occur. Thats probably going to be a maintenance nightmare and a
serious drawback to this approach.