XSLT question

Discussion in 'XML' started by bobiron, Oct 18, 2006.

  1. bobiron

    bobiron Guest

    Hi, any ideas to improve the above ugly and not efficient code?
    Thanks
    Roberto

    <!-- source XML
    NOTE: elements "col" changes from source to source
    -->
    <?xml version="1.0"?>
    <resultset>
    <header>
    <col name="#" path="position()" />
    <col name="NAME" path="@NAME"/>
    <col nome="field 1" path="FIELD_1/text()" />
    <col nome="field 2" path="FIELD_2/text()" />
    </header>
    <items>
    <item NAME="name1">
    <FIELD_1>8</FIELD_1>
    <FIELD_2>5</FIELD_2>
    <FIELD_3 />
    </item>
    <item NAME="name2">
    <FIELD_1>9</FIELD_1>
    <FIELD_2>4</FIELD_2>
    <FIELD_3 />
    </item>
    </items>
    </resultset>

    <!-- XSL -->
    <?xml version="1.0"?>
    <xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="/">
    <html>
    <head/>
    <body>
    <table border="1">
    <tr>
    <xsl:for-each select="resultset/header/col">
    <th><xsl:value-of select="@name"/></th>
    </xsl:for-each>
    </tr>
    <xsl:for-each select="resultset/items/item">
    <tr>
    <th><xsl:value-of select="position()"/></th>
    <xsl:variable name="v_item" select="."/>
    <xsl:for-each select="/resultset/header/col">
    <xsl:choose>
    <xsl:when test="@path = '@NAME'" >
    <td><xsl:value-of select="$v_item/@NAME"/></td>
    </xsl:when>
    <xsl:when test="@path = 'FIELD_1/text()'">
    <td><xsl:value-of select="$v_item/FIELD_1/text()"/></td>
    </xsl:when>
    <xsl:when test="@path = 'FIELD_2/text()'">
    <td><xsl:value-of select="$v_item/FIELD_2/text()"/></td>
    </xsl:when>
    <xsl:when test="@path = 'FIELD_3/text()'">
    <td><xsl:value-of select="$v_item/FIELD_3/text()"/></td>
    </xsl:when>
    </xsl:choose>
    </xsl:for-each>
    </tr>
    </xsl:for-each>
    </table>
    </body>
    </html>
    </xsl:template>
    </xsl:stylesheet>
    bobiron, Oct 18, 2006
    #1
    1. Advertising

  2. bobiron wrote:
    > Hi, any ideas to improve the above ugly and not efficient code?
    > Thanks
    > Roberto



    -- source --

    <?xml version="1.0"?>
    <resultset>
    <header>
    <col name="#" path="position()" />
    <col name="NAME" path="@NAME"/>
    <col name="field 1" path="FIELD_1/text()" />
    <col name="field 2" path="FIELD_2/text()" />
    </header>
    <items>
    <item NAME="name1">
    <FIELD_1>F11</FIELD_1>
    <FIELD_2>F21</FIELD_2>
    <FIELD_3>F31</FIELD_3>
    </item>
    <item NAME="name2">
    <FIELD_1>F12</FIELD_1>
    <FIELD_2>F22</FIELD_2>
    <FIELD_3>F32</FIELD_3>
    </item>
    <item>
    <FIELD_1>F13</FIELD_1>
    <FIELD_2>F23</FIELD_2>
    <FIELD_4>F43</FIELD_4>
    </item>
    </items>
    </resultset>


    -- transform --

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

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

    <xsl:template match="resultset">
    <table border="1">
    <xsl:apply-templates/>
    </table>
    </xsl:template>

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

    <xsl:template match="col">
    <th>
    <xsl:value-of select="@name"/>
    </th>
    </xsl:template>

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

    <xsl:template match="item">
    <tr>
    <th>
    <xsl:value-of select="count(preceding-sibling::*) + 1"/>
    </th>
    <td>
    <!-- We need this cell whether @NAME is present or not -->
    <xsl:value-of select="@NAME"/>
    </td>
    <!-- Assumes that the names of children are unknown -->
    <xsl:apply-templates select="*"/>
    </tr>
    </xsl:template>

    <!-- Assumes that the names of children are unknown -->
    <xsl:template match="item/*">
    <!-- Check that there is a col element whose @path begins with the name
    of the current item/* -->
    <xsl:if test="//col[starts-with(@path, name(current()))]">
    <td>
    <!-- The @path of the col element is not evaluated. To do this
    we need
    to use extension functions or make two XSLT passes. -->
    <xsl:apply-templates/>
    </td>
    </xsl:if>
    </xsl:template>

    </xsl:stylesheet>


    -- result --

    <html>
    <head>
    <META http-equiv="Content-Type" content="text/html;
    charset=UTF-8"></head>
    <body>
    <table border="1">

    <tr>

    <th>#</th>
    <th>NAME</th>
    <th>field 1</th>
    <th>field 2</th>

    </tr>


    <tr>
    <th>1</th>
    <td>name1</td>
    <td>F11</td>
    <td>F21</td>
    </tr>

    <tr>
    <th>2</th>
    <td>name2</td>
    <td>F12</td>
    <td>F22</td>
    </tr>

    <tr>
    <th>3</th>
    <td></td>
    <td>F13</td>
    <td>F23</td>
    </tr>


    </table>
    </body>
    </html>
    Magnus Henriksson, Oct 19, 2006
    #2
    1. Advertising

  3. bobiron

    Guest

    bobiron wrote:
    > Hi, any ideas to improve the above ugly and not efficient
    > code?


    [ugly XSLT]

    I'm not sure about efficiency, but yes, it is ugly. I would
    do something like:

    <xsl:stylesheet
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    version="1.0">
    <xsl:eek:utput method="xml"/>
    <xsl:template match="/">
    <xsl:variable
    name="header"
    select="resultset/header/col"/>
    <html>
    <body>
    <table>
    <thead>
    <xsl:apply-templates
    select="$header"
    mode="header"/>
    </thead>
    <tbody>
    <xsl:apply-templates
    select="resultset/items/item"
    mode="items">
    <xsl:with-param
    name="format"
    select="$header"/>
    </xsl:apply-templates>
    </tbody>
    </table>
    </body>
    </html>
    </xsl:template>
    <xsl:template match="col" mode="header">
    <th>
    <xsl:value-of select="@name"/>
    </th>
    </xsl:template>
    <xsl:template match="col" mode="item">
    <xsl:param name="data"/>
    <xsl:param name="pos"/>
    <td>
    <xsl:choose>
    <xsl:when test="@path='position()'">
    <xsl:value-of select="$pos"/>
    </xsl:when>
    <xsl:when test="starts-with(@path,'@')">
    <xsl:value-of
    select=
    "
    $data/@*
    [
    name()=substring-after(current()/@path,'@')
    ]
    "/>
    </xsl:when>
    <xsl:when test="substring-after(@path,'/')='text()'">
    <xsl:value-of
    select=
    "
    $data/*
    [
    name()=substring-before(current()/@path,'/')
    ]
    "/>
    </xsl:when>
    </xsl:choose>
    </td>
    </xsl:template>
    <xsl:template match="item" mode="items">
    <xsl:param name="format"/>
    <tr>
    <xsl:apply-templates
    select="$format"
    mode="item">
    <xsl:with-param name="data" select="."/>
    <xsl:with-param name="pos" select="position()"/>
    </xsl:apply-templates>
    </tr>
    </xsl:template>
    </xsl:stylesheet>

    --
    Pavel Lepin
    , Oct 19, 2006
    #3
  4. bobiron

    bobiron Guest

    With a very little changes, a friend of mine, have found this
    solution. I guess a nice solution!

    xml:

    <?xml version="1.0"?>
    <resultset>
    <header>
    <col name="#" path="position()" />
    <col name="NAME" path="NAME"/>
    <col name="field 1" path="FIELD_1" />
    <col name="field 2" path="FIELD_2" />
    </header>
    <items>
    <item NAME="name1">
    <FIELD_1>F11</FIELD_1>
    <FIELD_2>F21</FIELD_2>
    <FIELD_3>F31</FIELD_3>
    </item>
    <item NAME="name2">
    <FIELD_1>F12</FIELD_1>
    <FIELD_2>F22</FIELD_2>
    <FIELD_3>F32</FIELD_3>
    </item>
    <item NAME="name3">
    <FIELD_1>F13</FIELD_1>
    <FIELD_2>F23</FIELD_2>
    <FIELD_4>F43</FIELD_4>
    </item>
    </items>
    </resultset>

    xsl:

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

    <xsl:template match="/">
    <html>
    <body>
    <table border="1">
    <tr>
    <xsl:for-each select="resultset/header/col">
    <th><xsl:value-of select="@name"/></th>
    </xsl:for-each>
    </tr>
    <xsl:for-each select="resultset/items/item">
    <tr>
    <xsl:variable name="row" select="."/>
    <th><xsl:value-of select="position()"/></th>
    <xsl:for-each select="/resultset/header/col">
    <xsl:variable name="xpath" select="@path"/>
    <xsl:if test="$xpath != 'position()'" >
    <td><xsl:value-of select="($row/* | $row/@*)[name() =
    $xpath]"/></td>
    </xsl:if>
    </xsl:for-each>
    </tr>
    </xsl:for-each>
    </table>
    </body>
    </html>
    </xsl:template>
    </xsl:stylesheet>

    Regards, Roberto
    bobiron, Oct 26, 2006
    #4
  5. bobiron

    Guest

    bobiron wrote:
    > With a very little changes, a friend of mine, have found
    > this solution. I guess a nice solution!


    > <?xml version="1.0"?>
    > <xsl:stylesheet version="1.0"
    > xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    >
    > <xsl:template match="/">
    > <html>
    > <body>
    > <table border="1">
    > <tr>
    > <xsl:for-each select="resultset/header/col">
    > <th><xsl:value-of select="@name"/></th>
    > </xsl:for-each>
    > </tr>
    > <xsl:for-each select="resultset/items/item">
    > <tr>
    > <xsl:variable name="row" select="."/>
    > <th><xsl:value-of select="position()"/></th>
    > <xsl:for-each select="/resultset/header/col">
    > <xsl:variable name="xpath" select="@path"/>
    > <xsl:if test="$xpath != 'position()'" >
    > <td><xsl:value-of select="($row/* | $row/@*)
    > [name() = $xpath]"/></td>
    > </xsl:if>
    > </xsl:for-each>
    > </tr>
    > </xsl:for-each>
    > </table>
    > </body>
    > </html>
    > </xsl:template>
    > </xsl:stylesheet>


    Whatever floats your boat, but I'd say you were asking
    your question on the wrong newsgroup then. That would be
    more appropriate in alt.write.only.code.bork.bork.bork or
    something like that.

    --
    Pavel Lepin
    , Oct 26, 2006
    #5
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Stylus Studio
    Replies:
    0
    Views:
    658
    Stylus Studio
    Aug 3, 2004
  2. Benjamin Hillsley
    Replies:
    3
    Views:
    1,681
    Dimitre Novatchev
    Sep 25, 2003
  3. ted
    Replies:
    1
    Views:
    622
    Laurens
    Jan 26, 2004
  4. Replies:
    2
    Views:
    719
    Henry S. Thompson
    Oct 19, 2005
  5. Replies:
    18
    Views:
    2,756
    Joseph Kesselman
    Oct 4, 2006
Loading...

Share This Page