Re: <xsl:copy-of> question

Subject: Re: <xsl:copy-of> question
From: David Carlisle <davidc@xxxxxxxxx>
Date: Thu, 16 Dec 1999 16:37:18 GMT
> As a side question, the xsl:copy copy the imput namespace but for
> example, if you want to transform xhtml to html with the html output,

You can use xsl:element and explitly produce an element with the same
local-name as the source element, and any namespace that you want.


> Doing xhtml to xhtml with xml output doesn't follow the suggestions
> for a good display of xhtml (<br /> for example).

You can't force the space there but you can output
<br class="html-compat"/>
(with any arbitray class name) which seems to be enough.
Similar;y you have to take care to add some white space as content to
any elements which happen to be empty, so you get <a name="xx"> </a> not
<a name="xxx"/>

The stylesheet below (which is an improved version of one I posted
before is intended to convert xsl stylesheets, but the template
<xsl:template match="*|xsl:element">
is a more or less general html to xhtml converter.

David



<!--

html2xhtml.xsl:  HTML to XHTML  XSL stylesheet converter
========================================================

$Id: html2xhtml.xsl,v 1.3 1999/12/07 14:11:58 davidc Exp $

 Copyright 1999 David Carlisle NAG Ltd


The following stylesheet takes as input an XSL stylesheet that writes
HTML, and produces a stylesheet that writes XML that hopefully matches the
XHTML specification. (It does not check that the output matches the DTD.)
It does the following things:

* Adds a DOCTYPE giving FPI and URL for one of the three flavours
  of XHTML1. (Transitional unless the original stylesheet asked for
  Frameset or Strict HTML.)
  If the system-dtd parameter is set then instead of the canonical
  XHTML PUBLIC DTD, a SYSTEM declaration is given to the supplied URL.

* Writes all HTML elements and attributes as lowercase, with 
  elements being written in the XHTML namespace.

* Writes canonically empty elements such as <BR> as
  <br class="html-compat"/> . 
  (Appendix C recommends <br /> rather than <br/> but an XSL stylesheet
  has no control over the concrete syntax of the linearisation, so
  adding an attribute is probably the best that can be done. (No attribute
  is added if the element already has attributes.)

* Changes the output method from html to xml in xsl:output
  (and also in the xt:document extension element).

* Forces a line break after opening tags of non elements which are
  not canonically empty, to ensure that they are never written with XML
  empty syntax, so
  <p>
  </p>
  not
  <p/>

* Copies any elements from XSL or XT namespaces through to the new
  stylesheet.


* Duplicates name attributes to id unless element already has id.

* Adds meta element to head specifying utf-8 encoding.

-->

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
                xmlns:xt="http://www.jclark.com/xt";
                xmlns="http://www.w3.org/1999/xhtml";
                version="1.0"
                >

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

<xsl:param name="system-dtd" />

<xsl:template match="xsl:*|xt:*">
<xsl:copy>
  <xsl:copy-of select="@*"/>
  <xsl:apply-templates/>
</xsl:copy>
</xsl:template>

<xsl:template match="xsl:output|xt:document">
<xsl:copy>
  <xsl:attribute name="method">xml</xsl:attribute>
  <xsl:choose>
  <xsl:when test="$system-dtd">
    <xsl:attribute name="doctype-system">
       <xsl:value-of select="$system-dtd"/>
    </xsl:attribute>
  </xsl:when>
  <xsl:when test="contains(@doctype-public,'Frameset')">
    <xsl:attribute name="doctype-public">
     <xsl:text>-//W3C//DTD XHTML 1.0 Frameset//EN</xsl:text>
    </xsl:attribute>
    <xsl:attribute name="doctype-system">
       <xsl:text>http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd</xsl:text>
    </xsl:attribute>
  </xsl:when>
  <xsl:when test="contains(@doctype-public,'Strict')">
    <xsl:attribute name="doctype-public">
     <xsl:text>-//W3C//DTD XHTML 1.0 Strict//EN</xsl:text>
    </xsl:attribute>
    <xsl:attribute name="doctype-system">
       <xsl:text>http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd</xsl:text>
    </xsl:attribute>
  </xsl:when>
  <xsl:otherwise>
    <xsl:attribute name="doctype-public">
     <xsl:text>-//W3C//DTD XHTML 1.0 Transitional//EN</xsl:text>
    </xsl:attribute>
    <xsl:attribute name="doctype-system">
       <xsl:text>http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd</xsl:text>
    </xsl:attribute>
  </xsl:otherwise>
  </xsl:choose>
  <xsl:attribute name="indent">yes</xsl:attribute>
  <xsl:copy-of select="@*[not(
      name(.)='method' or
      name(.)='doctype-public' or
      name(.)='doctype-system' or
      name(.)='indent'
      )  ]"/>
  <xsl:apply-templates/>
</xsl:copy>
</xsl:template>

<xsl:template match="*|xsl:element">
<xsl:variable name="n">
  <xsl:choose>
  <xsl:when test="self::xsl:element">
    <xsl:value-of  select="translate(@name,
                   'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 
                   'abcdefghijklmnopqrstuvwxyz')"/>
  </xsl:when>
  <xsl:otherwise>
    <xsl:value-of  select="translate(local-name(.),
                   'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 
                   'abcdefghijklmnopqrstuvwxyz')"/>
  </xsl:otherwise>
  </xsl:choose>
</xsl:variable>
<xsl:element
  name="{$n}"
   namespace="http://www.w3.org/1999/xhtml";>
  <xsl:for-each select="self::*[not(self::xsl:element)]/@* |
                       self::xsl:element/@use-attribute-sets">
    <xsl:attribute name="{translate(local-name(.),
                   'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 
                   'abcdefghijklmnopqrstuvwxyz')}">
     <xsl:value-of select="."/>
    </xsl:attribute>

  </xsl:for-each>
  <xsl:if test="@name and not(@id)">
    <xsl:attribute name="id"><xsl:value-of select="@name"/></xsl:attribute>   
  </xsl:if>
  <xsl:if test="@NAME and not(@id)">
    <xsl:attribute name="id"><xsl:value-of select="@NAME"/></xsl:attribute>   
  </xsl:if>
  <xsl:choose>
  <xsl:when test="not($n='br' or $n='hr'
         or $n='link' or $n='img' or $n='base' or $n='meta' or $n='head')">
   <xsl:element name="xsl:text" xml:space='preserve'>&#xA;</xsl:element>
   <xsl:apply-templates/>
  </xsl:when>
   <xsl:when test="local-name(.)='head'">
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
   <xsl:apply-templates/>
   </xsl:when>
  <xsl:when test="not(@*)">
    <xsl:attribute name="class">html-compat</xsl:attribute>
  </xsl:when>
  </xsl:choose>
</xsl:element>
</xsl:template>


</xsl:stylesheet>



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


Current Thread