XSLT, include html, mix html and xml

HTML

1. How to use HTML as input documents?
2. Embedding HTML in XML documents using HTML dtd
3. HTML to XML conversion
4. Exclude-result-prefixes
5. How to embed HTML in XML
6. Including BR in an XSL template
7. HTML include problem
8. How to embed xsl:value-of into html tag
9. Embedding html in xml problem
10. HTML in XML
11. How to copy HTML elements
12. Headers and Footers in HTML
13. Parsing HTML as XML
14. Embed and don't escape xml in html

1.

How to use HTML as input documents?

Jarno Elovirta

Basically, use sx, Tidy, JTidy, or NekoHTML

John Cowan's TagSoup can also be used, but the last I tried, it messed up pre element content whitespace. NekoHTML is blizz with Java XSLT engines, works just like a SAX parser and e.g. Saxon have an option in their CLI to use if for parsing.

2.

Embedding HTML in XML documents using HTML dtd

Jeni Tennison


>I would like to enable HTML tags within my XML file - using the HTML
>dtd. For example, if there is a list in the XML:
><list>
><UL>
>            <LI>List item 1</LI>
>            <LI>List item 2</LI>
>            </UL>
></list>
>
>What do I have to add to the XML, the DTD and the XSL to be able to
>convert this to a list when I generate an HTML file? I would
>like to use the HTML dtd to make this work.
	

There are two approaches to this problem: either you can use what you know about your XML to say "the content of a 'list' element is HTML and should be copied directly" or you can explicitly put the UL and LI elements in the HTML namespace within the source XML, and then within your stylesheet say "all HTML elements should be copied".

In either case, you need to know about the xsl:copy and xsl:copy-of elements. xsl:copy copies the current node, but none of its contents or attributes. xsl:copy-of copies a node set that you select, including all of its contents and any attributes or namespace nodes.

The first is simpler but less extensible: when you find a 'list' element, you make a copy of its element content:

<xsl:template match="list">
  <xsl:copy-of select="*" />
</xsl:template>

Given an input of:

<list>
  <UL>
    <LI>List item 1</LI>
    <LI>List item 2</LI>
  </UL>
</list>

This will give:

<UL>
    <LI>List item 1</LI>
    <LI>List item 2</LI>
  </UL>

The problem is that you have to do something similar anywhere else where you have HTML elements within your XML elements and you want them copied. It might be that 'lists' are the only elements where HTML elements occur, in which case this is the easiest solution.

