xsl-list
[Top] [All Lists]

Re: [xsl] translate to XML using XSL into an HTML table

2007-08-03 19:22:27
Yes very enlighting and thank you for the much
unexpected reply! :)


--- Steve <subsume(_at_)gmail(_dot_)com> wrote:

Not to be ignored!

(even though I, being relatively new myself, know
its overwhelming.
you will see the light!)

On 8/3/07, Abel Braaksma <abel(_dot_)online(_at_)xs4all(_dot_)nl>
wrote:
Oryann,

You have already been helped very well with the
code below, but the
discussion stayed all around using the same
construct: xsl:for-each. You
stated that you are new to XSLT, so I take it that
you are not very
familiar with it. In a later post you say that you
are accustomed to
Perl, which is, as many general domain and
scripting languages, an
imperative language, where you are used to be in
charge yourself of
telling the compiler what to do and when, and XSLT
takes it just the
other way around.

Your approach below does exactly that: you layout
a table, and you use
for-each to tell the compiler (xslt processor) to
get a group of
elements and to do something with it. This is not
wrong on itself, but
if your code will grow, you will find yourself
having very complex and
hard to maintain structures, just like a nested
for/next and if/then
would give you in an imperative language (unless
you choose to use its
OO capabilities etc to get your code more
readable).

XSLT is a declarative / functional language. You
literally *declare*
what your output should look like based on a set
of rules, and then you
let the processor do the brainy stuff for you.
What you need to know is
that the processor will walk the input tree of XML
for you and you
declare templates where you say "if the processor
encounters node XYZ
create a TD tag" and "if the processor encounters
node ABC create a
TABLE tag". To control this flow, you can select
what nodes the
processor is allowed to process on a given
position.

To illustrate this approach, let's take your
example. Instead of writing
a for-each loop (it is not hard to imagine how
your code will look when
you need several tables inside one another, with
several for-each loops
etc), you can take the following approach, which
needs a little shift in
thinking (read along with the comment lines):

<xsl:template match="/">
    <!-- here comes your frameword for the html
page -->
    <html>
        <head>.....</head>
        .... etc ....
        <body>
             <!-- now we tell the processor what
main elements to grab -->
             <!-- these are children of the root
-->
             <xsl:apply-templates
select="PHONEBOOK" />
        </body>
     </body>
</xsl:template>

<!-- declaring the table, which starts for each
PHONEBOOK (only one) -->
<xsl:template match="PHONEBOOK">
      <!-- here comes the start of the table, you
could put it in the
main, but this keeps it cleaner -->
      <table border="3">
           <!-- table header -->
           <tr bgcolor="lightblue">
               <th>FirstName</th>
               <th>LastName</th>
               <th>Phone</th>
           </tr>
          <!-- here we say to the processor: take
these elements that we
want a rows -->
          <!-- I assume that you have added a
<member> around each
first/last/phone, though this is not necessary -->
          <xsl:apply-template select="MEMBER" />
      </table>
</xsl:template>

<!-- declaring the row, which the processor will
automatically select
for each MEMBER -->
<xsl:template match="MEMBER">
     <!-- here goes the row definition
            all is a client of MEMBER now -->
     <!-- an easy way to create a way so you can
point your browser
             to each member by its id or name
(IE), by using
http://yoururl/yourpath#memberID -->
     <xsl:variable name="id"><xsl:number
/></xsl:variable>
     <tr id="member-{$id}">
            <xsl:apply-templates select="FIRST |
LAST | PHONE" />
     </tr>
</xsl:template>

<!-- declare the cells, which is any node that is
a child of MEMBER -->
<xsl:template match="MEMBER/*">
     <!-- here we select the value of the current
node (.) -->
     <td><xsl:value-of select="." /></td>
</xsl:template>


Now, the above is finished. If you use that, you
will get a neatly
rendered table. Why is this better than the
previous approach? Suppose
that you want to but the text of the first name
(FIRST) into bold.

If you take your original approach, you would have
to add a <xsl:if>
statement, which would even more deeply indent the
already deeply nested
structure. In the new approach (the XSLT'ish
approach) all you need to
is make a specific exception for the FIRST nodes,
which you do by adding
an extra declaration, that is all. The processor
"knows" that it should
take the exception case, instead of the generic
case and will
automatically choose the correct declaration.

This is what I meant by: let the processor do the
thinking for you. This
is also the one point that many people find rather
daunting when
attacking XSLT at first, but once understood it
will make you go like
lightspeed!

Here's what you do, just add this to the code
above, and you are done:

<xsl:template match="FIRST">
     <td><b><xsl:value-of select="."></b><td>
</xsl:template>


These concepts are very well presented in Jeni
Tennison's tutorial
books. You can also check her website. Another
good starting point is
the XSLT Cookbook (consider the second edition
only) and Dave Pawson's
FAQ (search google for XSLT FAQ followed by your
query and you get
there). If you want to get a bit further on the
subject, you should
consider buying the authoritative definitive books
on XPath 2.0 and XSLT
2.0 by Michael Kay.

Hope it helps! Happy coding!

Cheers,
-- Abel Braaksma



      
____________________________________________________________________________________
Shape Yahoo! in your own image.  Join our Network Research Panel today!   
http://surveylink.yahoo.com/gmrs/yahoo_panel_invite.asp?a=7 



--~------------------------------------------------------------------
XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list
To unsubscribe, go to: http://lists.mulberrytech.com/xsl-list/
or e-mail: <mailto:xsl-list-unsubscribe(_at_)lists(_dot_)mulberrytech(_dot_)com>
--~--