XML to HTML transformation

Is it possible to transform XML data islands to HTML? Every example of XSLT that I can find works on a pure XML file, but I want to use XML data islands embedded in HTML.

For example, suppose I have a website with many pages, I want to put a title bar at the top of each page. I want a consistent look on each page, but don’t want to have to keep rewriting the HTML every time. Also I want a footer at the end of each page showing information.

the page might be roughly like this:

<HTML>
<HEAD><TITLE>My wonderful web page</TITLE></HEAD>
<BODY>
<XML ID=TOP>
<PAGE_TITLE> Welcome</PAGE_TITLE>
</XML>
Welcome to my wonderful web site.
Blah Blah blah, lots of text
A few images. Some more chat.
General HTML text.
<XML ID=END>
<FOOTER>
<LOGIN_NAME>Clive Jones</LOGIN_NAME>
<LOGIN TIME>11:15 AM</LOGIN TIME>
</FOOTER>
</XML>
</BODY>
</HTML>

Could some kind soul show me an example of how to transform this XML into HTML, please.

The header (as an example) could become

<TABLE><TR bgcolor=orange>
<TD><IMG source=“start.gif”></TD>
<TD><font size=5>Welcome</font></TD>
<TD><IMG source=“end.gif”></TD>
</TR></TABLE>

and the footer could be

<TABLE><TR>
<TD bgcolor=orange> <font size=2>logged in as: </TD>
<TD bgcolor=orange> <font size=2><b>clive Jones</b> </TD>
<TD bgcolor=orange> <font size=2>at </TD>
<TD bgcolor=orange> <font size=2></b>11:15 Am</b> </TD>
</TR></TABLE>

I’m no expert, but it strikes me you’ll need some kind of intermediary scripting between the XML and the HTML. Far better, surely, to have the repeating HTML elements stored as external files, and use something like PHP both to include the HTML, and to interpret the XML and deliver it up as HTML?

See that thing at the top that says HTML? That’s a signal that everything that follows is formatting instructions.

Well first, by using XML data islands, youre making sure that only people with IE are going to see that content. If thats Ok with you fine, you just need to know that in case you didnt.

Second, this is not a good use of XML. If you want to have one header/footer for multiple pages, you use include files. Pretty much all app servers that Im aware of, such as ASP, .Net, JSP, Cold Fusion, Perl, PHP, Python, all have mechanisms for including chunks of code the way you wish. If you dont or cant use any of these for some reason, see if your web server is running apache and if server side includes is enabled. Once you have the mechanism for including files, theres no need for the XML; just paste the html code you want in the header (or footer) onto a blank file and name it whatever you want (you may or may not need it to have an html extension depending on the app server you use). The exact code youll put in your main html file to call the include files will differ depending on the app server.

By the way; HTML, if well formed, ~is~ XML. In your case, theres no reason to put it in XML then back to HTML.