The second solution is to use namespaces to explicitly say that the UL and LI elements are HTML elements. To do that, you associate a namespace prefix (a string that you can choose) to a namespace name (a string that you can choose, but that should probably be a URI pointing to a DTD, schema, or human-readable documentation about the elements you're using). For common XML dialects like HTML, there is usually a namespace name defined somewhere, and using that namespace name could enable you to use other people's stylesheets that also process elements in that namespace. In the case of XHTML, the namespace name is:

  http://www.w3.org/1999/xhtml

You can associate the prefix 'html' with this namespace name using a namespace attribute:

  xmlns:html="http://www.w3.org/1999/xhtml"

You don't have to use the prefix 'html' - you can use anything you want.

This attribute should be put on an element that is an ancestor of the HTML elements (or is itself an HTML element). A namespace attribute makes a namespace 'in scope' (i.e. usable) for the element that it's on and all its descendents. Usually you'd put it on your document element (i.e. the top-most element). In your case, you could put it on the 'list' element:

<list xmlns:html="http://www.w3.org/1999/xhtml">
  ...
</list>

Within the 'list' element, any elements that are within the HTML namespace need to be given qualified names to indicate that fact. You do this by adding the prefix (i.e. 'html') and a colon before the name of the element, so:

<list xmlns:html="http://www.w3.org/1999/xhtml">
  <html:UL>
    <html:LI>List item 1</html:LI>
    <html:LI>List item 2</html:LI>
  </html:UL>
</list>

As a quick aside, XHTML defines that element names should be in lower case, so I'd make this:

<list xmlns:html="http://www.w3.org/1999/xhtml">
  <html:ul>
    <html:li>List item 1</html:li>
    <html:li>List item 2</html:li>
  </html:ul>
</list>

for compliance to that standard.

In terms of the DTD for the source XML, DTDs and namespaces don't mix particularly well: you have to use the same qualified names within the DTD as you use within your XML, which means that the prefix is fixed within the DTD. [You could get around this using a parameter entity.] If you have to validate your source XML against a DTD, then the DTD should hold something like:

<!ELEMENT list (html:ul)>
<!ATTLIST list
  xmlns:html CDATA #FIXED 'http://www.w3.org/1999/xhtml'>

<!ELEMENT html:ul (html:li+)>
<!ELEMENT html:li (#PCDATA)>

You may be able to draw on some of the XHTML modularisation work to import relevant parts of the HTML DTD, but they may not be using qualified names, I'm not sure.

Within the XSLT stylesheet, you have to ensure that all the relevant namespaces are declared so that whenever you use a qualified name (like 'html:UL'), the namespace declaration for it is 'in scope'. This usually means putting the namespace attribute on the xsl:stylesheet document element:

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

Again, you don't have to use the 'html' prefix, but you *do* have to make sure that the namespace name (the http://www.w3.org/1999/xhtml URI) is the same in your source XML and your stylesheet. It's actually the namespace name (or URI) that is used to determine the namespace that an element is in, not its prefix.

Within your stylesheet, then, you can now place the rule "copy all HTML elements". The following template matches any element in the source that's within the HTML namespace (whether it's within a 'list' or not):

<xsl:template match="html:*">
  <xsl:copy-of select="." />
</xsl:template>

However, when you're producing HTML output, copying is a bad idea because while the XSLT processor will produce something that is technically correct XML, it will not be interpreted correctly by the vast majority of HTML browsers. The above, for example, produces:

<html:ul xmlns:html="http://www.w3.org/1999/xhtml">
   <html:li>List item 1</html:li>
   <html:li>List item 2</html:li>
</html:ul>

because it literally copies everything, including the namespace nodes. Instead, then, you should create by hand the relevant elements and attributes, giving them names corresponding to the local part of their name, without the namespace prefix:

<xsl:template match="html:*">
  <xsl:element name="{local-name()}">
    <xsl:for-each select="@html:*">
      <xsl:attribute name="{local-name()}">
        <xsl:value-of select="." />
      </xsl:attribute>
    </xsl:for-each>
    <xsl:apply-templates />
  </xsl:element>
</xsl:template>

This has the added advantage that if you have any specialised XML embedded within your HTML elements, it will be treated as that specialised XML rather than simply copied without paying attention to what it is.

So, to summarise:

1. declare the HTML namespace within your source document (namespace attribute on document element)
2. change the names of HTML elements within your source document to give them the relevant namespace prefix
3. add the namespace attribute to the DTD and change the names of the relevant elements to reflect the namespace prefix
4. declare the HTML namespace within your stylesheet (namespace attribute on xsl:stylesheet element)
5. use the above template to copy all HTML elements into your result

3.

HTML to XML conversion

Duane Nickull

1. XML GLobal has a two way conversion process which is the subject of scrutiny for it's use in retaining XML semantics within the confines of an HTML document. IT has been referred to by it's ancronym of XHML which stands for Extensible hybrid markup language. DO not worry - it's not being proposed as another standard! ;-)

The idea is that our XML Search Engine can then index HTML data the same way it captures XML documents for indexing.

It converts XML to html but retains the original context by embedding the XML tags within the html document that start with a namespace. By default, ours appear as <xhml:MyOriginalXmlTagHere>some content</xhml:MyOriginalTagHere>. This avoids collisions with other namespaces. It still renders the user the exact same page becuase browsers ignore the tags they don;t understand due to forwards compatibility issues. Our goals is to offer this as a way to make the WWW more intelligent to search through one day.

The HTML to XML transformation is only valid on properly formed html. When we parse the HTML described in the earlier POST (XHML), we ignore all tags except those which start with the prefix namespace (in our case <xhml:foo>).

I do not think there would be any purpose to transforming any tags from html with the exception of properly constructed <html><head><title><body><p> tags.

2. A company called Percussion has a two way conversion engine they unleashed this week at XML 99. It converts XML to html but retains the original context by embedding the XML tags within the html document inside a Span ID="PREFIX - OriginalTagHere> They have a two way demo for XML to HTML to XML conversions.

4.

Exclude-result-prefixes

Toivo Lainevool


5.

How to embed HTML in XML

Mike Brown


> I want to embed HTML into an XML.The problem which I am facing is that the
> XSLT processor gives errors for HTML tags and forces me to define them in
> the DTD.
> 
> Is there some simple way in which I can make the XSLT processor to ignore
> the HTML tags and I dont have to define it in the DTD.
    

HTML and XML do not mix. You can pretend your HTML is one character data section, copy it to a text node, and rely on disable-output-escaping functionality in XSLT to work with it, but ultimately you may find it easier to make your HTML well-formed XML (XHTML; see the spec at w3.org) and work with that in your XML instead.

As for validation, an XML parser is feeding to the XSL processor some information about the logical contents of the XML document. It is possible that you are invoking an XSL processor and it is invoking an XML parser for you. The XSL processor does not know about the DTD. You should check the documentation for your XSL processor and/or XML parser to figure out how to get it to parse without validating.

You can't half-validate, though. If you're validating, you must declare all the elements that are used in the document. No way around that.

6.

Including BR in an XSL template

David Marston


>Some browsers just don't like the <BR/> format, and display two empty
>lines with the <BR></BR> format.

Putting it all together:

1. xsl:output method="html" specified
2. Stylesheet says to output <BR/>
3. XSLT processor takes (1) into account when performing (2), so it
   actually generates <BR>

As already mentioned, the above behavior is required by the XSLT spec (Section 16.2, paragraph 4), so you can depend on it.

7.

HTML include problem

Jeni Tennison


>    I have created my XML documents with schemas and XSLs. Is it possible to
>use 'include' method in XSL so I don't have to type the same piece of 'html'
>code in each XSL? Those 'html' code are static for all XSLs. E.g. header and
>footer.

>Could anyone help me out with my problem.
>I want to embed an HTML doucment(by giving the path of the file) into either
>an XSL or XML .
>Could you tell me how?
    

I'll answer these together since they are both the same question. The first thing is that you need to make sure that your HTML files are well-formed XML. XSLT can't process anything that isn't well-formed XML. You can make your HTML well-formed by running it through Tidy.

Once you have your HTML files well-formed you can include them into your output in two main ways.

Firstly, you can declare them as external parsed entities within the stylesheet and then put references to them wherever you want them put. For example:

<?xml version="1.0"?>
<!DOCTYPE xsl:stylesheet [
<!-- declares header.html as an external parsed entity -->
<!ENTITY header SYSTEM "header.html">
]>
<xsl:stylesheet version="1.0"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:template match="/">
  <html>
    <head><title>Test Page</title></head>
    <body>
      <!-- includes header.html directly -->
      &header;
      <xsl:apply-templates />
    </body>
  </html>
</xsl:template>

</xsl:stylesheet>

[See archive for more details.]

Secondly, you can access them using document and create copies of their content. For example:

<xsl:template match="/">
  <html>
    <head><title>Test Page</title></head>
    <body>
      <xsl:copy-of select="document('header.html')" />
      <xsl:apply-templates />
    </body>
  </html>
</xsl:template>

The second method is probably better in most situations because it limits the effective size of the stylesheet. However, it can give quite verbose output if you've declared the HTML namespace in your HTML (which you should probably have done). xsl:copy-of and xsl:copy both give complete copies of all the nodes within the node set (i.e. the document in this case), including all the namespace nodes, so you get xmlns="http://www.w3.org/1999/xhtml" on every element.

A final approach is to have a couple of templates that copy the elements by hand (as it were) and thus don't include the namespace (best to define a separate mode to do this):

<xsl:template match="*" mode="copy">
  <xsl:element name="{local-name()}">
    <xsl:copy-of select="@*" />
    <xsl:apply-templates mode="copy" />
  </xsl:element>
</xsl:template>

<xsl:template match="text()" mode="copy">
  <xsl:value-of select="." />
</xsl:template>

And then apply templates to the document in copy mode:

<xsl:template match="/">
  <html>
    <head><title>Test Page</title></head>
    <body>
      <xsl:apply-templates select="document('header.html')" mode="copy" />
      <xsl:apply-templates />
    </body>
  </html>
</xsl:template>

8.

How to embed xsl:value-of into html tag

Wendell Piez

You want an attribute value template, like so:

<xsl:template match="productName">
  <input type="text" name="productName"
     value='{.}' size="25" maxlength="30" />
</xsl:template>

There's another way to do it with <xsl:attribute>, but this is the easy way.

It's not a workaround either. An AVT (recognize it by the { } ) is explicitly provided as a way of saying "inside this attribute, evaluate this expression instead of taking it as a literal."

9.

Embedding html in xml problem

Jeni Tennison


>I want to put lots of html code between <top> and </top> (and all the rest
>too).  So in my xsl I can have something like:
>
>  <xsl:template match="top">
>    <table width="100%" border="0" height="30">
>      <tr>
>        <td>
>        <!-- whatever it takes to grab the values between the top tags,
>value-of or whatever -->
>        </td>
>      </tr>
>    </table>
>  <xsl:call-template name="left"/>
>  <xsl:call-template name="bottom"/>
>  </xsl:template>

You will find XSL a lot easier and more gratifying to use if you think in terms of the abstract node trees that you're manipulating rather than the string representation of those trees. It is very very very rare that you need to resort to CDATA sections and disable-output-escaping.

If you're wanting to grab all the content within the 'top' element and just copy it node-for-node, then you're looking for xsl:copy-of. xsl:copy-of takes the nodes that you specify (so the HTML content of your 'top' element) and copies them exactly as they are, with all their attributes and all their content intact:

  <xsl:template match="top">
    <table width="100%" border="0" height="30">
      <tr>
        <td>
          <xsl:copy-of select="node()" />
        </td>
      </tr>
    </table>
    <xsl:call-template name="left"/>
    <xsl:call-template name="bottom"/>
  </xsl:template>

If the content of the 'top' element has some elements in it that you need to process (e.g. embedded in the HTML, you have some XML elements that indicate where the portal user's name should go) then you need to step through the HTML, applying templates that, by default, copy the elements and apply templates to their content, with exceptions for those embedded XML elements:

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

<xsl:template match="insert-user">
  <xsl:value-of select="$user" />
</xsl:template>

Note that the default template (match="*") will match on *any* element. It may be worthwhile using namespaces to indicate which elements within your input are HTML and which are XML, because you can then limit the copying template to copying only the HTML elements:

<xsl:template match="html:*">
  ...
</xsl:template>

Or the other alternative is to use 'modes' to limit the application of the template. So in your 'top' matching template have:

  <xsl:template match="top">
    <table width="100%" border="0" height="30">
      <tr>
        <td>
          <xsl:apply-templates mode="copy" />
        </td>
      </tr>
    </table>
    <xsl:call-template name="left"/>
    <xsl:call-template name="bottom"/>
  </xsl:template>

and make the copying template be both within that mode and apply templates in that mode:

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

10.

HTML in XML

Steve Muench


|  We have
| some fields in our database that has HTML tags in the data to emphasize the
| text in the browser.  A good example of this is to have parts of data being
| bold using <STRONG> tag, or displaying information 
| using bullets with <UL>
| tags.  I create XML using this data, and when I send the XML to the XSLT
| processor, I don't get any results back if there are any HTML tags in the
| data.
| Is there any way I can have the XSLT processor to ignore the HTML Tags?
    

If you are generating query results that contain HTML fragments like:

<ROWSET>
  <ROW>
    <SKU>12345</SKU>
    <DESC>Big Red Apple</DESC>
    <BLURB>
      &lt;ul>
        &lt;li>&lt;b>Delicious&lt;/b>&lt;/li>
        &lt;li>&lt;b>Nutritious&lt;/b>&lt;/li>
      &lt;/ul>
    </BLURB>
  </ROW>
</ROWSET>

And you want the HTML "blurb" to showup "verbatim" in the output:

for this you'd use (assuming the current node is "ROWSET/ROW"):

   <xsl:value-of disable-output-escaping="yes"
                           select="BLURB"/>

This will produce:

 <ul>
   <li><b>Delicious</b></li>
   <li><b>Nutritious</b></li>
 </ul>

11.

How to copy HTML elements

Gary Gregory

Here is a complete HTML 4.01 XSL

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

    <xsl:output method="xml" indent="no" omit-xml-declaration="yes"/>

    <xsl:param name="reportDir"/>

    <!-- Hack: copy HTML elements over -->

    <xsl:template match="/">

        <xsl:apply-templates/>

    </xsl:template>

    <xsl:template match=" a | abbr | acronym | address | applet | area | b | base | basefont | 
	    bdo | big | blockquote  | body | br | button | caption | center | cite | code | col | 
	    colgroup | dd | del | dfn | dir | div | dl | dt | em | fieldset     | font | form | 
	    frame | frameset | h1 | h2 | h3 | h4 | h5 | h6 | head | hr | html | i | iframe | img | 
	    input | ins | isindex    | kbd | label | legend | li | link | map | menu | meta | 
	    noframes | noscript | object | ol | optgroup | option | p     | param | pre | q | s | 
	    samp | script | select | small | span | strike | strong | style | sub | sup | table | 
	    tbody | td | textarea | tfoot | th | thead | title | tr | tt | u | ul | var">

        <xsl:copy>
            <xsl:copy-of select="@*"/>
            <xsl:apply-templates/>
        </xsl:copy>
    </xsl:template>
    <!-- End Hack: copy HTML elements over -->
    <!-- ADD template here -->
</xsl:stylesheet>



12.

Headers and Footers in HTML

Tim Watts

I'm working on a project which has standard headers and footers, and we use the following to call the include files;

<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:include href="../document.xsl" />
<xsl:param name="title">Search Results</xsl:param>
<xsl:template name="body">
    <!-- your data here -->
</xsl:template>
</xsl:stylesheet>

to call the document.xsl which is like so:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="*"/>
<!-- The main template that wraps the html tags, header and footer content
around the body template -->
<!-- when it finds the top level xml tag (document in my case) the template
is called -->
<xsl:template match="document">
<html lang="EN-US" dir="LTR">
<head>
    <script type="text/javascript" language="javascript">
<!-- any javascript you may want here -->
    </script>
<link rel="stylesheet" type="text/css" href="stylesheet.css"/>
   <title><xsl:value-of select="$title"/></title>
</head>
<body>
<!-- Your header info here -->
<xsl:call-template name="body"/><!-- this calls the body template in the
main xsl -->
<!-- Your footer info here -->
</body>
</html>
</xsl:template>

You will notice that each page has its own title because of the param in the original xsl

13.

Parsing HTML as XML

David Carlisle



<xsl:stylesheet
   version="2.0"
   xmlns:d="data:,dpc"
   xmlns:xs="http://www.w3.org/2001/XMLSchema"
   xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
   exclude-result-prefixes="d xs">

<!-- HTML Parser in XSLT2 Copyright 2004 David Carlisle
 Distribution, use and modification of this code permited so long as
 original is cited.  -->

<!-- $Id: htmlparse.xsl,v 1.14 2004/08/09 14:13:15 David Exp $-->

<!--

d:htmlparse(string)

  Parses the string as html using some inbuilt heuristics to control implied
  opening and closing of elements. 

  It doesn't have full knowledge of HTML DTD but does have full list of
  empty elements and full list of entity definitions. HTML entities, and
  decimal and hex character references are all accepted.

  Element names are lowercased and placed into the XHTML1 namespace. 
  Attribute names are lowercased.
  Four styles of attribute value are supported
      a="double quote delimited, including possibly unquoted < and >"
      a='single quote delimited, including possibly unquoted < and >'
      a=unquotedtoken a  which parse as the XML
      a="double quote delimited, including 
                   possibly unquoted &lt; and &gt;"
      a="single quote delimited, including 
                   possibly unquoted &lt; and &gt;"
      a="unquotedtoken"
      a="a"
  Doctype declarations are accepted but ignored
  Comments and Processing instructions produce equivalent constructs in the
  result tree
  CDATA sections are parsed correctly (Barring bugs)
  HTML Script and Style elemnets have some support as CDATA elements.

  XML "/>" empty element syntax is also accepted as are XML Namespace
  declarations, resulting elements will be in the specified namespaces
  (So Microsoft Style embedding of XML inside HTML should be parsed
  correctly, note howeve that in html mode currently all elements are
  lowercased even in "XML" sections, and html element names such as
  li will be recognised and treated specially even in XML sections.


  Note: very long attribute values (in excess of 800 characters) can cause 
  javascript regexp stack overflow in Saxon (It may be able to avoid this
  by using a larger JVM, haven't checked.)


d:htmlparse(string,namespace-uri)


  In the two argument form, the second argument (which may be "") gives the
  default namespace to use for initial unnamespaced elements in the input
  string. If this is "http://ww.w3.org/1999/xhtml" then the behaviour is
  exactly as described above for the one argument form. Otherwise the special
  casing of HTML element names and lowercasing of element and attreibute
  names is _not_ done. HTML entity names are still recognised though.
  Implied element ending is still implemented so
  
  <a><b><c></a>
  
  parses as
  
  <a><b><c></c></b></a>
  
  <body><p>one <p>two </body>
  
  parses as
  
  <body><p>one <p>two </p></p></body>
  
  In "XHTML mode" however,
  
  <body><p>one <p>two </body>
  
  parses as
  
  <body><p>one </p><p>two </p></body>
  
  AS when producing XHTML, an opening p tag causes the closing of any
  currently open p. Similar code is in place of HTML list items, etc.

Typical use:

  1)
    To produce a tree corresponding to the external HTML file
    file.html:
  
      <xsl:copy-of 
          select="d:htmlparse(unparsed-text('file.html','UTF-8'))"/>
  
  2)
    To parse a CDATA section quoted snippet of HTML in an element foo:
   <foo><![CDATA[...<a href="#x">click here</a> ...]]><foo>
  
    <xsl:template match="foo">
     <xsl:copy-of select="d:htmlparse(.)"/>
    </xsl:template>


-->



<xsl:variable name="d:attr"
   select="'(\i\c*)\s*(=\s*(&quot;[^&quot;]*&quot;|''[^'']*''|\c+))?\s*'"/>

<xsl:variable name="d:elem"
   select="'(\i\c*)'"/>

<xsl:variable name="d:comment"
   select="'&lt;!\-\-[^\-]*(\-[^\-]+)*\-\->'"/>

<xsl:variable name="d:pi"
   select="'&lt;\?\i\c*[^>]*>'"/>

<xsl:variable name="d:doctype"
   select="'&lt;!D[^\[&lt;>]*(\[[^\]]*\])?>'"/>

<xsl:variable name="d:cdata"
   select="'&lt;!\[CDATA(.|\s)*\]\]>'"/>

<xsl:function  name="d:htmlparse">
 <xsl:param name="s"/>
 <xsl:copy-of select="d:htmlparse($s,'http://www.w3.org/1999/xhtml')"/>
</xsl:function>

<xsl:function name="d:htmlparse">
 <xsl:param name="s"/>
 <xsl:param name="ns"/>
 <xsl:variable name="xhtml" select="$ns='http://www.w3.org/1999/xhtml'"/>
 <xsl:variable name="x">
  <xsl:analyze-string select="replace($s,'&#13;&#10;','&#10;')"
     regex="&lt;(/?){$d:elem}\s*(({$d:attr})*)(/?)>|{$d:comment}|{$d:pi}|{$d:doctype}|{$d:cdata}">
    <xsl:matching-substring>
      <xsl:choose>
      <xsl:when test="starts-with(.,'&lt;![CDATA')">
        <xsl:value-of select="substring(.,10,string-length(.)-13)"/>
      </xsl:when>
      <xsl:when test="starts-with(.,'&lt;!D')"></xsl:when>
      <xsl:when test="starts-with(.,'&lt;!-')">
        <comment>
          <xsl:value-of select="substring(.,5,string-length(.)-7)"/>
        </comment>
      </xsl:when>
      <xsl:when test="starts-with(.,'&lt;?')">
        <pi>
          <xsl:value-of 
          select="normalize-space((substring(.,3,string-length(.)-4)))"/>
        </pi>
      </xsl:when>
      <xsl:when test="(regex-group(1)='/')">
        <end name="{if ($xhtml) then 
         lower-case(regex-group(2)) else regex-group(2)}"/>
      </xsl:when>
      <xsl:otherwise>
        <start name="{if ($xhtml) then 
               lower-case(regex-group(2)) else regex-group(2)}">
          <attrib>
            <xsl:analyze-string regex="{$d:attr}" select="regex-group(3)">
            <xsl:matching-substring>
              <xsl:choose>
              <xsl:when test="starts-with(regex-group(1),'xmlns')">
                <!-- prototype support for embedded (MS-style) 
              namespaced XML inside html -->
                 <d:ns>
                   <xsl:variable name="n"
                     select="d:chars(substring(regex-group(3),2,
                 string-length(regex-group(3))-2))"/>
                   <xsl:namespace name="{substring-after(regex-group(1),'xmlns:')}"
                                  select="if ($n) then $n else 'data:,dpc'"/>
                 </d:ns>
              </xsl:when>
              <xsl:otherwise>
                <xsl:attribute name="{if ($xhtml) then 
                      lower-case(regex-group(1)) else regex-group(1)}">
                  <xsl:choose>
                  <xsl:when test="starts-with(regex-group(3),'&quot;')">
                    <xsl:value-of 
     select="d:chars(substring(regex-group(3),2,string-length(regex-group(3))-2))"/>
                  </xsl:when>
                  <xsl:when test="starts-with(regex-group(3),'''')">
                    <xsl:value-of 
     select="d:chars(substring(regex-group(3),2,string-length(regex-group(3))-2))"/>
                  </xsl:when>
                  <xsl:when test="string(regex-group(2))">
                    <xsl:value-of select="regex-group(3)"/>
                  </xsl:when>
                  <xsl:otherwise>
                    <xsl:value-of select="regex-group(1)"/>
                  </xsl:otherwise>
                  </xsl:choose>
                </xsl:attribute>
              </xsl:otherwise>
              </xsl:choose>
            </xsl:matching-substring>
            </xsl:analyze-string>
          </attrib>
        </start>
        <xsl:if test="regex-group(8)='/'">
        <end name="{if ($xhtml) then lower-case(regex-group(2)) 
                 else regex-group(2)}"/>
        </xsl:if>
      </xsl:otherwise>
      </xsl:choose>
    </xsl:matching-substring>
    <xsl:non-matching-substring>
      <xsl:value-of select="."/>
    </xsl:non-matching-substring>
  </xsl:analyze-string>
  </xsl:variable>
  
  
  <xsl:variable name="y">
  <xsl:choose>
  <xsl:when test="$xhtml">
    <xsl:apply-templates mode="d:html" select="$x/node()[1]"/>
  </xsl:when>
  <xsl:otherwise>  
    <xsl:apply-templates mode="d:gxml" select="$x/node()[1]"/>
  </xsl:otherwise>  
  </xsl:choose>
