RE: [xsl] should be a simple problem

Subject: RE: [xsl] should be a simple problem
From: Tom Preston <tpreston@xxxxxxxxxxxxxxxxx>
Date: Thu, 13 Dec 2001 15:03:08 -0500
I take Jeni's recommendation and give a fully qualified name in the .xsl
document.  But now, the namespace that I add to the xsl document gets
output!  Can anyone explain this to me and tell me how to get the namespace
to not appear in the output document.
----------------
opera.out (notice the xmlns:op inside the <html> element)
----------------
<html xmlns:op="http://www.emilygraham.com/java/other/Opera";>
<body>
<center>
<h1>Programme</h1>
<h2>Wolfgang Amadeus Mozart (1756-1791)</h2>
<p>The Magic Flute</p>
<p>Don Giovanni</p>
<h2>Guiseppe Verdi (1813-1901)</h2>
<p>Ernani</p>
<p>Rigoletto</p>
<h2>Giacomo Puccini (1858-1924)</h2>
<p>Tosca</p>
</center>
</body>
</html>
----------------
opera.xsl
----------------
<?xml version="1.0"?>
<xsl:stylesheet version="1.0"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
                xmlns:op="http://www.emilygraham.com/java/other/Opera";>
<xsl:template match="/">             
<html>
<body><center>
   <h1>Programme</h1>
   <xsl:for-each select="/op:programme/op:composer">
       <h2><xsl:value-of select="concat(op:fullname, ' (', op:born, '-',
op:died, ')')"/></h2>
       <xsl:variable name="c" select="."/>
       <xsl:for-each select="/op:programme/op:opera[op:composer=$c/@name]">
           <p><xsl:value-of select="op:title"/></p>
       </xsl:for-each>
   </xsl:for-each>
</center></body>
</html>
</xsl:template>
</xsl:stylesheet>
----------------
opera.xml
----------------
<?xml version="1.0"?>
<programme xmlns="http://www.emilygraham.com/java/other/Opera";>
	<opera>
		<title>The Magic Flute</title>
		<composer>Mozart</composer>
        <date>1791</date>
	</opera>
	<opera>
		<title>Don Giovanni</title>
		<composer>Mozart</composer>
        <date>1787</date>
	</opera>
	<opera>
		<title>Ernani</title>
		<composer>Verdi</composer>
        <date>1843</date>
	</opera>
	<opera>
		<title>Rigoletto</title>
		<composer>Verdi</composer>
        <date>1850</date>
	</opera>
	<opera>
		<title>Tosca</title>
		<composer>Puccini</composer>
        <date>1897</date>
	</opera>
    <composer name="Mozart">
        <fullname>Wolfgang Amadeus Mozart</fullname>
        <born>1756</born>
        <died>1791</died>
    </composer>
    <composer name="Verdi">
        <fullname>Guiseppe Verdi</fullname>
        <born>1813</born>
        <died>1901</died>
    </composer>
    <composer name="Puccini">
        <fullname>Giacomo Puccini</fullname>
        <born>1858</born>
        <died>1924</died>
    </composer>
</programme>


Thanks

Tom
-----Original Message-----
From: Jeni Tennison [mailto:jeni@xxxxxxxxxxxxxxxx]
Sent: Thursday, December 13, 2001 5:17 AM
To: Tom Preston
Cc: xsl-list@xxxxxxxxxxxxxxxxxxxxxx
Subject: Re: [xsl] should be a simple problem


Hi Tom,

> I am new to xslt. Much of the explanation of xslt (books, websites)
> discuss namespace from the .xsl perspective and doesn't give
> examples where the -IN xml document uses namespaces. My specific
> problem is that when I add a namespace, the examples break.

In your first example, the programme, opera etc. elements were all in
*no namespace* as you had no default namespace declaration (and they
weren't prefixed).

In your second example, the programme, opera etc. elements were all in
the namespace 'http://www.emilygraham.com/java/other/Opera' as that
was the namespace specified by the default namespace declaration.

When expressions or patterns select or match elements and attributes,
they select or match them according to *both* their local name (e.g.
'programme', 'opera') and their namespace.  As far as an XSLT
processor is concerned, the two following programme elements are
completely different:

  <programme>
    ...
  </programme>
  
  <programme xmlns="http://www.emilygraham.com/java/other/Opera";>
    ...
  </programme>

I sometimes use the extended representation {namespace-uri}local-name
to make this clearer. In the first example, the programme element is
{}programme. In the second example, the programme element is actually
{http://www.emilygraham.com/java/other/Opera}programme.

When you use an element or attribute name in an XPath and you don't
give a prefix to that element or attribute name, the XSLT processor
*always* looks for elements/attributes in no namespace. So:

  /programme/composer

is equivalent to:

  /{}programme/{}composer

To process your second example, you need to have the equivalent of:

  /{http://www.emilygraham.com/java/other/Opera}programme
    /{http://www.emilygraham.com/java/other/Opera}composer

To do this, you need to have a prefix in your XSLT stylesheet that
is associated with the namespace
'http://www.emilygraham.com/java/other/Opera'. You do this in the same
way as you do in normal documents, with an xmlns:xx attribute:

<xsl:stylesheet version="1.0"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
                xmlns:op="http://www.emilygraham.com/java/other/Opera";>
...
</xsl:stylesheet>

Within the stylesheet, the 'op' prefix is associated with the
'http://www.emilygraham.com/java/other/Opera' namespace. So you can
do:

  /op:programme/op:composer

to get the XPath that you need.

To put it into simple steps - if you add a default namespace to your
instance document you need to:

 - declare the namespace with a prefix in the stylesheet
 - change all the paths in the stylesheet so that they use the prefix

One of the requirements for XSLT 2.0 is that you should be able to
easily change the default namespace used when an element (or
attribute?) name in a path doesn't have a prefix, so that adding a
namespace to a document doesn't involve a massive change in the
stylesheet.

I hope that helps,

Jeni

---
Jeni Tennison
http://www.jenitennison.com/

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


Current Thread