    <rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:admin="http://webns.net/mvcb/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:content="http://purl.org/rss/1.0/modules/content/">
     <channel>
        <title>ACCU  :: Transforming XML with XSLT</title>
        <link>https://members.accu.org/index.php/articles/311</link>
        <description>Professionalism in Programming</description>
        <dc:language>en-us</dc:language> 
        <dc:creator>Administrator</dc:creator> 
        <admin:generatorAgent rdf:resource="http://www.xaraya.org" /> 
        <admin:errorReportsTo rdf:resource="mailto:webeditor@accu.org" />
       <sy:updatePeriod>hourly</sy:updatePeriod>
       <sy:updateFrequency>1</sy:updateFrequency>
       <docs>http://backend.userland.com/rss</docs>




<div class="xar-mod-head"><span class="xar-mod-title">Programming Topics + Overload Journal #60 - Apr 2004</span></div>

<table border="0" cellpadding="1" cellspacing="0">
    <tbody>
    <tr>
        <td valign="top">
            Browse in :
       </td>
       <td valign="top">

                                            <a href="https://members.accu.org/index.php/articles/">All</a>

                     &gt;                         <a href="https://members.accu.org/index.php/articles/c13/">Topics</a>

                     &gt;                         <a href="https://members.accu.org/index.php/articles/c65/">Programming</a>
<br />

                                            <a href="https://members.accu.org/index.php/articles/">All</a>

                     &gt;                         <a href="https://members.accu.org/index.php/articles/c76/">Journals</a>

                     &gt;                         <a href="https://members.accu.org/index.php/articles/c78/">Overload</a>

                     &gt;                         <a href="https://members.accu.org/index.php/articles/c152/">60</a>
<br />

                                            <a href="https://members.accu.org/index.php/articles/c65-152/">Any of these categories</a>

                    -                        <a href="https://members.accu.org/index.php/articles/c65+152/">All of these categories</a>
<br />
</td>
   </tr>
   </tbody>
</table>




<div class="xar-error">
   <p>
 <strong>Note:</strong> when you create a new publication type,
the articles module will automatically use the templates
<em>user-display-[publicationtype].xt</em>
and <em>user-summary-[publicationtype].xt</em>.
If those templates do not exist when you try to preview or display a new article,
you'll get this warning :-)  Please place your own templates in themes/<em>yourtheme</em>/modules/articles . The templates will get the extension .xt there. </p>
</div>
<div class="xar-norm xar-standard-box-padding">
   <h1><strong>Title:</strong>&nbsp;Transforming XML with XSLT</h1>