</xsl:variable>
  
  <xsl:variable name="j">
   <xsl:element name="x" namespace="{if ($ns) then $ns else ''}"/> 
  </xsl:variable>

  <xsl:variable name="z">
  <xsl:apply-templates mode="d:tree" select="$y/node()[1]">
    <xsl:with-param name="ns" select="$j/*/namespace::*[name()='']"/>
   </xsl:apply-templates>
  </xsl:variable>
  
  <!--
   <xsl:copy-of select="$x"/>
  ===
  <xsl:copy-of select="$y"/>
  ===
 -->

  <xsl:copy-of select="$z"/>
  
</xsl:function>

<xsl:function name="d:chars">
 <xsl:param name="s"/>
 <xsl:value-of>
  <xsl:analyze-string select="$s" 
             regex="&amp;(#?)(x?)([0-9a-fA-F]+|[a-zA-Z][a-zA-Z0-9]*);">
  <xsl:matching-substring>
  <xsl:choose>
  <xsl:when test="regex-group(2)='x'">
   <xsl:value-of select="codepoints-to-string(
         d:hex(
           for $i in string-to-codepoints(upper-case(regex-group(3)))
           return if ($i &gt; 64) then $i - 55 else $i - 48))"/>
  </xsl:when>
  <xsl:when test="regex-group(1)='#'">
    <xsl:value-of select="codepoints-to-string(xs:integer(regex-group(3)))"/>
  </xsl:when>
  <xsl:when test="$d:ents/key('d:ents',regex-group(3))">
    <xsl:value-of select="$d:ents/key('d:ents',regex-group(3))"/>
  </xsl:when>
  <xsl:otherwise>
  <xsl:message>htmlparse: Unknown entity: 
                <xsl:value-of select="regex-group(3)"/></xsl:message>
  <xsl:text>&amp;</xsl:text>
  <xsl:value-of select="regex-group(3)"/>
  <xsl:text>;</xsl:text>
  </xsl:otherwise>
  </xsl:choose>
  </xsl:matching-substring>
  <xsl:non-matching-substring>
   <xsl:value-of select="."/>
  </xsl:non-matching-substring>
  </xsl:analyze-string>
 </xsl:value-of>
