Eric,
What appears below is *not* a beginner's solution, but it's an interesting
approach to your problem. While less evidently straightforward than Joerg's
solution, it has the virtue of a more complete modeling of the problem,
making it more flexible and extensible.
You start with a lookup table in your stylesheet:
<my:privileges xmlns:my="mynamespace.com"> <!-- put the table in a local
namespace -->
<rights group="C">
<rights group="B">
<rights group="A"/>
</rights>
</rights>
</my:privileges>At 12:23 PM 3/29/2002, you wrote:
Notice that the design of these nodes reflects the relations of the groups:
that C can see B's and A's stuff, that B can see A's stuff but not C's, and
that A can only see A's stuff.
Next, you create a utility variable just so you can pick any of these nodes
out easily:
<xsl:variable name="rightsgroups"
select="document('')/*/my:privileges//rights"/>
Okay, that's "advanced": it queries the stylesheet itself with the
document('') function, then traverses down via an XPath to collect all the
rights elements inside your my:privileges node. (Actually you could do
without this variable, rolling it into the next one, but breaking it out
makes it a bit easier to understand.)
Next, you want to locate the *subset* of these nodes in which you are
actually interested. You do this with a parameter, which you can pass into
the stylesheet at run time:
<xsl:param name="thisgroup" select="'A'"/>
(This declaration sets the default to 'A' but it could be the empty string
'' if you wanted to default to no permissions, or 'C' for the highest,
whatever.)
And then,
<xsl:variable name="theseprivileges"
select="$rightsgroups[@group=$thisgroup]//rights/@group"/>
This fancy expression means "all the 'group' attribute nodes [@group] on
any rights nodes that are descendants or self of the node from
$rightsgroups whose @group attribute equals $thisgroup".
The long way of writing this expression would look like:
$rightsgroups[@group=$thisgroup]/descendant-or-self::rights/@group
This way, if your parameter is 'C' you'll get the @group attribute on the C
rights node *along with the @group attributes* on its descendants, B and A;
but if $thisgroup is 'A', you'll only get the group='A' attribute node
(since its 'rights' element has no descendants).
Now, you proceed as Joerg did, except you can use the equality rule for
nodesets and strings to collect nodes from your source file that are
permitted to each group:
<xsl:apply-templates select="article[@audience = $theseprivileges]"/>
Remember that $theseprivileges is a *collection* of attribute nodes: in
your case, if $thisgroup is A, it's a lone @group attribute with value 'A';
but if $thisgroup is C, it's a collection of @group attributes, with values
'A', 'B', 'C'.
Since a string is equal to a nodeset if its value is the value of *any* of
the nodes in the set, you can see you'll get your A, B, and C articles when
your group is C, but only your A articles when your group is A.
While it's obscure (and if you use this code, *document* it for the poor
XSLT beginner who takes over your job when you move up), you can see how
powerful and extensible this approach is. All you need to do is extend your
lookup table to accommodate for more groups and their relations:
<my:privileges>
<rights group="admin">
<rights group="superusers">
<rights group="daytimers">
<rights group="guests"/>
<rights group="gamers"/>
</rights>
<rights group="nighttimers">
<rights="gamers"/>
</rights>
</rights>
</rights>
</my:privileges>
And it works with any strings as group labels, not just one-character
strings. Here, the admin group gets all articles, the daytimers get their
own stuff plus guests' and gamers' articles, but gamers get only gamers'
stuff. Nightimers get their stuff plus gamers'; the appearance of one group
in several places is not a problem here.
I know that's more than you asked for, but your problem was interesting
enough that I thought it was worth sketching out. While not, as you
requested, a beginner's solution, it does demonstrate some things that
beginners (or advanced beginners) might like to know about:
1. using a local (or remote) lookup table for very flexible configuration
(with the document() function for access)
2. XPath expressions (in your variable declarations etc.) to select *and
filter* nodes
3. testing a string against a node set -- true when *any* node contains the
string (a very useful feature once you're aware of it)
4. using tree structures to represent more complex relations than simple
linear relations (such as the relations in a permissions hierarchy)
I hope that's fun, anyway--
Cheers,
Wendell
> I'm trying produce three sets of output from one set of data, each of
> which are subsets of the preceding. That is, I have:
> <article audience="A">stuff here</article>
> <article audience="B">stuff here</article>
> <article audience="C">stuff here</article>
> <article audience="A">stuff here</article>
> <article audience="A">stuff here</article>
>
> For audience A, I want to include only the A articles; for audience B, I
> want to include both A&B articles, and for audience C, I want to include
> them all. I was preparing to just create three different XSL files and
> then use Instant Saxon to transform with each XSL. However, since the
> output is formatted identically, I suspect there's a much more elegant
> way to do it (perhaps passing some parameter when compiling?), but I'm
> not sure what I would do.
>
> If this is explainable to a beginner, I'd appreciate any help. (Or if
> this is beyond a beginner's ability, I'd appreciate someone telling me
> that... and I'll do the easy three files as I planned and come back to
> this at some point in the future.)
======================================================================
Wendell Piez mailto:wapiez@xxxxxxxxxxxxxxxx
Mulberry Technologies, Inc. http://www.mulberrytech.com
17 West Jefferson Street Direct Phone: 301/315-9635
Suite 207 Phone: 301/315-9631
Rockville, MD 20850 Fax: 301/315-8285
----------------------------------------------------------------------
Mulberry Technologies: A Consultancy Specializing in SGML and XML
======================================================================
XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list