This is the mail archive of the
xsl-list@mulberrytech.com
mailing list .
Re: Constraint Searching in XML via XSLT
- To: Joel Beach <j dot beach at ee dot mu dot oz dot au>
- Subject: Re: [xsl] Constraint Searching in XML via XSLT
- From: Jeni Tennison <mail at jenitennison dot com>
- Date: Fri, 20 Jul 2001 15:43:43 +0100
- CC: XSL-List at lists dot mulberrytech dot com
- Organization: Jeni Tennison Consulting Ltd
- References: <5.1.0.14.2.20010719100604.00a698e0@postoffice.ee.mu.oz.au>
- Reply-To: xsl-list at lists dot mulberrytech dot com
Hi Joel,
> I am using XML as a kind of client-side database for the project I'm
> currently doing. I have an SQL database on the server side which
> generates XML data files, and also XML an XML index file. The XML
> index file contains an ID for each data file (in this case a Trial),
> and a whole lot of attributes. I want to transform into an HTML
> Search Result. I want to do this by setting top-level parameters in
> the XSLT stylesheet (these parameters are to be the values for the
> constraints).
It would probably be most efficient, if you can arrange it, to have
the attributes specified in the SQL query that you use to get the data
out of your database rather than retrieving all of it and then using
XSLT to filter it.
However, it might be that you can't do that. To answer your specific
questions:
> 1. If a constraint is not specified, how do I get the XSLT
> stylesheet to match all elements?
I'd suggest that you change from applying templates to all the TrialID
elements and only matching some of them to applying templates to only
those TrialID elements that you're actually interested in. For
example, you can apply templates to only those TrialID elements that
have a TrialName equal to $trialName with:
<xsl:apply-templates
select="vfdindex:TrialID[vfdindex:TrialName = $trialName]" />
Your template giving the details of the relevant TrialID elements can
then match *all* TrialID elements - it just won't be applied to those
TrialID elements that don't match because they're not selected to have
templates applied to them.
To deal with unspecified constraints, you need to choose a default
value for the constraint that can never be a real value for that
constraint. For some, that might be an empty string (''), for others
it might be NaN or 'myUniqueUnspecifiedConstraintValue'. It depends on
what data could be held by the values. Usually an empty string will
do.
If you want to process all TrialID elements only when all the
constraints are unspecified, then you need something like:
<xsl:apply-templates
select="vfdindex:TrialID
[($trialName = '' or vfdindex:TrialName = $trialName) and
($rainfall = NaN or vfdindex:Rainfall = $rainfall) and
($soilType = 'unspecifiedSoilType' or
vfdindex:SoilType = $soilType)
...]" />
If you want to include partial matches, then you need to test whether
all the constraints are unspecified explicitly:
<xsl:choose>
<xsl:when test="$trialName = '' and
$rainfall = NaN and
$soilType = 'unspecifiedSoilType' and
...">
<xsl:apply-templates select="vfdindex:TrialID" />
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates
select="vfdindex:TrialID
[vfdindex:TrialName = $trialName or
vfdindex:Rainfall = $rainfall or
vfdindex:SoilType = $soilType or
...]" />
</xsl:otherwise>
</xsl:choose>
> 2. In the case of rainfall, I want to allow users to specify a
> rainfall *range*. Is it possible to do this in XSLT? I had a look
> and there seem to be < and > operators.
You're right that there are < and > operators. If you have a maximum
and minimum rainfall held in different variables (e.g. $maxRainfall,
$minRainfall) then you can test whether the vfdindex:Rainfall element
has a value between those values (inclusive) with:
vfdindex:Rainfall >= $minRainfall and
vfdindex:Rainfall <= $maxRainfall
You have to use < to escape the < because you're writing XML.
> 3. Should I be using <xsl:choose> and <xsl:if> instead of
> <xsl:template> for this sort of stuff?
Use what you feel comfortable with. You could apply templates to all
the TrialID elements and then do tests within the template to see
whether they match the parameters instead:
<xsl:template match="vfdindex:TrialID">
<xsl:if test="vfdindex:TrainName = $trialName or
vfdindex:Rainfall = $rainfall or
...">
...
</xsl:if>
</xsl:template>
Only applying templates to the TrialID elements that you're interested
in may be slightly more efficient, I think (?), and has the advantage
that if you create a node set of those TrialID elements then you can
apply templates to that set multiple times in different modes to
create summary tables etc. without testing each TrialID element
multiple times.
I hope that helps,
Jeni
---
Jeni Tennison
http://www.jenitennison.com/
XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list