</xsl:function>


<xsl:function name="d:hex">
<xsl:param name="x"/>
  <xsl:value-of
    select="if (empty($x)) then 0 else 
               ($x[last()] + 16* d:hex($x[position()!=last()]))"/>
</xsl:function>

<xsl:template mode="d:cdata"  match="text()">
<xsl:param name="s" select="()"/>
  <xsl:value-of select="."/>
  <xsl:apply-templates mode="#current" select="following-sibling::node()[1]">
    <xsl:with-param name="s" select="$s"/>
  </xsl:apply-templates>
</xsl:template>

<xsl:template mode="d:html d:gxml"  match="text()">
<xsl:param name="s" select="()"/>
  <xsl:value-of select="d:chars(.)"/>
  <xsl:apply-templates mode="#current" select="following-sibling::node()[1]">
    <xsl:with-param name="s" select="$s"/>
  </xsl:apply-templates>
</xsl:template>

<xsl:template mode="d:html d:gxml"  match="comment|pi">
<xsl:param name="s" select="()"/>
  <xsl:copy-of select="."/>
  <xsl:apply-templates mode="#current" select="following-sibling::node()[1]">
    <xsl:with-param name="s" select="$s"/>
  </xsl:apply-templates>
</xsl:template>


<xsl:template mode="d:html" match="start[@name=('script','style')]">
<xsl:param name="s" select="()"/>
  <start name="{@name}" s="{$s}">
   <xsl:copy-of select="attrib"/>
  </start>
  <xsl:apply-templates mode="d:cdata" select="following-sibling::node()[1]"/>
  <end name="{@name}" s="{$s}"/>
  <xsl:apply-templates mode="d:html" 
  select="following-sibling::end[@name=current()/@name][1]/following-sibling::node()[1]">
   <xsl:with-param  name="s" select="$s"/>
  </xsl:apply-templates>