<p><strong>Author:</strong>&nbsp;</p>
<p>
<strong>Date:</strong> 02 April 2004 22:54:59 +01:00 or Fri, 02 April 2004 22:54:59 +01:00</p>
<p><strong>Summary:</strong>&nbsp;</p>
<p><strong>Body:</strong>&nbsp;<div class="sect1" lang="en">
<div class="titlepage">
<h2><a name="d0e19" id="d0e19"></a></h2>
</div>
<p>David Nash's article in C Vu of October 2003 covered reading XML
data into a program. Here, I hope to introduce newcomers to
manipulating XML with XSLT scripts, using an example drawn from
that article.</p>
</div>
<div class="sect1" lang="en">
<div class="titlepage">
<h2><a name="d0e23" id="d0e23"></a>What Is
It?</h2>
</div>
<p>Simply stated, XML is portable, self-describing data structured
as a tree of named nodes, each possibly containing named
attributes, text, and sub-nodes. It may already be the most popular
way to bridge systems built using disparate technologies. XSLT
stands for eXtensible Stylesheet Language for Transformations. The
<span class="emphasis"><em>stylesheet</em></span> part concerns the
presentation of XML ('pure content'), but that's about all I have
to say about that. The fact that <span class=
"emphasis"><em>transformations</em></span> are part of XSLT shows
the W3C's recognition of the need for manipulation, as well as
presentation, of XML content.</p>
<p>If you ever accidentally opened an XML file in a Microsoft
environment, you might have been surprised to see a collapsible
tree view like that in Figure 1. That is produced by the web
browser using a built in XSL transform which converts the data to
HTML, and is perhaps the most widespread example of using XSLT to
adapt input for a pre-existing parser. (It's also handy way for
looking at non-trivial XML files.)</p>
<div class="figure"><a name="d0e36" id="d0e36"></a>
<p class="title c2">Figure 1. XSLT used to render XML as HTML</p>
<div class="mediaobject c3"><img src="/var/uploads/journals/resources/rahman-fig1.png"
align="middle" alt="XSLT used to render XML as HTML"></div>
</div>
<p>An XSL transform is itself valid XML, usually stored in a file
with the extension &quot;.xsl&quot; and commonly called an XSL script.
Programs that execute XSL scripts against XML data are called XSLT
processors (see 'Tools' below). Modern integrated development
environments (IDEs) often contain a built in XSLT processor to
support rapid prototyping of transforms. For example in IBM's
Websphere IDE you can view two XML files side by side and point
&amp; click to specify how the source data should map to the
destination - and the IDE will create a transform for you.</p>
</div>
<div class="sect1" lang="en">
<div class="titlepage">
<h2><a name="d0e44" id="d0e44"></a>What Can I Do
With It?</h2>
</div>
<p>Although XML is rapidly becoming the preferred mechanism for
data sharing, the XML that one system produces might not be
structured precisely the way all of its consumers expect, despite
containing the needed information<sup>[<a name="d0e49" href=
"#ftn.d0e49" id="d0e49">1</a>]</sup>. For example, David's article
shows a C++ program that can read personal data like <tt class=
"filename">person.xml</tt>, shown below.</p>
<pre class="programlisting">
&lt;?xml version=&quot;1.0&quot;?&gt;
&lt;Person&gt;
&lt;FirstName&gt;Elvis&lt;/FirstName&gt;
&lt;LastName&gt;Presley&lt;/LastName&gt;
&lt;DateOfBirth&gt;
&lt;Year&gt;1935&lt;/Year&gt;
&lt;Month&gt;01&lt;/Month&gt;
&lt;Day&gt;08&lt;/Day&gt;
&lt;/DateOfBirth&gt;
&lt;/Person&gt;
</pre>
<p>Assume today you build and debug a parser to read person.xml.
What if tomorrow you're confronted with the need to read personal
information from a new source which structures its data slightly
differently? For example, consider flatperson.xml, which contains
the same information as person.xml but more concisely<sup>[<a name=
"d0e60" href="#ftn.d0e60" id="d0e60">2</a>]</sup>:</p>
<pre class="programlisting">
&lt;?xml version=&quot;1.0&quot;?&gt;
&lt;flatperson firstname=&quot;Elvis&quot;
            surname=&quot;Presley&quot; dob=&quot;19350108&quot; /&gt;
</pre>
<p>Often, as I hope to show here, an XSLT script can save you
having to touch your parser code by adapting the new data:</p>
<pre class="programlisting">
$ xsltproc expand.xsl flatperson.xml
&lt;?xml version=&quot;1.0&quot;?&gt;
&lt;Person&gt;
  &lt;FirstName&gt;Elvis&lt;/FirstName&gt;
  &lt;LastName&gt;Presley&lt;/LastName&gt;
  &lt;DateOfBirth&gt;
    &lt;Year&gt;1935&lt;/Year&gt;
    &lt;Month&gt;01&lt;/Month&gt;
    &lt;Day&gt;08&lt;/Day&gt;
  &lt;/DateOfBirth&gt;
