Subject: Match by attribute.
Posted By: ole_v2 Post Date: 11/10/2006 7:33:54 AM
Input XML:
<?xml version="1.0"?>
<library>
    <book>
        <title>PHP Cookbook</title>
        <type>Reference</type>
    </book>
    <book featured="yes">
        <title>Jam and the dodgers</title>
        <type>Comedy</type>
    </book>
    <book>
        <title>Matilda</title>
        <type>Adventure</type>
    </book>
</library>


Desired output:
<html><body>
<div class="featured">
    <h1>Jam and the dodgers</h1>
</div>
<div class="others">
    <div>
        <h2>PHP Cookbook</h2>
    </div>
    <div>
        <h2>Matilda</h2>
    </div>
</div>
Basically I need to match for featured='yes' and others separately. I could use a for-each and then choose. But I'm trying to get my head around template and apply-templates. How would it be done using them?

This is what I'm trying at the moment, but the matches clearly aren't working. xslt
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" indent="yes"
        doctype-public="-//W3C//DTD XHTML 1.0 Strict//EN"
        doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"/>
    <xsl:template match="/">
        <div class="featured">
            <xsl:apply-templates match="book[featured='yes']"/>
        </div>
        <div class="others">
            <xsl:apply-templates match="book[featured!='yes']"/>
        </div>
    </xsl:template>
    <xsl:template match="book[featured='yes']">
        <h1><xsl:value-of select="title"/></h1>
    </xsl:template>
    <xsl:template match="book[featured!='yes']">
        <div><h2><xsl:value-of select="title"/></h2></div>
    </xsl:template>
</xsl:stylesheet>

Generates
<?xml version="1.0"?>
<!DOCTYPE div PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<div class="featured">Jam and the dodgersComedyMatildaAdventure</div><div class="others">Jam and the dodgersComedyMatildaAdventure</div>

Am I going about this the wrong way? Is there a better way to do this?

Many thanks in advance.

Reply By: joefawcett Reply Date: 11/10/2006 7:47:19 AM
There were quite a few mistakes in the XSLT but I think these may have ben copy/paste as what you showed would have produced very little.
This isa working version, I've removed the doctype stuff to simplify because with XHTML you need to create namespaced elements.
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">   
    <xsl:template match="/">
    <html><head><title>Books</title></head><body>
        <div class="featured">
            <xsl:apply-templates select="library/book[@featured = 'yes']"/>
        </div>
        <div class="others">
            <xsl:apply-templates select="library/book[not(@featured = 'yes')]"/>
        </div>
    </body></html>
    </xsl:template>
    <xsl:template match="book[@featured = 'yes']">
        <h1><xsl:value-of select="title"/></h1>
    </xsl:template>
    <xsl:template match="book[not(@featured = 'yes')]">
        <div><h2><xsl:value-of select="title"/></h2></div>
    </xsl:template>
</xsl:stylesheet>



--

Joe (Microsoft MVP - XML)
Reply By: ole_v2 Reply Date: 11/10/2006 7:57:10 AM
Wow, what a great place this is :)
Thanks joefawcett that worked perfectly.

Obviously I need to look into XPath more.

Reply By: ole_v2 Reply Date: 11/11/2006 7:11:47 AM
OK. I'm a bit confused.
I've just tried having a template matching
book[@featured = 'yes']
and
book[not(@featured = 'yes')]
and that works very well.

Then I tried having a template matching
book[@featured = 'yes']
and
book[@featured != 'yes']
The != one doesn't match.

Why is this?

Reply By: joefawcett Reply Date: 11/11/2006 7:59:53 AM
Because @featured != 'yes' needs an attribute called featured that doesn't equal 'yes'. As the elements don't have a featured  attribute it doesn't not equal 'yes'. not(@featured = 'yes') means any situation except where there is a featured attribute with a value of 'yes'.

--

Joe (Microsoft MVP - XML)
Reply By: mhkay Reply Date: 11/11/2006 8:43:40 AM
@featured='yes' means "there is an attribute featured and it is equal to yes". @featured!=yes means "there is an attribute featured and it is not equal to yes". not(@featured=yes)" means "there is not an attribute featured that is equal to yes".

Hope this makes it more clear!

Michael Kay
http://www.saxonica.com/
Author, XSLT Programmer's Reference and XPath 2.0 Programmer's Reference
Reply By: ole_v2 Reply Date: 11/11/2006 9:24:41 AM
Ahh yes that does make things clearer.


Go to topic 52184

Return to index page 124
Return to index page 123
Return to index page 122
Return to index page 121
Return to index page 120
Return to index page 119
Return to index page 118
Return to index page 117
Return to index page 116
Return to index page 115