</xsl:template>



<xsl:template mode="d:cdata" match="start">
   <xsl:text>&lt;</xsl:text>
  <xsl:value-of select="(@name,.)"/>
  <xsl:text>&gt;</xsl:text>
  <xsl:apply-templates mode="d:cdata" select="following-sibling::node()[1]"/>
</xsl:template>

<xsl:template mode="d:html d:gxml" match="start">
<xsl:param name="s" select="()"/>
  <start name="{@name}" s="{$s}">
   <xsl:copy-of select="attrib"/>
  </start>
  <xsl:apply-templates mode="#current"  select="following-sibling::node()[1]">
   <xsl:with-param  name="s" select="(string(@name),$s)"/>
  </xsl:apply-templates>
</xsl:template>

<xsl:template mode="d:html" 
match="start[@name=('br','hr','basefont','area','link','img','param','input','col',
         'frame','isindex','base','meta')]">
<xsl:param name="s" select="()"/>
  <start name="{@name}" s="{$s}">
   <xsl:copy-of select="attrib"/>
  </start>
  <end name="{@name}" s="{$s}"/>
  <xsl:apply-templates mode="d:html" 
        select="following-sibling::node()[not(self::end/@name=current()/@name)][1]">
   <xsl:with-param  name="s" select="$s"/>
  </xsl:apply-templates>
</xsl:template>

<xsl:variable name="d:lists" select="('ul','ol','dl')"/>
<xsl:variable name="d:listitems" select="('li','dt','dd')"/>

<xsl:template mode="d:html" match="start[@name=$d:listitems]">
<xsl:param name="s" select="()"/>
  <xsl:choose>
  <xsl:when test="not($d:lists=$s) or $d:lists=$s[1]">
  <start name="{@name}" s="{$s}">
   <xsl:copy-of select="attrib"/>
  </start>
  <xsl:apply-templates mode="d:html" select="following-sibling::node()[1]">
   <xsl:with-param  name="s" select="(string(@name),$s)"/>
  </xsl:apply-templates>
  </xsl:when>
  <xsl:otherwise>
    <xsl:call-template name="d:end">
      <xsl:with-param name="s" select="$s"/>
      <xsl:with-param name="n" select="$s[1]"/>
      <xsl:with-param name="next" select="."/>
    </xsl:call-template>
  </xsl:otherwise>
  </xsl:choose>
