skip to Main Content

so I’m trying to have a list of books be filtered so only the ones in a certain category are displayed. I’m going off this http://www.w3schools.com/xsl/tryxslt.asp?xmlfile=cdcatalog&xsltfile=cdcatalog_filter which I copy and pasted in and just changed the variables because it wasn’t working, and it still won’t work. The problem is this line:

<xsl:for-each select="Catalog/Book[bookCategory='database']">

If I change it so it has a “/” in front of catalog, it works but it keeps looping and I’ll have a long list of the same books repeating:

<xsl:for-each select="/Catalog/Book[bookCategory='database']">

If anyone can figure out why that lines not working I’d appreciate it.

XML (shortened version for the sake of sanity, it’s normally really long):

<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet href="HTMLfilter.xsl" type="text/xsl"?>
<Catalog xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="C:UsersSeanDocumentsXMLCLA~1FINALP~1CATALO~1.XSD">
    <Book>
        <bookID>0-07-882122-3</bookID>
        <bookTitle>Oracle: A Beginner's Guide</bookTitle>
        <bookCategory>database</bookCategory>
        <bookDescription>A beginner's guide to the complex and powerful Oracle database management system. Teaches you how to set up, query and manage your database, including principles of database design, how to manage data, generate reports and tune the system for optimal performance.</bookDescription>
        <bookPrice>30.00</bookPrice>
        <bookAuthor>Michael Abbey</bookAuthor>
        <bookImage>images/Oracle.JPG</bookImage>
        <bookInfo>Oracle.xml</bookInfo>
    </Book>
    <Book>
        <bookID>0-201-43787-7</bookID>
        <bookTitle>Creating Killer Interactive Web Sites : The Art of Integrating Interactivity and Design</bookTitle>
        <bookCategory>web</bookCategory>
        <bookDescription>Creating Killer Interactive Sites is the one-of-a-kind look into the secrets of one of the world's most preeminent Web design firms. Its highly visual, inspiring approach brings a new standard to integrating design and interactivity to create successful sites. The book's companion Web site includes all the code and examples from the book, valuable tools and utilities, plus updated new, information, and tips.</bookDescription>
        <bookPrice>39.99</bookPrice>
        <bookAuthor>Deke McClelland</bookAuthor>
        <bookImage>images/KillerInteractiveSites.gif</bookImage>
        <bookInfo>CreatingKiller.xml</bookInfo>
    </Book>
    <Book>
        <bookID>0-201-44787-8</bookID>
        <bookTitle>The Practical SQL Handbook</bookTitle>
        <bookCategory>database</bookCategory>
        <bookDescription>The best-selling guide to learning SQL, the standard language for accessing information in relational databases. Teaches SQL as it's really used, with step-by-step lessons in the basic vocabulary and functions of the language and the processes and issues involved in developing robust applications.</bookDescription>
        <bookPrice>40.12</bookPrice>
        <bookAuthor>Judith Bowman</bookAuthor>
        <bookImage>images/PracticalSQL.JPG</bookImage>
        <bookInfo>PracticalSQL.xml</bookInfo>
    </Book>
    <Book>
        <bookID>0-672-30956-4</bookID>
        <bookTitle>SQL Server 6.5 Second Edition</bookTitle>
        <bookCategory>database</bookCategory>
        <bookDescription>Comprehensive guide to Microsoft SQL Server 6.5, including the latest enhancements such as Distributed Transaction Coordinator (DTC), replication to ODBC clients, SQL Enterprise Manager and SQL Web Assistant, SQL language enhancements.</bookDescription>
        <bookPrice>60.00</bookPrice>
        <bookAuthor>David Solomon</bookAuthor>
        <bookImage>images/SQLUnleashed.JPG</bookImage>
        <bookInfo>SQLServer.xml</bookInfo>
    </Book>
    <Book>
        <bookID>0-7645-4032-7</bookID>
        <bookTitle>Photoshop 4 for Windows 95 Bible</bookTitle>
        <bookCategory>graphics</bookCategory>
        <bookDescription>Comprehensive reference for Photoshop users includes step-by-step guides to everything from working wonders with layers to customizing graphics for the World Wide Web.</bookDescription>
        <bookPrice>50.23</bookPrice>
        <bookAuthor>Deke McClelland</bookAuthor>
        <bookImage>images/PS4Bible.JPG</bookImage>
        <bookInfo>Photoshop4.xml</bookInfo>
    </Book>
    <Book>
        <bookID>1-26592-234-2</bookID>
        <bookTitle>Web Page Design : A Different Multimedia</bookTitle>
        <bookCategory>web</bookCategory>
        <bookDescription>Revealing the crucial differences between an ordinary Web page and an effective site, bestselling Internet author Mary E. S. Morris and co-author Randy J. Hinrichs go beyond the basics of web creation to show readers how to tackle the crucial problems of information overload at your Web site, getting lost in cyberspace, bandwidth constraints required to hold a user's attention, and more.</bookDescription>
        <bookPrice>19.96</bookPrice>
        <bookAuthor>David Flanagan</bookAuthor>
        <bookImage>images/WebPageDesign.gif</bookImage>
        <bookInfo>WebPageDesign.xml</bookInfo>
    </Book>
    <Book>
        <bookID>1-549514-32-1</bookID>
        <bookTitle>Information Architecture for the World Wide Web</bookTitle>
        <bookCategory>web</bookCategory>
        <bookDescription>With a swift and convincing stroke, the authors of Information Architecture for the World Wide Web tear down many entrenched ideas about Web design. Flashy animations are cool, they agree, as long as they don't irritate the viewer. Nifty clickable icons are nice, but are their meanings universal? Is the search engine providing results that are useful and relevant? This book acts as a mirror and with careful questioning causes the reader to think through all the elements and decisions required for well-crafted Web design.</bookDescription>
        <bookPrice>19.34</bookPrice>
        <bookAuthor>Louis Rosenfeld</bookAuthor>
        <bookImage>images/InformationArchitecture.gif</bookImage>
        <bookInfo>InformationArchitecture.xml</bookInfo>
    </Book>
    <Book>
        <bookID>1-56204-223-1</bookID>
        <bookTitle>The Non-Designer's Web Book : An Easy Guide to Creating, Designing, and Posting Your Own Web Site</bookTitle>
        <bookCategory>web</bookCategory>
        <bookDescription>The Non-Designer's Web Book is a pretty, full-color guide for aspiring Web designers. The authors first explain how to browse and search the Web and then discuss how to plan and post a Web site. Then they get you into the real work of designing Web sites, whether for business or personal purposes. The authors teach you basic design principles--covering such areas as alignment, proximity, repetition, and contrast--and then discuss design issues that are specific to the Web: You learn about creating pages with careful attention to color, graphics, typography, tables, and more. Finally, you learn how to test, fix, upload, update, and register your site. The book isn't an HTML primer, but you do get a few tips on tweaking your pages by editing HTML code.</bookDescription>
        <bookPrice>23.96</bookPrice>
        <bookAuthor>Robin Williams</bookAuthor>
        <bookImage>images/NonDesignerWebBook.gif</bookImage>
        <bookInfo>NonDesigner.xml</bookInfo>
    </Book>
    <Book>
        <bookID>1-56542-264-4</bookID>
        <bookTitle>Elements of Web Design : The Designer's Guide to a New Medium</bookTitle>
        <bookCategory>graphics</bookCategory>
        <bookDescription>Elements of Web Design helps designers learn how the experts plan and design their Web sites. It"s ideal for readers who haven"t yet learned what the Web is all about, but who'd like to start applying their design and management skills to Web-site production. The book provides a history of the Web, examples of well-designed sites, and information on coding HTML and preparing Web graphics.</bookDescription>
        <bookPrice>31.96</bookPrice>
        <bookAuthor>Michael Groh</bookAuthor>
        <bookImage>images/ElementsOfWebDesign.gif</bookImage>
        <bookInfo>ElementsofWebDesign.xml</bookInfo>
    </Book>
    <Book>
        <bookID>1-56592-234-4</bookID>
        <bookTitle>JavaScript: The Definitive Guide</bookTitle>
        <bookCategory>programming</bookCategory>
        <bookDescription>A thorough description of the JavaScript programming language, complete with sophisticated programming examples, as well as a definitive, in-depth reference section covering each JavaScript function, object method, property and event handler.</bookDescription>
        <bookPrice>33.23</bookPrice>
        <bookAuthor>David Flanagan</bookAuthor>
        <bookImage>images/JavaScript.JPG</bookImage>
        <bookInfo>Javascript.xml</bookInfo>
    </Book>
    <Book>
        <bookID>1-56604-286-0</bookID>
        <bookTitle>The Visual Guide to Microsoft Access for Windows 95</bookTitle>
        <bookCategory>database</bookCategory>
        <bookDescription>A graphical approach to using Microsoft Access 95 to build, customize and manage databases.</bookDescription>
        <bookPrice>35.36</bookPrice>
        <bookAuthor>Michael Groh</bookAuthor>
        <bookImage>images/MSAccess.JPG</bookImage>
        <bookInfo>MicrosoftAccess95.xml</bookInfo>
    </Book>