&lt;/Person&gt;
</pre>
<p>This article guides the novice in stages to construct scripts
like <tt class="filename">expand.xsl</tt> (and its converse,
<tt class="filename">flatten.xsl</tt>) which can interconvert
between a <tt class="literal">flatperson</tt> and a <tt class=
"literal">Person</tt>.</p>
<p>Naturally, if your system produces output for others, you can be
sure that the XML structure it uses internally will not perfectly
match the format expected by each potential consumer. Here, a set
of XSLT scripts can adapt that internal representation for each
consumer. The classic example of this is a web portal that
transforms XML into browser- or device- specific markup as a final
stage of request processing. (Despite the ECMAScript standard,
browsers still have their quirks in the way they handle web
content.)</p>
</div>
<div class="sect1" lang="en">
<div class="titlepage">
<h2><a name="d0e86" id="d0e86"></a>Tools</h2>
</div>
<p>XSLT processors are available in many flavours just like XML
parsers. They typically provide an API allowing you to incorporate
a transformation capability into a program, as well as a command
line wrapper for experimenting with. By default, a processor will
interpret scripts (for rapid prototyping), but can also be told to
precompile them for performance. I often use the Cygwin environment
which includes Gnome's <tt class="literal">libxslt</tt> and its
<tt class="literal">xsltproc</tt> command (which we have seen in
action above). My JDK installation includes the Apache
Xalan<sup>[<a name="d0e97" href="#ftn.d0e97" id=
"d0e97">3</a>]</sup> processor, so I could achieve the same effect
thus:</p>
<pre class="screen">
$ java org.apache.xalan.xslt.Process -XSL expand.xsl -IN flatperson.xml
</pre>
<p>See Resources at end for pointers where you can download these.
I use <tt class="literal">xsltproc</tt> in this article for
brevity.</p>
</div>
<div class="sect1" lang="en">
<div class="titlepage">
<h2><a name="d0e111" id="d0e111"></a>How Does a
Transform Work?</h2>
</div>
<p>An XSL script has a top-level <tt class=
"literal">xsl:transform</tt> element typically containing a number
of 'functions' that you write, having the job of operating on some
part of the input XML to produce some part of the output data.
These 'functions' are embodied in <tt class=
"literal">xsl:template</tt> elements and can be written
declaratively and/or imperatively, depending on how you want them
to be invoked. By default a template will just copy any text it
contains to the output when called; however templates also have at
their disposal rich data manipulation and control flow constructs
similar to those lurking in your favourite programming
languages.</p>
<p>The XSLT processor treats the input XML data as a tree of nodes,
each of which has an associated path (a route, by name, down the
tree to that node). The processor starts at the top of this tree
(path: &quot;<tt class="literal">/</tt>&quot;) then searches the transform
script for a template matching the current path (via the template's
<tt class="literal">match=&quot;...&quot;</tt> attribute ).</p>
<p>If the processor finds a matching template, it invokes it. What
happens next depends on how the template is coded. E.g. it could
imperatively call other templates as part of its processing, just
like a C function can call other functions.</p>
<p>If no user-supplied template matches the root node, a &quot;default
template&quot; is invoked, which prints out the text of the current node
then recursively traverses its descendants. This is the effect of
transforming <tt class="filename">person.xml</tt> using an 'empty'
XSL transform (one containing no user templates):</p>
<pre class="screen">
$ xsltproc empty.xsl person.xml
  Elvis
  Presley
    1935
    1
    8
