krul
krul

Reputation: 2269

How XSLT Templates Rules are applied

Let's say I have following XML:

XML

<bookstore>
<book category="cooking">
    <title lang="en">Everyday Italian</title>
    <author>Giada De Laurentiis</author>
    <year>2005</year>
    <price>30.00</price>
</book>
<book category="children">
    <title lang="en">Harry Potter</title>
    <author>J K. Rowling</author>
    <year>2005</year>
    <price>29.99</price>
</book>
<book category="web">
    <title lang="en">XQuery Kick Start</title>
    <author>James McGovern</author>
    <author>Per Bothner</author>
    <author>Kurt Cagle</author>
    <author>James Linn</author>
    <author>Vaidyanathan Nagarajan</author>
    <year>2003</year>
    <price>49.99</price>
</book>
<book category="web" cover="paperback">
    <title lang="en">Learning XML</title>
    <author>Erik T. Ray</author>
    <year>2003</year>
    <price>39.95</price>
</book>

and following XSLT:

XSLT

    <?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="2.0"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:fo="http://www.w3.org/1999/XSL/Format"
                xmlns:xs="http://www.w3.org/2001/XMLSchema"
                xmlns:fn="http://www.w3.org/2005/xpath-functions"
                xmlns:msxsl="urn:schemas-microsoft-com:xslt"
                exclude-result-prefixes="fo xs fn msxsl">

  <xsl:output method="xml" indent="yes" />

  <xsl:template match="/">
    <xsl:element name="rootnode">
      <xsl:choose>
        <xsl:when test="//bookstore/book[year!=2005]">
          <xsl:message select="'book exists'" />
          <xsl:apply-templates></xsl:apply-templates>
        </xsl:when>
      </xsl:choose>
    </xsl:element>
  </xsl:template>

  <xsl:template match="book[year!=2005]">
    <xsl:element name="not2005">
      <xsl:copy-of select="." />
    </xsl:element>
    <!--<xsl:apply-templates select="@* | node()" />-->
  </xsl:template>
</xsl:stylesheet>

Once transformed xml looks like this:

Result

<?xml version="1.0" encoding="UTF-8"?>
<rootnode>Everyday ItalianGiada De Laurentiis200530.00Harry PotterJ K. Rowling200529.99<not2005>
        <book category="web">
            <title lang="en">XQuery Kick Start</title>
            <author>James McGovern</author>
            <author>Per Bothner</author>
            <author>Kurt Cagle</author>
            <author>James Linn</author>
            <author>Vaidyanathan Nagarajan</author>
            <year>2003</year>
            <price>49.99</price>
        </book>
    </not2005>
    <not2005>
        <book category="web" cover="paperback">
            <title lang="en">Learning XML</title>
            <author>Erik T. Ray</author>
            <year>2003</year>
            <price>39.95</price>
        </book>
    </not2005>
</rootnode>

instead of what I'm expecting:

Expected result

<?xml version="1.0" encoding="UTF-8"?>
<rootnode>
    <not2005>
        <book category="web">
            <title lang="en">XQuery Kick Start</title>
            <author>James McGovern</author>
            <author>Per Bothner</author>
            <author>Kurt Cagle</author>
            <author>James Linn</author>
            <author>Vaidyanathan Nagarajan</author>
            <year>2003</year>
            <price>49.99</price>
        </book>
    </not2005>
    <not2005>
        <book category="web" cover="paperback">
            <title lang="en">Learning XML</title>
            <author>Erik T. Ray</author>
            <year>2003</year>
            <price>39.95</price>
        </book>
    </not2005>
</rootnode>

Why following is transformed/picked up?

Everyday ItalianGiada De Laurentiis200530.00Harry PotterJ K. Rowling200529.99

and also curious why my xsl:message is not popping up as well?

<xsl:message select="'book exists'" />

Any article pointers explaining fundamental concept that I'm obviously missing would be appreciated...

Upvotes: 1

Views: 69

Answers (1)

Martin Honnen
Martin Honnen

Reputation: 167401

Change

  <xsl:choose>
    <xsl:when test="//bookstore/book[year!=2005]">
      <xsl:message select="'book exists'" />
      <xsl:apply-templates></xsl:apply-templates>
    </xsl:when>
  </xsl:choose>

to

<xsl:apply-templates select="bookstore/book[year != 2005]"/>

Your current code only works as you rely on built-in templates https://www.w3.org/TR/xslt20/#built-in-rule but they have the effect of outputting any text nodes of elements you don't explicitly match.

Upvotes: 1

Related Questions