You can handle this transformation using XSLT provided that the HTML part is written as well-formed XML (e.g., close off all those <p> nodes with </p>, write empty nodes like IMG as <IMG src="…"/>. If it’s not in that form, use a program like Tidy to convert the HTML to well-formed XML.

Here’s the transform to convert your header section:

<?xml version=“1.0” encoding=“utf-8”?>
<xsl:stylesheet xmlns:xsl=“http://www.w3.org/1999/XSL/Transform
version=“1.0”>

<xsl:output method=“html”/>

<xsl:template match="/">
<xsl:apply-templates/>
</xsl:template>

<xsl:template match=“XML[PAGE_TITLE]”>
<!-- Match an XML element that has a PAGE_TITLE child -->
<TABLE>
<TR bgcolor=orange>
<TD><IMG source=“start.gif”></TD>
<TD>
<font size=5>
<xsl:copy-of select=“PAGE_TITLE/* | PAGE_TITLE/test()”/>
</font>
</TD>
<TD><IMG source=“end.gif”></TD>
</TR>
</TABLE>
</xsl:template>
<xsl:template select="|text()|comment()">
<!-- Default - just copy the HTML nodes -->
<xsl:copy>
<xsl:copy-of select="@
"/>
<xsl:apply-templates select="*|text()"/>
</xsl:copy>
</xsl:template>

</xsl:stylesheet>

Perhaps I didn’t make myself clear. I don’t want one header for multiple pages, I want each page to have its own header. But I want to make sure that all headers are formatted the same. So, I want to have the page title stored as data in each page, and the formatting instructions stored seperately.

By the way, this IS an ASP application i’m writing. It involves dynamically generated web pages, based on information read from a database. now, I can use VBScript to transform the RecordSet into an HTML table, but that’s rather tedious. My database has support for XML, its capable of returning the results of my SP as well-formed XML. I want to put the XML into the middle of the HTML, then use a stylesheet to transform it into HTML. I can do this transformation with a pure XML file, now I want to do it with XML data islands. And if I can’t, I wanna know why not.

sure there’s a reason… suppose my web site has 100 pages. I could do the HTML for each page, then later if I want to change the appearence of my website, go back and re-do every one of those 100 pages. But I think it would be less tedious to have it so that I only have one file to change.

Persaonlly, if youre just concerned about formatting, Id use CSS, buuut Ok.

You have a few choices. You can use your html template as the source xml file and transform it with something like ChordedZithers template (though I havent seen a ‘template select’ before, is that a typo?). Going that route Id probably write the xsl a bit different, but its not a major deal.

Or, you can write something like this, that has most of the basic html markup in the xsl template itself. Since Im assuming the title info and content would be associated together for the pages they go to, it would make sense that the title info and content are at the least siblings. Also, PAGE_TITLE is confusing, as its really the header, and not the title. Personally, Id pass the username and current time in your footer as a parameter to the xsl.

Sample xml feed (just an example):

<XML>
<PAGE_HEADER>Welcome</PAGE_HEADER>
<PAGE_CONTENT>
Welcome to my wonderful web site.
Blah Blah blah, lots of text
A few images. Some more chat.
General HTML text.
</PAGE_CONTENT>
</XML>

Sample xsl:

<?xml version=‘1.0’?>
<xsl:stylesheet xmlns:xsl=‘http://www.w3.org/1999/XSL/Transform’ version=‘1.0’>

<!-- output as xml to preserve the well-formedness and readability -->
<xsl:output method=“xml” omit-xml-declaration=“yes” indent=“yes”/>

<!-- default the user and time to empty just in case -->
<xsl:param name=“user” select=""/>
<xsl:param name=“time” select=""/>

<xsl:template match="/">
<HTML>
<HEAD><TITLE>My wonderful web page</TITLE></HEAD>
<BODY>
<xsl:apply templates select=“PAGE_HEADER”/>
<xsl:copy-of select=“PAGE_CONTENT”/>
<xsl:apply templates select=“PAGE_FOOTER”/>
</BODY>
</HTML>
</xsl:template>

<!-- ideally these would be in a seperate, imported xsl file -->
<xsl:template match=“PAGE_HEADER”>
<TABLE>
<TR bgcolor=“orange”>
<TD><IMG source=“start.gif” /></TD>
<TD>
<font size=“5”>
<xsl:value-of select="."/>
</font>
</TD>
<TD><IMG source=“end.gif” /></TD>
</TR>
</TABLE>
</xsl:template>

<xsl:template match=“PAGE_FOOTER”>
<TABLE>
<TR bgcolor=“orange”>
<TD> <font size=“2”>logged in as: </TD>
<TD> <font size=“2”><strong><xsl:value-of select="$user"/></strong></TD>
<TD> <font size=“2”>at </TD>
<TD> <font size=“2”><strong><xsl:value-of select="$time"/></strong></TD>
</TR></TABLE>
</xsl:template>

</xsl:stylesheet>
The advantage to using either this or ChordedZithers template is you can cache the result. If you cache though you need to make sure the username and time are passed as params.

If you are really hell bent on using data islands, you have to use javascript, as the client has to do the parsing, and this is basically how its done:

====the html page=============================
<HTML>
<HEAD>
<TITLE>My wonderful web page</TITLE>
<script type=“text/javascript”>
function transformMe(){
var StyleOb = new ActiveXObject(“MSXML2.DOMDocument.3.0”);
StyleOb.async = false;

        	StyleOb.load("header.xsl");
	document.all('header').innerHTML = TOP.transformNode(StyleOb);
        	StyleOb.load("footer.xsl");
	document.all('footer').innerHTML = END.transformNode(StyleOb);
            StyleOb = null;
}
onload = transformMe;

</script>
</HEAD>
<BODY>
<XML ID=“TOP”>
<PAGE_TITLE>Welcome</PAGE_TITLE>
</XML>
<div id=“header”>
</div>
Welcome to my wonderful web site.
Blah Blah blah, lots of text
A few images. Some more chat.
General HTML text.
<XML ID=“END”>
<FOOTER>
<LOGIN_NAME>Clive Jones</LOGIN_NAME>
<LOGIN_TIME>11:15 AM</LOGIN_TIME>
</FOOTER>
</XML>
<div id=“footer”>
</div>
</BODY>
</HTML>

=====header.xsl=============================
<?xml version=‘1.0’?>
<xsl:stylesheet xmlns:xsl=‘http://www.w3.org/1999/XSL/Transform’ version=‘1.0’>

<!-- output as xml to preserve the well-formedness and readability -->
<xsl:output method=“xml” omit-xml-declaration=“yes” indent=“yes”/>
<xsl:template match=“PAGE_TITLE”>
<TABLE>
<TR bgcolor=“orange”>
<TD><IMG source=“start.gif” /></TD>
<TD><font size=“5”><xsl:value-of select="."/></font></TD>
<TD><IMG source=“end.gif” /></TD>
</TR>
</TABLE>
</xsl:template>
</xsl:stylesheet>

=====footer.xsl==================================
<?xml version=‘1.0’?>
<xsl:stylesheet xmlns:xsl=‘http://www.w3.org/1999/XSL/Transform’ version=‘1.0’>
<!-- output as xml to preserve the well-formedness and readability -->
<xsl:output method=“xml” omit-xml-declaration=“yes” indent=“yes”/>
<xsl:template match="/">
<TABLE>
<TR bgcolor=“orange”>
<TD> <font size=“2”>logged in as:</font> </TD>
<TD> <font size=“2”><strong><xsl:value-of select=“FOOTER/LOGIN_NAME”/></strong></font></TD>
<TD> <font size=“2”>at </font></TD>
<TD> <font size=“2”><strong><xsl:value-of select=“FOOTER/LOGIN_TIME”/></strong></font></TD>
</TR>
</TABLE>
</xsl:template>
</xsl:stylesheet>

Hope this helps.

Yes, that should have been “match”.

I will say, though ,that I also agree with the sentiments expressed by Voodoochile and Peter Morris that, were I writing this application, I would have the application generate XML containing the core data to go onto the page, then use XSLT to transform that core data into an HTML document, and I would leave detailed, non-structural formatting issues (fonts, colors, etc.) to a CSS file.

Exactly what CZither said; he describes the standard approach. Using that approach, you can then cache the output from various transformations with various caching mechanisms. If youre just using a 2-tier thingy, database to xml on one tier, transform and serve on another, depending on how often the data changes youd want to cache the xml on the 2nd tier as well as the result of the transforms on the server tier. You can cache stuff for a minute or a year, its all up to how much load youre going to have, how often the data changes, etc. Ram is cheaper than processors. Ideally youd have 3-tier; 1 - database, 2 - machine pulling from dbase and rendering xml, 3 - front end servers calling the xml and transforming then serving the pages (though about half the time youd want to do the transform on the middle tier, cache it, and just have the server call the result).

Thanks for your advice, I’ve got it working now.