</pre></div>
<div class="sect1" lang="en">
<div class="titlepage">
<h2><a name="d0e139" id="d0e139"></a>Hello...</h2>
</div>
<p>Time for a concrete example<sup>[<a name="d0e144" href=
"#ftn.d0e144" id="d0e144">4</a>]</sup>. This is the <tt class=
"filename">hello.xsl</tt> script, containing one simple
template.</p>
<pre class="programlisting">
&lt;?xml version=&quot;1.0&quot;?&gt;
&lt;xsl:transform xmlns:xsl=&quot;http://www.w3.org/1999/XSL/Transform&quot; version=&quot;1.0&quot;&gt;
&lt;xsl:output method=&quot;text&quot;/&gt;
&lt;xsl:template match=&quot;/&quot;&gt; Hello World
&lt;/xsl:template&gt;
&lt;/xsl:transform&gt;
</pre>
<p>Don't worry too much about the packaging - focus on the single
<tt class="literal">xsl:template</tt> element. You'll often see
scripts with a template declared to match &quot;<tt class=
"literal">/</tt>&quot; whose job is simply to invoke other templates in
the desired order, a role akin to a <tt class=
"function">main()</tt> function. Our template is less ambitious,
doing its work with no help.</p>
<p>Two things to note are: (1) The <tt class="literal">match</tt>
attribute declares its intention to be called in the context of the
root input node and (2) It just ignores the input data and outputs
the greeting we've all grown to love, with a nod to Kernighan &amp;
Ritchie.</p>
<p>This shows <tt class="filename">hello.xsl</tt> being applied to
<tt class="filename">person.xml</tt> on the command line.</p>
<pre class="screen">
$ xsltproc hello.xsl person.xml 
Hello World
</pre>
<p>As you can see, the contents of <tt class=
"filename">person.xml</tt> don't figure in the output - all we see
is the greeting.</p>
<p>So, we've seen one script blindly copy all text from its input
to the output and another ignoring its input altogether. Time for
something with a bit more intent behind it.</p>
</div>
<div class="sect1" lang="en">
<div class="titlepage">
<h2><a name="d0e186" id="d0e186"></a>Personal
Hello</h2>
</div>
<p>When manipulating XML you generally want your templates to read
parts of the input structure and create output with a structure
more suitable for your purposes. Let me introduce the <tt class=
"literal">xsl:value-of</tt> tag, which is a bit like the SQL
<tt class="literal">select</tt> statement, as it returns the value
of some specified aspect of the data. You specify what you want to
retrieve, in its <tt class="literal">select</tt> attribute, with a
path (i.e. a particular route to a particular node in the input
tree).</p>
<p>For example, in our <tt class="literal">hello</tt> template we
could query the <tt class="literal">Person</tt>'s first name with
the path <tt class="literal">/Person/FirstName</tt>. To upgrade
<tt class="filename">hello.xsl</tt> so it greets the right person
on first name terms, replace the text <tt class=
"literal">World</tt> with the tag <tt class=
"literal">&lt;xsl:value-of
select=&quot;/Person/FirstName&quot;/&gt;</tt>.</p>
<p>This shows the resulting script <tt class=
"filename">personal.xsl</tt> and its effect on our <tt class=
"literal">Person</tt> data.</p>
<pre class="programlisting">
$ cat personal.xsl
&lt;?xml version=&quot;1.0&quot;?&gt;
&lt;xsl:transform xmlns:xsl=&quot;http://www.w3.org/1999/XSL/Transform&quot; version=&quot;1.0&quot; &gt;
  &lt;xsl:output method=&quot;text&quot;/&gt;
  &lt;xsl:template match=&quot;/&quot; &gt;
    Hello &lt;xsl:value-of select=&quot;/Person/FirstName&quot;/&gt;
  &lt;/xsl:template&gt;