</xsl:template>



<xsl:template mode="d:html" match="start[@name='td']">
<xsl:param name="s" select="()"/>
  <xsl:choose>
  <xsl:when test="not('tr'=$s) or 'tr'=$s[1]">
  <start name="{@name}" s="{$s}">
   <xsl:copy-of select="attrib"/>
  </start>
  <xsl:apply-templates mode="d:html" select="following-sibling::node()[1]">
   <xsl:with-param  name="s" select="(string(@name),$s)"/>
  </xsl:apply-templates>
  </xsl:when>
  <xsl:otherwise>
    <xsl:call-template name="d:end">
      <xsl:with-param name="s" select="$s"/>
      <xsl:with-param name="n" select="$s[1]"/>
      <xsl:with-param name="next" select="."/>
    </xsl:call-template>
  </xsl:otherwise>
  </xsl:choose>
</xsl:template>


<xsl:template mode="d:html" match="start[@name='p']">
<xsl:param name="s" select="()"/>
  <xsl:choose>
  <xsl:when test="not('p'=$s)">
  <start name="{@name}" s="{$s}">
   <xsl:copy-of select="attrib"/>
  </start>
  <xsl:apply-templates mode="d:html" select="following-sibling::node()[1]">
   <xsl:with-param  name="s" select="(string(@name),$s)"/>
  </xsl:apply-templates>
  </xsl:when>
  <xsl:otherwise>
    <xsl:call-template name="d:end">
      <xsl:with-param name="s" select="$s"/>
      <xsl:with-param name="n" select="$s[1]"/>
      <xsl:with-param name="next" select="."/>
    </xsl:call-template>
  </xsl:otherwise>
  </xsl:choose>
</xsl:template>


<xsl:template mode="d:html d:gxml" match="end" name="d:end">
<xsl:param name="n" select="@name"/>
<xsl:param name="s" select="()"/>
<xsl:param name="next" select="following-sibling::node()[1]"/>
<xsl:variable name="s2" select="$s[position()!=1]"/>
  <xsl:choose>
  <xsl:when test="empty($s)">
  <!--====/<xsl:value-of select="$n"/>======-->
  <xsl:message>htmlparse: Not well formed 
        (<xsl:value-of select="@name"/>)</xsl:message>
  </xsl:when>
  <xsl:when test="$s[1]=$n">
  <end name="{$n}" s="{$s2}"/>
  <xsl:apply-templates mode="#current" select="$next">
   <xsl:with-param name="s" select="$s2"/>
  </xsl:apply-templates>
  </xsl:when>
  <xsl:when test="not($n=$s)">
  <!--====/<xsl:value-of select="$n"/>======-->
  <xsl:message>htmlparse: Not well formed 
         (ignoring /<xsl:value-of select="$n"/>)</xsl:message>
  <xsl:apply-templates mode="#current" select="$next">
   <xsl:with-param name="s" select="$s"/>
  </xsl:apply-templates>
  </xsl:when>
  <xsl:otherwise>
  <end name="{$s[1]}" s="{$s2}"/>
  <xsl:apply-templates mode="#current" select=".">
   <xsl:with-param name="s" select="$s2"/>
  </xsl:apply-templates>
  </xsl:otherwise>
  </xsl:choose>
</xsl:template>



<xsl:template mode="d:tree" match="text()">
  <xsl:param name="ns"/>
  <xsl:copy-of select="."/>
  <xsl:apply-templates select="following-sibling::node()[1]" mode="d:tree">
    <xsl:with-param name="ns" select="$ns"/>
  </xsl:apply-templates>
</xsl:template>

<xsl:template mode="d:tree" match="comment">
  <xsl:param name="ns"/>
  <xsl:comment>
    <xsl:value-of select="."/>
  </xsl:comment>
  <xsl:apply-templates select="following-sibling::node()[1]" mode="d:tree">
    <xsl:with-param name="ns" select="$ns"/>
  </xsl:apply-templates>
</xsl:template>

<xsl:template mode="d:tree" match="pi">
  <xsl:param name="ns"/>
  <xsl:processing-instruction name="{substring-before(.,' ')}">
    <xsl:value-of select="substring-after(.,' ')"/>
  </xsl:processing-instruction>
  <xsl:apply-templates select="following-sibling::node()[1]" mode="d:tree">
    <xsl:with-param name="ns" select="$ns"/>
  </xsl:apply-templates>
</xsl:template>



<xsl:template mode="d:tree" match="start">
  <xsl:param name="ns"/>
  <xsl:variable name="n" select="following-sibling::end[@s=current()/@s][1]"/>
  <xsl:variable name="xns" select="attrib/d:ns/namespace::*"/>
  <xsl:variable name="nns" select="($ns,$xns)"/>
<xsl:if test="@name='dx'">
</xsl:if>
  <xsl:element name="{@name}" 
    namespace="{$nns[name()=substring-before(current()/@name,':')]
                [last()][not(.='data:,dpc')]}">
  <xsl:copy-of select="attrib/(@*|$xns[not(.='data:,dpc')])"/>
  <xsl:apply-templates
  select="following-sibling::node()[1][not(. is $n)]" 
          mode="d:tree">
    <xsl:with-param name="ns" select="$nns"/>
  </xsl:apply-templates>
  </xsl:element>
  <xsl:apply-templates select="$n/following-sibling::node()[1]" mode="d:tree">
    <xsl:with-param name="ns" select="$ns"/>
  </xsl:apply-templates>
</xsl:template>

<!--
Old version without NS support
<xsl:template mode="d:tree" match="start">
  <xsl:variable name="n" select="following-sibling::end[@s=current()/@s][1]"/>
  <xsl:element name="{@name}" namespace="http://www.w3.org/1999/xhtml">
  <xsl:copy-of select="attrib/@*"/>
  <xsl:apply-templates 
        select="following-sibling::node()[1][not(. is $n)]" mode="d:tree"/>
  </xsl:element>
  <xsl:apply-templates select="$n/following-sibling::node()[1]" mode="d:tree"/>
</xsl:template>
-->


