This is the mail archive of the xsl-list@mulberrytech.com mailing list .


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Re: Conditional text using attributes


| I'm trying to figure out how to exclude text and graphics from an output
| file (HTML or FO, for example) by testing for attributes in my XSL
| stylesheet. For instance, I have an XML file with instructions
| appropriate for both Macintosh users and Windows users.
| 
| I'm using the DocBook DTD and Norm Walsh's DocBook XSL stylesheets

Beth,

You can do what you're trying to achieve by using XSLT's
import mechanism (instead of the <xsl:include> that your example
had) in combination with the <xsl:apply-imports/> action.
Here's a simple example that hopefully will get you going
in the right direction...

Let's say your Docbook source looks like this:

<?xml version="1.0"?>
<article>
  <para>
    Press the <emphasis os="PC">Left</emphasis> mouse button to start 
    the timer. You can use the <emphasis os="Mac">Finder</emphasis>
    <emphasis os="PC">Start Button</emphasis> to launch a new program.
  </para>
</article>

and let's say we had the following stylesheet playing the role
of Norm's "docbook.xsl" for illustration:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                version="1.0">
  <xsl:strip-space elements="*"/>
  <xsl:preserve-space elements="programlisting"/>

  <xsl:template match="book|article">
   <html>
     <body>
      <xsl:apply-templates/>
     </body>
   </html>
  </xsl:template>

  <xsl:template match="para">
    <p><xsl:apply-templates/></p>
  </xsl:template>

  <xsl:template match="emphasis">
    <i><xsl:apply-templates/></i>
  </xsl:template>

</xsl:stylesheet>

Just as you were doing (but using <xsl:import> instead
of <xsl:include>) we can create a "beth.xsl" stylesheet
like the one below to import the base stylesheet,
and add one or more templates that will take precedence
over the templates from the imported stylesheet:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                version="1.0">
  <xsl:import href="norm.xsl"/>

   <!-- Your overrides here -->

</xsl:stylesheet>

Since it appears you want to key off the presence
of an "os" attribute, it doesn't really make
sense to have your template match all of
the combinations that you had:

| <xsl:template match="*|@*|comment()|text()">

since attributes, comments, and text cannot themselves
have an "os" attribute. So you only need to match
elements using the "*" pattern.

Presumably, not all elements have an "os" attribute, so
what I'm guessing you want is some logic like this:

  -> When you match any element...

     -> If the element has NO "os" attribute
        *OR* 
        If the element has an "os" attribute and
        its value is the value for the current
        platform that your rendering,

        -> Then, go process the current element
           using the templates from the imported
           stylesheet

     -> Else

        -> Do nothing (to suppress it's being rendered)

We can accomplish this with a template like the following,
where "$os" is a top-level XSL parameter that represents
the current platform you're rendering. The <xsl:apply-imports/>
tells the XSLT processor to process the current node
(an element in this case) using the template from
the imported stylesheet.

  <xsl:template match="*">
    <xsl:if test="not(@os) or @os=$os">
      <xsl:apply-imports/>
    </xsl:if>
  </xsl:template>

The completed "beth.xsl" stylesheet then looks like
this (with the <xsl:param> declaration at the top...

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
  <xsl:import href="norm.xsl"/>

  <xsl:param name="os">Mac</xsl:param>

  <xsl:template match="*">
    <xsl:if test="not(@os) or @os=$os">
      <xsl:apply-imports/>
    </xsl:if>
  </xsl:template>

</xsl:stylesheet>

So now I can use a command-line XSLT engine (I'll use
Oracle XSLT as an example) you can now do:

  $ oraxsl test.xml beth.xsl

to produce the rendering for the default value ('Mac')
of the "$os" parameter, to get the output of:

<html>
   <body>
      <p>
    Press the  mouse button to start
    the timer. You can use the
    <i>Finder</i> to launch a new program.
  </p>
   </body>
</html>

By passing a different value for the "$os" parameter
on the command line, you can render the "PC" version
using a command like (notice the single quotes!):

  $ oraxsl -p os='PC' test.xml beth.xsl

This produces the "PC"-ified version:

<html>
   <body>
      <p>
    Press the <i>Left</i> mouse button to start
    the timer. You can use the
    <i>Start Button</i> to launch a new program.
  </p>
   </body>
</html>

Hope this helps.
______________________________________________________________
Steve Muench, Lead XML Evangelist & Consulting Product Manager
BC4J & XSQL Servlet Development Teams, Oracle Rep to XSL WG
Author "Building Oracle XML Applications", O'Reilly
http://www.oreilly.com/catalog/orxmlapp/



 XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]