&lt;/xsl:transform&gt;
</pre>
<pre class="screen">
$ xsltproc personal.xsl person.xml
Hello Elvis
</pre></div>
<div class="sect1" lang="en">
<div class="titlepage">
<h2><a name="d0e232" id="d0e232"></a>Expand an
Attribute</h2>
</div>
<p>We're nearing the original goal of converting <tt class=
"literal">flatperson</tt> data to <tt class="literal">Person</tt>
data (for which, hypothetically, we have a preexisting parser). New
aspects to this are: A <tt class="literal">flatperson</tt> holds
its information in attributes (like <tt class=
"literal">firstname</tt>) which the 'expanding' transform must
read; and the output must contain XML elements (like <tt class=
"literal">FirstName</tt>) encapsulating this information, rather
than plain text like &quot;<tt class="literal">Hello ...</tt>&quot;.</p>
<p>We can reference an attribute (in <tt class=
"literal">xsl:value-of</tt> and elsewhere) using <tt class=
"literal">@&lt;AttributeName&gt;</tt> in a path. For example a
<tt class="literal">flatperson</tt>'s first name has the path
&quot;<tt class="literal">/flatperson/@firstname</tt>&quot;. (This has a
modicum of charm, I confess.)</p>
<p>Creating XML structure in the output is achieved by simply
embedding XML tags in the template body.</p>
<p>This shows the script <tt class="filename">expandfirst.xsl</tt>
and how it partly reconstitutes a <tt class=
"literal">flatperson</tt> to a <tt class="literal">Person</tt> (for
brevity, it only reconstitutes the first name).</p>
<pre class="programlisting">
$ cat expandfirst.xsl
&lt;?xml version=&quot;1.0&quot;?&gt;
&lt;xsl:transform xmlns:xsl=&quot;http://www.w3.org/1999/XSL/Transform&quot; version=&quot;1.0&quot; &gt;
  &lt;xsl:output indent=&quot;yes&quot; /&gt;
  &lt;xsl:template match=&quot;/&quot; &gt;
    &lt;Person&gt;
      &lt;FirstName&gt;
        &lt;xsl:value-of select=&quot;/flatperson/@firstname&quot;/&gt;
      &lt;/FirstName&gt;
    &lt;/Person&gt;
  &lt;/xsl:template&gt;
&lt;/xsl:transform&gt;
</pre>
<pre class="screen">
$ xsltproc expandfirst.xsl flatperson.xml
&lt;?xml version=&quot;1.0&quot;?&gt;
&lt;Person&gt;
&lt;FirstName&gt;Elvis&lt;/FirstName&gt;
&lt;/Person&gt;
</pre>
<p>(Note the <tt class="literal">xsl:output</tt> tag tells the
processor what kind of output is expected. Without the <tt class=
"literal">method=&quot;text&quot;</tt> attribute, the processor defaults to
emitting an <tt class="literal">&lt;?xml..?&gt;</tt> header .
Without the indent attribute, redundant whitespace like newlines
would not be added, leading to slightly leaner output at the
expense of readability.)</p>
</div>
<div class="sect1" lang="en">
<div class="titlepage">
<h2><a name="d0e297" id="d0e297"></a>Flatten an
Element</h2>
</div>
<p>For completeness let's look at the reverse direction. The
<tt class="literal">xsl:attribute</tt> tag can inject an attribute
into an output XML element. To illustrate, here is <tt class=
"filename">flattenfirst.xsl</tt>, the 'inverse' of <tt class=
"filename">expandfirst.xsl</tt>. It takes a <tt class=
"literal">Person</tt> on input and outputs a minimal <tt class=
"literal">flatperson</tt> containing just the first name:</p>
<pre class="programlisting">
$ cat flattenfirst.xsl
&lt;?xml version=&quot;1.0&quot;?&gt;
&lt;xsl:transform xmlns:xsl=&quot;http://www.w3.org/1999/XSL/Transform&quot; version=&quot;1.0&quot; &gt;
  &lt;xsl:template match=&quot;/&quot; &gt;
    &lt;flatperson&gt;
      &lt;xsl:attribute name=&quot;firstname&quot;&gt;
        &lt;xsl:value-of select=&quot;/Person/FirstName&quot;/&gt;
      &lt;/xsl:attribute&gt;
    &lt;/flatperson&gt;
  &lt;/xsl:template&gt;