<xsl:variable name="d:ents">
  
  <entity name="Aacute">&#xC1;</entity>
  <entity name="aacute">&#xE1;</entity>
  <entity name="Acirc">&#xC2;</entity>
  <entity name="acirc">&#xE2;</entity>
  <entity name="acute">&#xB4;</entity>
  <entity name="AElig">&#xC6;</entity>
  <entity name="aelig">&#xE6;</entity>
  <entity name="Agrave">&#xC0;</entity>
  <entity name="agrave">&#xE0;</entity>
  <entity name="Aring">&#xC5;</entity>
  <entity name="aring">&#xE5;</entity>
  <entity name="Atilde">&#xC3;</entity>
  <entity name="atilde">&#xE3;</entity>
  <entity name="Auml">&#xC4;</entity>
  <entity name="auml">&#xE4;</entity>
  <entity name="brvbar">&#xA6;</entity>
  <entity name="Ccedil">&#xC7;</entity>
  <entity name="ccedil">&#xE7;</entity>
  <entity name="cedil">&#xB8;</entity>
  <entity name="cent">&#xA2;</entity>
  <entity name="copy">&#xA9;</entity>
  <entity name="curren">&#xA4;</entity>
  <entity name="deg">&#xB0;</entity>
  <entity name="divide">&#xF7;</entity>
  <entity name="Eacute">&#xC9;</entity>
  <entity name="eacute">&#xE9;</entity>
  <entity name="Ecirc">&#xCA;</entity>
  <entity name="ecirc">&#xEA;</entity>
  <entity name="Egrave">&#xC8;</entity>
  <entity name="egrave">&#xE8;</entity>
  <entity name="ETH">&#xD0;</entity>
  <entity name="eth">&#xF0;</entity>
  <entity name="Euml">&#xCB;</entity>
  <entity name="euml">&#xEB;</entity>
  <entity name="frac12">&#xBD;</entity>
  <entity name="frac14">&#xBC;</entity>
  <entity name="frac34">&#xBE;</entity>
  <entity name="Iacute">&#xCD;</entity>
  <entity name="iacute">&#xED;</entity>
  <entity name="Icirc">&#xCE;</entity>
  <entity name="icirc">&#xEE;</entity>
  <entity name="iexcl">&#xA1;</entity>
  <entity name="Igrave">&#xCC;</entity>
  <entity name="igrave">&#xEC;</entity>
  <entity name="iquest">&#xBF;</entity>
  <entity name="Iuml">&#xCF;</entity>
  <entity name="iuml">&#xEF;</entity>
  <entity name="laquo">&#xAB;</entity>
  <entity name="macr">&#xAF;</entity>
  <entity name="micro">&#xB5;</entity>
  <entity name="middot">&#xB7;</entity>
  <entity name="nbsp">&#xA0;</entity>
  <entity name="not">&#xAC;</entity>
  <entity name="Ntilde">&#xD1;</entity>
  <entity name="ntilde">&#xF1;</entity>
  <entity name="Oacute">&#xD3;</entity>
  <entity name="oacute">&#xF3;</entity>
  <entity name="Ocirc">&#xD4;</entity>
  <entity name="ocirc">&#xF4;</entity>
  <entity name="Ograve">&#xD2;</entity>
  <entity name="ograve">&#xF2;</entity>
  <entity name="ordf">&#xAA;</entity>
  <entity name="ordm">&#xBA;</entity>
  <entity name="Oslash">&#xD8;</entity>
  <entity name="oslash">&#xF8;</entity>
  <entity name="Otilde">&#xD5;</entity>
  <entity name="otilde">&#xF5;</entity>
  <entity name="Ouml">&#xD6;</entity>
  <entity name="ouml">&#xF6;</entity>
  <entity name="para">&#xB6;</entity>
  <entity name="plusmn">&#xB1;</entity>
  <entity name="pound">&#xA3;</entity>
  <entity name="raquo">&#xBB;</entity>
  <entity name="reg">&#xAE;</entity>
  <entity name="sect">&#xA7;</entity>
  <entity name="shy">&#xAD;</entity>
  <entity name="sup1">&#xB9;</entity>
  <entity name="sup2">&#xB2;</entity>
  <entity name="sup3">&#xB3;</entity>
  <entity name="szlig">&#xDF;</entity>
  <entity name="THORN">&#xDE;</entity>
  <entity name="thorn">&#xFE;</entity>
  <entity name="times">&#xD7;</entity>
  <entity name="Uacute">&#xDA;</entity>
  <entity name="uacute">&#xFA;</entity>
  <entity name="Ucirc">&#xDB;</entity>
  <entity name="ucirc">&#xFB;</entity>
  <entity name="Ugrave">&#xD9;</entity>
  <entity name="ugrave">&#xF9;</entity>
  <entity name="uml">&#xA8;</entity>
  <entity name="Uuml">&#xDC;</entity>
  <entity name="uuml">&#xFC;</entity>
  <entity name="Yacute">&#xDD;</entity>
  <entity name="yacute">&#xFD;</entity>
  <entity name="yen">&#xA5;</entity>
  <entity name="yuml">&#xFF;</entity>
  
  
  <entity name="bdquo">&#x201E;</entity>
  <entity name="circ">&#x2C6;</entity>
  <entity name="Dagger">&#x2021;</entity>
  <entity name="dagger">&#x2020;</entity>
  <entity name="emsp">&#x2003;</entity>
  <entity name="ensp">&#x2002;</entity>
  <entity name="euro">&#x20AC;</entity>
  <entity name="gt">&#x3E;</entity>
  <entity name="ldquo">&#x201C;</entity>
  <entity name="lrm">&#x200E;</entity>
  <entity name="lsaquo">&#x2039;</entity>
  <entity name="lsquo">&#x2018;</entity>
  <entity name="lt">&#38;#60;</entity>
  <entity name="mdash">&#x2014;</entity>
  <entity name="ndash">&#x2013;</entity>
  <entity name="OElig">&#x152;</entity>
  <entity name="oelig">&#x153;</entity>
  <entity name="permil">&#x2030;</entity>
  <entity name="quot">&#x22;</entity>
  <entity name="rdquo">&#x201D;</entity>
  <entity name="rlm">&#x200F;</entity>
  <entity name="rsaquo">&#x203A;</entity>
  <entity name="rsquo">&#x2019;</entity>
  <entity name="sbquo">&#x201A;</entity>
  <entity name="Scaron">&#x160;</entity>
  <entity name="scaron">&#x161;</entity>
  <entity name="thinsp">&#x2009;</entity>
  <entity name="tilde">&#x2DC;</entity>
  <entity name="Yuml">&#x178;</entity>
  <entity name="zwj">&#x200D;</entity>
  <entity name="zwnj">&#x200C;</entity>
  
  
  <entity name="alefsym">&#x2135;</entity>
  <entity name="Alpha">&#x391;</entity>
  <entity name="alpha">&#x3B1;</entity>
  <entity name="and">&#x2227;</entity>
  <entity name="ang">&#x2220;</entity>
  <entity name="asymp">&#x2248;</entity>
  <entity name="Beta">&#x392;</entity>
  <entity name="beta">&#x3B2;</entity>
  <entity name="bull">&#x2022;</entity>
  <entity name="cap">&#x2229;</entity>
  <entity name="Chi">&#x3A7;</entity>
  <entity name="chi">&#x3C7;</entity>
  <entity name="clubs">&#x2663;</entity>
  <entity name="cong">&#x2245;</entity>
  <entity name="crarr">&#x21B5;</entity>
  <entity name="cup">&#x222A;</entity>
  <entity name="dArr">&#x21D3;</entity>
  <entity name="darr">&#x2193;</entity>
  <entity name="Delta">&#x394;</entity>
  <entity name="delta">&#x3B4;</entity>
  <entity name="diams">&#x2666;</entity>
  <entity name="empty">&#x2205;</entity>
  <entity name="Epsilon">&#x395;</entity>
  <entity name="epsilon">&#x3B5;</entity>
  <entity name="equiv">&#x2261;</entity>
  <entity name="Eta">&#x397;</entity>
  <entity name="eta">&#x3B7;</entity>
  <entity name="exist">&#x2203;</entity>
  <entity name="fnof">&#x192;</entity>
  <entity name="forall">&#x2200;</entity>
  <entity name="frasl">&#x2044;</entity>
  <entity name="Gamma">&#x393;</entity>
  <entity name="gamma">&#x3B3;</entity>
  <entity name="ge">&#x2265;</entity>
  <entity name="hArr">&#x21D4;</entity>
  <entity name="harr">&#x2194;</entity>
  <entity name="hearts">&#x2665;</entity>
  <entity name="hellip">&#x2026;</entity>
  <entity name="image">&#x2111;</entity>
  <entity name="infin">&#x221E;</entity>
  <entity name="int">&#x222B;</entity>
  <entity name="Iota">&#x399;</entity>
  <entity name="iota">&#x3B9;</entity>
  <entity name="isin">&#x2208;</entity>
  <entity name="Kappa">&#x39A;</entity>
  <entity name="kappa">&#x3BA;</entity>
  <entity name="Lambda">&#x39B;</entity>
  <entity name="lambda">&#x3BB;</entity>
  <entity name="lang">&#x2329;</entity>
  <entity name="lArr">&#x21D0;</entity>
  <entity name="larr">&#x2190;</entity>
  <entity name="lceil">&#x2308;</entity>
  <entity name="le">&#x2264;</entity>
  <entity name="lfloor">&#x230A;</entity>
  <entity name="lowast">&#x2217;</entity>
  <entity name="loz">&#x25CA;</entity>
  <entity name="minus">&#x2212;</entity>
  <entity name="Mu">&#x39C;</entity>
  <entity name="mu">&#x3BC;</entity>
  <entity name="nabla">&#x2207;</entity>
  <entity name="ne">&#x2260;</entity>
  <entity name="ni">&#x220B;</entity>
  <entity name="notin">&#x2209;</entity>
  <entity name="nsub">&#x2284;</entity>
  <entity name="Nu">&#x39D;</entity>
  <entity name="nu">&#x3BD;</entity>
  <entity name="oline">&#x203E;</entity>
  <entity name="Omega">&#x3A9;</entity>
  <entity name="omega">&#x3C9;</entity>
  <entity name="Omicron">&#x39F;</entity>
  <entity name="omicron">&#x3BF;</entity>
  <entity name="oplus">&#x2295;</entity>
  <entity name="or">&#x2228;</entity>
  <entity name="otimes">&#x2297;</entity>
  <entity name="part">&#x2202;</entity>
  <entity name="perp">&#x22A5;</entity>
  <entity name="Phi">&#x3A6;</entity>
  <entity name="phi">&#x3D5;</entity>
  <entity name="Pi">&#x3A0;</entity>
  <entity name="pi">&#x3C0;</entity>
  <entity name="piv">&#x3D6;</entity>
  <entity name="Prime">&#x2033;</entity>
  <entity name="prime">&#x2032;</entity>
  <entity name="prod">&#x220F;</entity>
  <entity name="prop">&#x221D;</entity>
  <entity name="Psi">&#x3A8;</entity>
  <entity name="psi">&#x3C8;</entity>
  <entity name="radic">&#x221A;</entity>
  <entity name="rang">&#x232A;</entity>
  <entity name="rArr">&#x21D2;</entity>
  <entity name="rarr">&#x2192;</entity>
  <entity name="rceil">&#x2309;</entity>
  <entity name="real">&#x211C;</entity>
  <entity name="rfloor">&#x230B;</entity>
  <entity name="Rho">&#x3A1;</entity>
  <entity name="rho">&#x3C1;</entity>
  <entity name="sdot">&#x22C5;</entity>
  <entity name="Sigma">&#x3A3;</entity>
  <entity name="sigma">&#x3C3;</entity>
  <entity name="sigmaf">&#x3C2;</entity>
  <entity name="sim">&#x223C;</entity>
  <entity name="spades">&#x2660;</entity>
  <entity name="sub">&#x2282;</entity>
  <entity name="sube">&#x2286;</entity>
  <entity name="sum">&#x2211;</entity>
  <entity name="sup">&#x2283;</entity>
  <entity name="supe">&#x2287;</entity>
  <entity name="Tau">&#x3A4;</entity>
  <entity name="tau">&#x3C4;</entity>
  <entity name="there4">&#x2234;</entity>
  <entity name="Theta">&#x398;</entity>
  <entity name="theta">&#x3B8;</entity>
  <entity name="thetasym">&#x3D1;</entity>
  <entity name="trade">&#x2122;</entity>
  <entity name="uArr">&#x21D1;</entity>
  <entity name="uarr">&#x2191;</entity>
  <entity name="upsih">&#x3D2;</entity>
  <entity name="Upsilon">&#x3A5;</entity>
  <entity name="upsilon">&#x3C5;</entity>
  <entity name="weierp">&#x2118;</entity>
  <entity name="Xi">&#x39E;</entity>
  <entity name="xi">&#x3BE;</entity>
  <entity name="Zeta">&#x396;</entity>
  <entity name="zeta">&#x3B6;</entity>

</xsl:variable>

<xsl:key name="d:ents" match="entity" use="@name"/>

</xsl:stylesheet>

14.

Embed and don't escape xml in html

Evan Lenz


I am writing a stylesheet which outputs HTML.  My stylesheet pulls in a
chunk of XML from an XML file and then stuffs it within the HTML <body>
element.  Here's what I want my stylesheet to generate:

<html>
   <body>
       <pre>
            -- XML chunk here (tags not escaped so they will display
in a browser) --
       </pre>
   </body>
</html>

When I drop the resulting HTML into a browser I want the XML chunk to
display, including the tags. 

Evan Lenz has a tidy solution for this at xmlportfolio.com