Re: [xsl] XHTML html validation

Subject: Re: [xsl] XHTML html validation
From: Abel Braaksma <>
Date: Sat, 17 Feb 2007 00:04:06 +0100
Hi John,

This clears things up quite a bit. What I understand now, is the following (see my comments)

<%@ page contentType='x-application/xslt' %>

You serve this page with content-type "x-application/xslt" (don't believe that is a valid content-type but, I'm not sure), but your page is XML. The content-type should be text/xml or text/application+xml

<?xml-stylesheet href='xslt/dev.xsl'?>

This means that you are not using Resin at all for transformation. The browser does the transformation. With this instruction, you ask the browser to search on the path 'xslt/dev.xsl' (relative to the *.jsp file and available though http) to load and apply the dev.xsl file to the XML content of your page.

<html xmlns=""; xml:lang="en" lang="en">

In a way, this looks like you want your page to be XHTML, but this won't make your page XHTML unless it contains XHTML. The xmlns here is, I think, not wrong per se, but my guess is that you rather have plain XML, something like <data> or <faqlist> here.

In addition, the namespace declaration means that all XPath instructions must be in that same namespace.



Indeed, it is not XHTML. It is some XML, that's all. A tip: don't use that namespace when it is about data and when the elements do not match XHTML, it will be rather confusing.

<xsl:stylesheet xmlns:xsl=""; version="1.0">

There is nothing about the namespace ""; in this declaration. And neither is there in your template matches. None of your template matches will ever match.

<xsl:output method="html"
doctype-public="-//W3C//DTD XHTML 1.0 Transitional//EN"/>

I reckon, but am not sure, that xsl:output is out of place here. The document is translated into a DOM, not serialized, and xsl:output only applies to parsers that can serialize, and browsers cannot do that (well, not entirely true, but that's another subject). I never use xsl:output for my client-side, browser-based XSLT.

<xsl:template match='faqlist'>
This will never match anything, unless you place it in a namespace.

<xsl:apply-templates select="*[local-name() != 'faq']" />

You won't need to use this kind of construct. This is what you do when you do not know the namespace of a certain element up front. My advice: remove the namespace in your XML and you can simply say:

<xsl:apply-templates select="faq" />

  <xsl:apply-templates select="faq" mode="question" />
  <xsl:apply-templates select="faq" mode="answer" />

Like you do here. You do not need to switch modes. Select "faq/question" and "faq/answer". Make a matching template for "answer" and one for "question". Use the current-node instruction, the dot . retrieving your values of these nodes, like this:

<xsl:template match='answer'>
         <td colspan="2" >&#160; </td>
         <td class="mText" style="font-size: 11px" align='left'>
           <xsl:copy-of select='.' />

A few tips here, too: I also see you use classes, the style attribute and width. It is better to place all these in your CSS, the class attribute can be moved up to the table level and declare your CSS as

.mText td {font-size: 11px}

etc. You can use colspan if some cells do not contain any content. Set the width of the cells only on the first one, which is likely the <th>.

<xsl:template match='*|@*'> <xsl:copy> <xsl:apply-templates select='node()|@*' /> </xsl:copy> </xsl:template>

Aha! The copy template. That matches anything not matched. In this case: this means that *everything* is copied, because none of the other templates will match. Which is why your output looks equal to your input.

This generates html which looks like this

How did you see this? Does the browser show you this? Or was I mistaken and does Resin parse the <?xsl-stylesheet instruction for you? It looks like the latter.

Well, to make it all work: remove the namespace in your original XML. Fix a couple of things in your stylesheet. When debugging, it is a good idea to remove the xsl:copy for a while to see if the matches work. Also, add <html>, <head> etc to the stylesheet, not to your source document. You want to separate logic from data (and probably design from logic, with CSS), this means you should remove all this from your source and let the XSLT do the work for you.

<!DOCTYPE HTML PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN""";>

<html xmlns=""; xml:lang="en" lang="en">


-- Abel Braaksma

Current Thread