&lt;/xsl:transform&gt;
</pre>
<pre class="screen">
$ xsltproc flattenfirst.xsl person.xml
&lt;?xml version=&quot;1.0&quot;?&gt;
&lt;flatperson firstname=&quot;Elvis&quot;/&gt;
</pre>
<p>(Note that all <tt class="literal">xsl:attribute</tt> tags must
precede other content for an element. You might see why if you
consider where attributes would end up in the output in relation
to, say subelements.)</p>
</div>
<div class="sect1" lang="en">
<div class="titlepage">
<h2><a name="d0e326" id="d0e326"></a>Completing
the Scripts</h2>
</div>
<p>Within the context of a <tt class="literal">flatperson</tt>, the
path &quot;<tt class="literal">/flatperson/@dob</tt>&quot; refers to the
<tt class="literal">dob</tt> attribute whose value (for Elvis) is
&quot;19350108&quot;. The function <tt class="function">substring()</tt> can
pick out individual parts so we can populate the <tt class=
"literal">Year</tt>, <tt class="literal">Month</tt> and <tt class=
"literal">Day</tt> elements of a reconstituted <tt class=
"literal">Person</tt>. For example this tag extracts the YYYY
digits of a <tt class="literal">flatperson</tt>'s <tt class=
"literal">dob</tt> attribute:</p>
<pre class="programlisting">
&lt;xsl:value-of select=&quot;substring(/flatperson/@dob,1,4)&quot;/&gt;
</pre>
<p>Armed with this, the hands-on reader is encouraged to upgrade
<tt class="filename">expandfirst.xsl</tt> into the script
<tt class="filename">expand.xsl</tt> which reconstitutes the whole
<tt class="literal">Person</tt> from a <tt class=
"literal">flatperson</tt>.</p>
<p>XSLT additionally provides access to a rich set of
string-related functions, including regular expressions. For
details see the Xquery and Xpath specifications (Resources).</p>
<p>Now, by default, the XSL processor merges a sequence of text
items into a single text item when creating an output node, so the
following would be one way to concatenate a <tt class=
"literal">Person</tt>'s <tt class="literal">DateOfBirth</tt>
sub-elements, for readers wishing to complete <tt class=
"filename">flattenfirst.xsl</tt>:</p>
<pre class="programlisting">
&lt;xsl:attribute name=&quot;dob&quot;&gt;
  &lt;xsl:value-of select=&quot;/Person/DateOfBirth/Year&quot;/&gt;
  &lt;xsl:value-of select=&quot;/Person/DateOfBirth/Month&quot;/&gt;
  &lt;xsl:value-of select=&quot;/Person/DateOfBirth/Day&quot;/&gt;
