1

I have an XML document which uses multiple @class values, like below:

<html>
     <head>
        <title>This is the title.</title>
     </head>
     <body>
         <div class="sect1 rights">
             <p>This is the first paragraph.</p>
         </div>
     </body>
</html>

However, my XSLT below does not work when both @class values are present. It will only work if <div class="rights">.

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="xs"
version="2.0">

<xsl:template match="node()|@*">
    <xsl:copy>
        <xsl:apply-templates select="node()|@*"/>
    </xsl:copy>        
</xsl:template>

<xsl:template match="*[@class='rights']">
    <p>Rights have not cleared to show this material.</p>
</xsl:template>

I don't think this is a priority of templates problem (from the identity template) as I'm not getting a warning of that. Is there a way to select this content? I won't always know what other class values are assigned besides "rights" so I can't use *[@class='sect1 rights'] as sect1 will change throughout the document.

user2093335
  • 197
  • 1
  • 2
  • 12

2 Answers2

2

In your example, the "class" attribute has only a single value: the string "sect1 rights". If you want to test for the inclusion of the string "rights" in that value, use:

<xsl:template match="*[contains(@class,'rights')]">

or perhaps:

contains(concat(' ', @class, ' '), ' rights ')

if you want to ensure the presence of "rights" as a word (i.e. not as part of "copyrights", for example).

michael.hor257k
  • 113,275
  • 6
  • 33
  • 51
2

Since you're using XSLT 2.0, you can use tokenize(). This a much simpler form of the concat() solution that @user3016153 gave (both forms are much more accurate than the simple contains()).

<xsl:template match="*[tokenize(@class,'\s')='rights']">
    <p>Rights have not cleared to show this material.</p>
</xsl:template>

It is also very easy to extend if you want to match more than one possible class:

<xsl:template match="*[tokenize(@class,'\s')=('rights','otherclass')]">
    <p>Rights have not cleared to show this material.</p>
</xsl:template>
Sylvain Leroux
  • 50,096
  • 7
  • 103
  • 125
Daniel Haley
  • 51,389
  • 6
  • 69
  • 95