[XSL-LIST Mailing List Archive Home] [By Thread] [By Date] [Recent Entries] [Reply To This Message]

RE: Comparing attribute values with the matches() fun

Subject: RE: Comparing attribute values with the matches() function
From: "Michael Kay" <mike@xxxxxxxxxxxx>
Date: Mon, 7 Apr 2008 10:29:31 +0100
RE:  Comparing attribute values with the matches()  fun
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.

Current Thread

PURCHASE STYLUS STUDIO ONLINE TODAY!

Purchasing Stylus Studio from our online shop is Easy, Secure and Value Priced!

Buy Stylus Studio Now

Download The World's Best XML IDE!

Accelerate XML development with our award-winning XML IDE - Download a free trial today!

Don't miss another message! Subscribe to this list today.
Email
First Name
Last Name
Company
Subscribe in XML format
RSS 2.0
Atom 0.3
Site Map | Privacy Policy | Terms of Use | Trademarks
Free Stylus Studio XML Training:
W3C Member
Stylus Studio® and DataDirect XQuery ™are products from DataDirect Technologies, is a registered trademark of Progress Software Corporation, in the U.S. and other countries. © 2004-2013 All Rights Reserved.