</Catalog>

full XSL:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format">
    <xsl:output method="html" version="4.0" encoding="UTF-8" indent="yes"/>
    <xsl:template match="Catalog/Book">
        <xsl:for-each select="Catalog/Book[bookCategory='database']">
            <h3>
                <xsl:text>Title: </xsl:text>
                <xsl:value-of select="bookTitle"/>
            </h3>
            <img alt="">
                <xsl:attribute name="src"><xsl:value-of select="bookImage"/></xsl:attribute>
            </img>
            <div>
                <xsl:text>Author: </xsl:text>
                <xsl:value-of select="bookAuthor"/>
            </div>
            <div>
                <xsl:text>ISBN: </xsl:text>
                <xsl:value-of select="bookID"/>
            </div>
            <div>
                <a>
                    <xsl:attribute name="href"><xsl:value-of select="bookInfo"/></xsl:attribute>
            Click here for details
            </a>
            </div>
        </xsl:for-each>
    </xsl:template>
    <xsl:template match="/">
        <html>
            <head>
                <link rel="stylesheet" href="catalog.css"/>
                <h4>Filter by Category: </h4>
                <A href="HTMLcategory.xml">HTML</A>  |  
                <A href="nonexist.xml">Javascript</A>  |  
                <A href="nonexist.xml">Database</A>  |  
                <A href="nonexist.xml">Graphics</A>  |  
                <A href="nonexist.xml">Programming</A>  |  
                <A href="nonexist.xml">Web</A>
            </head>
            <body>
                <xsl:apply-templates select="Catalog/Book"/>
            </body>
            <br>
                <A href="allBooks.xml">Back</A>
            </br>
        </html>
    </xsl:template>