&lt;/xsl:attribute&gt;
</pre></div>
<div class="sect1" lang="en">
<div class="titlepage">
<h2><a name="d0e392" id=
"d0e392"></a>Conclusion</h2>
</div>
<p>Of course you can parse XML and navigate/manipulate the
resulting DOM tree using various languages. However XSLT was
specifically designed to transform XML so it supports working at a
higher level than SAX or DOM. Though transforming then parsing can
be slower than one-step parsing with a new parser, building and
debugging that new parser will often be overkill as a first port of
call when a simple XSLT script lets you reuse an existing parser.
Once you're happy with a script, you would typically dispense with
the command line interpreter in favour of programmatically invoking
a precompiled version of your script from your application.</p>
<p>I hope I have helped curious readers in their first few steps
with XSLT, with simple but self-contained examples, and shown how
relatively painlessly it can adapt XML data for a pre-existing
parser.</p>
</div>
<div class="sect1" lang="en">
<div class="titlepage">
<h2><a name="d0e399" id=
"d0e399"></a>Acknowledgements</h2>
</div>
<p>LOTS of people kindly read drafts! My thanks in particular to
Frederek Althoff, Phil Bass, Dr Islam Choudhury, Dr Trevor Hopkins
and Dirk Laessig for helpful feedback.</p>
</div>
<div class="bibliography">
<div class="titlepage">
<h2><a name="d0e404" id="d0e404"></a>References &amp;
Resources</h2>
</div>
<div class="bibliomixed">
<p class="bibliomixed">David Nash, &quot;Combining the STL with SAX and
Xpath for Effective XML Parsing&quot;, <span class="citetitle"><i class=
"citetitle">C Vu Volume 15 No 5</i></span> (October 2003,
pp.18-20)</p>
</div>
<div class="bibliomixed">
<p class="bibliomixed">Ivan Kiselev, <span class=
"citetitle"><i class="citetitle">Aspect Oriented Programming with
AspectJ</i></span>, SAMS Publishing.</p>
</div>
<div class="bibliomixed">
<p class="bibliomixed">Kernighan &amp; Richie, <span class=
"citetitle"><i class="citetitle">The C Programming
Language</i></span>, Prentice-Hall (The archetypal use of &quot;Hello
World&quot; to introduce a programming language.)</p>
</div>
<div class="bibliomixed">
<p class="bibliomixed"><span class="bibliomisc">XSLT specification
on the W3C site: <a href="http://tinyurl.com/2ewsm" target=
"_top">http://tinyurl.com/2ewsm</a></span></p>
</div>
<div class="bibliomixed">
<p class="bibliomixed"><span class="bibliomisc">Xpath/Xquery
functions/operators: <a href="http://tinyurl.com/2puva" target=
"_top">http://tinyurl.com/2puva</a></span></p>
</div>
<div class="bibliomixed">
<p class="bibliomixed"><span class="bibliomisc">Gnome project's
libxslt: <a href="http://xmlsoft.org/XSLT" target=
"_top">http://xmlsoft.org/XSLT</a></span></p>
</div>
<div class="bibliomixed">
<p class="bibliomixed"><span class="bibliomisc">Windows binary
distribution libxslt: <a href="http://tinyurl.com/2p9yt" target=
"_top">http://tinyurl.com/2p9yt</a></span></p>
</div>
<div class="bibliomixed">
<p class="bibliomixed"><span class="bibliomisc">Xalan-c at Apache
website: <a href="http://xml.apache.org/xalan-c" target=
"_top">http://xml.apache.org/xalan-c</a></span></p>
</div>
<div class="bibliomixed">
<p class="bibliomixed"><span class="bibliomisc">Sun have a Web
Services tutorial with a good intro to XML and XSLT: <a href=
"http://tinyurl.com/2572z" target=
"_top">http://tinyurl.com/2572z</a></span></p>
</div>
<div class="bibliomixed">
<p class="bibliomixed"><span class="bibliomisc">The newsgroup
<tt class="literal">comp.text.xml</tt> is full of helpful
stuff.</span></p>
</div>
<div class="bibliomixed">
<p class="bibliomixed"><span class="bibliomisc">Check <a href=
"http://cocoon.apache.org" target=
"_top">http://cocoon.apache.org</a> for an approach that heavily
uses XSLT for multi channel user interfaces.</span></p>
</div>
</div>
<div class="footnotes"><br>
<hr class="c4" width="100">
<div class="footnote">
<p><sup>[<a name="ftn.d0e49" href="#d0e49" id=
"ftn.d0e49">1</a>]</sup> See http://www.oasis-open.org for an
effort underway to change this situation.</p>
</div>
<div class="footnote">
<p><sup>[<a name="ftn.d0e60" href="#d0e60" id=
"ftn.d0e60">2</a>]</sup> Ivan Kiselev's soother for people (like
me) who find XML configuration files overly verbose for name-value
pairs: &quot;..any design decision is a compromise, some like it hot and
nobody's perfect&quot;.</p>
</div>
<div class="footnote">
<p><sup>[<a name="ftn.d0e97" href="#d0e97" id=
"ftn.d0e97">3</a>]</sup> In JDK 1.4 the Xalan classes live in
<tt class="literal">&lt;JAVA_HOME&gt;\jre\lib\rt.jar</tt>. In case
of classpath woes, try adding this jar to your classpath. If your
JDK precedes 1.4 you can download the Xalan classes (see
Resources).</p>
</div>
<div class="footnote">
<p><sup>[<a name="ftn.d0e144" href="#d0e144" id=
"ftn.d0e144">4</a>]</sup> I recommend installing one of the free
XSLT processors and trying out the examples.</p>
</div>
</div>
</p>
<p><strong>Notes:</strong>&nbsp;</p>
<p><em>More fields may be available via dynamicdata ..</em></p>
</div>
</channel>
</rss>
