Subject: RE: Comparing attribute values with the matches() function
From: "Michael Kay" <mike@xxxxxxxxxxxx>
Date: Mon, 7 Apr 2008 10:29:31 +0100
|
Firstly, this:
@audience=.//*[@audience]/@audience
is the same as this:
@audience=.//*/@audience
because if an element doesn't have an @audience attribute, it will be
ignored anyway.
> The expression I need will be similar but require only that
> the two @audience values share at least one audience identifier.
I would write a function:
<xsl:function name="f:overlaps" as="xs:boolean">
<xsl:param name="a1" as="attribute(audience)"/>
<xsl:param name="a2" as="attribute(audience)"/>
<xsl:sequence select="string-to-codepoints($a1) =
string-to-codepoints($a2)"/>
</xsl:function>
(The "=" test, remember, tests whether any item in the first sequence is
equal to any item in the second sequence).
Then the condition becomes
test="some $d in .//*/@audience satisfies f:overlaps(@audience, $d)"
Michael Kay
http://www.saxonica.com/
> -----Original Message-----
> From: Tony Cusack [mailto:tony@xxxxxxxxxxxxxx]
> Sent: 06 April 2008 22:28
> To: xsl-list@xxxxxxxxxxxxxxxxxxxxxx
> Subject: Comparing attribute values with the matches() function
>
> Hello XSL list,
>
> I am having difficulty (with my very basic XSLT skills)
> devising a test to compare attribute values. Hope you may be
> able to help.
>
> My application filters XML content for multiple audiences
> identified simply as A, B, C etc potentially up to Z. The
> source is flagged with an @audience value such as 'ABC' to
> indicate that it is relevant to those three audiences. As one
> descends through the document the content becomes more
> specific. The following snippet illustrates:
>
> <Publication title="Demo publication" audience="ABC">
> <Topic title="Level 1 ABC">
> <BodyText>Level 1 Content shared by all 3 audiences.</BodyText>
> <Topic title="Level 2 ABC">
> <BodyText>Level 2 Content shared by all audiences.</BodyText>
> <Topic title="Level 3 ABC">
> <BodyText>Level 3 Content shared by all audiences.</BodyText>
> </Topic>
> <Topic title="Level 3 AB" audience="AB">
> <BodyText>Level 3 Content shared by AB audiences.</BodyText>
> </Topic>
> <Topic title="Level 3 BC" audience="BC">
> <BodyText>Level 3 Content shared by BC audiences.</BodyText>
> </Topic>
> <Topic title="Level 3 AC" audience="AC">
> <BodyText>Level 3 Content shared by AC audiences.</BodyText>
> </Topic>
> <Topic title="Level 3 A" audience="A">
> <BodyText>Level 3 Audience A only content.</BodyText>
> </Topic>
> </Topic>
> </Topic>
> </Publication>
>
> Note that @audience is DTD optional everywhere except
> Publication, but, as a business rule, should only ever occur
> at the point where @audience narrows down.
>
> To filter the content I run my stylesheet once for each
> audience with a global variable ($config) set to that
> audience's identifier, and use the
> contains() function to compare @audience values with the
> global variable.
> For example:
>
> Topic[(contains(@audience, $config)) or (not(@audience) and
> ancestor::*[@audience][1][contains(@audience,$config)])]>
>
> For other purposes however I need to compare @audience values
> with each other rather than a global variable. For example I
> want to run a test at the beginning of each execution of the
> stylesheet to check that the above mentioned business rule
> has been observed. The contains() function won't do the trick
> because, for example, ABC doesn't 'contain' AC in the relevant sense.
>
> I believe the XSLT 2 matches() function will achieve the
> desired result but I'm afraid that when it comes to mixing
> XPath expressions with Regex it all becomes too much for me.
>
> To give you a better idea of my approach here is an
> expression which works for the = operator.
>
> <xsl:when
> test="//*[@audience=.//*[@audience]/@audience]"><xsl:value-of
> select="//*[@audience=.//*[@audience]/@audience][1]//*[@audien
> ce][1]/@title"
> /></xsl:when>
>
> In English that's "When any element has a descendant with
> @audience equal to its (the ancestor's) own @audience, output
> the @title of the first descendant instance of the first
> ancestor instance".
>
> The expression I need will be similar but require only that
> the two @audience values share at least one audience identifier.
>
> I am using Saxon b9-0-0-2j.
>
> Thanks very much,
> Tony Cusack.
|