</xsl:stylesheet>

If anyone sees the problem, let me know!

Thanks!

3

Answers


  1. The template itself,

    <xsl:template match="Catalog/Book">
    

    already selects all Book elements. Everything you put “in” there will be relative to that XPath. Putting a / in front of the Catalog makes it read globally again, once for each book. That is why you get nothing, or the entire list repeated for every single Book.

    All you need here is a single test for each single Book:

    <xsl:for-each select=".[bookCategory='database']">
    

    but, since there is (or should) only be one, you can also use a simple if instead of the <xsl:for-each>:

    <xsl:if test="bookCategory='database'">
    

    However, you should avoid such a test and only call the template for Book when necessary, by removing the for-each/if (so it always write its output). Change the template match itself to

    <xsl:template match="Book">
    

    and in the template for /, change the line

    <xsl:apply-templates select="Catalog/Book"/>
    

    to

    <xsl:apply-templates select="Catalog/Book[bookCategory='database']"/>
    

    This way, you can easily add more lines immediately below this one to add other categories, all of these calls will be close together, and you can adjust the template for each single Book in only one location.

    Login or Signup to reply.
  2. Your <xsl:template match="Catalog/Book"> is matching each book.

    If within that template, you use

    <xsl:for-each select="Catalog/Book[bookCategory='database']">

    none will be found because the selection is relative to the current position, (i.e., things under the current /Catalog/Book )and there is none.

    Using

    <xsl:for-each select="/Catalog/Book[bookCategory='database']">

    you’re finding all the books of the specified database, but from the root, without regard for where you are in the document, and you find them again on repeated matches of the template.

    The answer by @Jongware gives one possible solution.

    Another is to change your template and for-each to collaborate sensibly:

    <?xml version="1.0" encoding="UTF-8"?>
    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format">
        <xsl:output method="html" version="4.0" encoding="UTF-8" indent="yes"/>
        <xsl:template match="Catalog">
            <xsl:for-each select="Book[bookCategory='database']">
                <h3>
                    <xsl:text>Title: </xsl:text>
                    <xsl:value-of select="bookTitle"/>
                </h3>
                <img alt="">
                    <xsl:attribute name="src"><xsl:value-of select="bookImage"/></xsl:attribute>
                </img>
                <div>
                    <xsl:text>Author: </xsl:text>
                    <xsl:value-of select="bookAuthor"/>
                </div>
                <div>
                    <xsl:text>ISBN: </xsl:text>
                    <xsl:value-of select="bookID"/>
                </div>
                <div>
                    <a>
                        <xsl:attribute name="href"><xsl:value-of select="bookInfo"/></xsl:attribute>
                Click here for details
                </a>
                </div>
            </xsl:for-each>
        </xsl:template>
        <xsl:template match="/">
            <html>
                <head>
                    <link rel="stylesheet" href="catalog.css"/>
                    <h4>Filter by Category: </h4>
                    <A href="HTMLcategory.xml">HTML</A>  |  
                    <A href="nonexist.xml">Javascript</A>  |  
                    <A href="nonexist.xml">Database</A>  |  
                    <A href="nonexist.xml">Graphics</A>  |  
                    <A href="nonexist.xml">Programming</A>  |  
                    <A href="nonexist.xml">Web</A>
                </head>
                <body>
                    <xsl:apply-templates select="Catalog/Book"/>
                </body>
                <br>
                    <A href="allBooks.xml">Back</A>
                </br>
    
            </html>
        </xsl:template>
    </xsl:stylesheet>
    
    Login or Signup to reply.
  3. A somewhat more idiomatic solution for XSLT:

    <!-- Books with the right category have their contents formatted as HTML -->
    <xsl:template match="Book[bookCategory='database']" priority="1">
          <h3>
                <xsl:text>Title: </xsl:text>
                <xsl:value-of select="bookTitle"/>
            </h3>
            <img alt="">
                <xsl:attribute name="src"><xsl:value-of select="bookImage"/></xsl:attribute>
            </img>
            <div>
                <xsl:text>Author: </xsl:text>
                <xsl:value-of select="bookAuthor"/>
            </div>
            <div>
                <xsl:text>ISBN: </xsl:text>
                <xsl:value-of select="bookID"/>
            </div>
            <div>
                <a>
                    <xsl:attribute name="href"><xsl:value-of select="bookInfo"/></xsl:attribute>
            Click here for details
            </a>
            </div>
    
    </xsl:template>
    
    <!-- Other Books produce no output, and thus are discarded. -->
    <xsl:template match="Book"/>
    

    With those two templates, you can let XSLT’s template matching do all the selection work for you. (The priority adjustment ensures that Books which have the right category match that template rather than the more general one which catches everything else.)

    XSLT is a declarative, nonprocedural, pattern-matching language. You’ll be most productive in it, and get the most value out of it, if you learn to write your code in terms of templates and applies rather than explicit loops.

    If you really insist on having a single template for both cases, then @Jongware’s answer is correct — just use ‘xsl:if’, and apply it to the current node (‘.’).

    Note that if you’re designing this from scratch, I would suggest turning most of your ‘book’s child elements into attributes instead. If the value isn’t going to have further sub-structure, an attribute is usually easier to work with as well as being more compact.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search