473,387 Members | 1,453 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,387 software developers and data experts.

Do I have a bug, or am I pushing the limits of XSLT engines?

I am trying to convert an HTML table into a list of name-value pairs,
one pair per field in the table. I believe my XSLT is correct, but
I've tried both Xalan and Saxon, which both fail with different
results. Below I've listed my HTML input, my expected XML output, my
XSLT, and the actual output from both Saxon and Xalan. Thanks in
advance.

HTML Input
----------
<html>
<head/>
<body>
<table>
<tr>
<th>Field 1</th>
<th>Field 2</th>
</tr>
<tr>
<td>A</td>
<td>1</td>
</tr>
<tr>
<td>B</td>
<td>2</td>
</tr>
</table>
</body>
</html>

Expected XML Output
-------------------
<?xml version="1.0" encoding="UTF-8" ?>
<records>
<record>
<field>
<name>Field 1</name>
<value>A</value>
</field>
<field>
<name>Field 2</name>
<value>1</value>
</field>
</record>
<record>
<field>
<name>Field 1</name>
<value>B</value>
</field>
<field>
<name>Field 2</name>
<value>2</value>
</field>
</record>
</records>

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

<xsl:variable name="fields" select="//th" />

<xsl:template name="lookup-field">
<xsl:param name="at-index"/>
<xsl:value-of select="$fields[$at-index]" />
</xsl:template>

<xsl:template match="/html/body/table">
<records>
<xsl:apply-templates select="tr[td]"/>
</records>
</xsl:template>

<xsl:template match="tr[td]">
<record>
<xsl:for-each select="td">
<field>
<name>
<xsl:call-template name="lookup-field">
<xsl:with-param name="at-index">
<xsl:value-of select="position()"/>
</xsl:with-param>
</xsl:call-template>
</name>
<value>
<xsl:value-of select="."/>
</value>
</field>
</xsl:for-each>
</record>
</xsl:template>

</xsl:transform>

Actual Output From Saxon:
-------------------------
<?xml version="1.0" encoding="UTF-8" ?>
<records>
<record>
<field>
<name>Field 1</name>
<value>A</value>
</field>
<field>
<name>Field 1</name>
<value>1</value>
</field>
</record>
<record>
<field>
<name>Field 1</name>
<value>B</value>
</field>
<field>
<name>Field 1</name>
<value>2</value>
</field>
</record>
</records>

Actual Output From Xalan:
-------------------------
javax.xml.transform.TransformerException:
java.lang.NullPointerException
Jul 20 '05 #1
3 1616
In article <fa**************************@posting.google.com >, Mike Whittemore wrote:
I am trying to convert an HTML table into a list of name-value pairs,
one pair per field in the table. I believe my XSLT is correct, but
I've tried both Xalan and Saxon, which both fail with different
results. Below I've listed my HTML input, my expected XML output, my
XSLT, and the actual output from both Saxon and Xalan. Thanks in
advance.
[snipped most of helpful example]
<xsl:transform version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:variable name="fields" select="//th" />

<xsl:template name="lookup-field">
<xsl:param name="at-index"/>
<xsl:value-of select="$fields[$at-index]" />
</xsl:template>

<xsl:template match="/html/body/table">
<records>
<xsl:apply-templates select="tr[td]"/>
</records>
</xsl:template>

<xsl:template match="tr[td]">
<record>
<xsl:for-each select="td">
<field>
<name>
<xsl:call-template name="lookup-field">
<xsl:with-param name="at-index">
<xsl:value-of select="position()"/>
</xsl:with-param>
Replace the above three lines with

<xsl:with-param name="at-index" select="position()"/>

What you have sets the param to a result tree fragment. You need to set the param
to a number, so that in the called template $at-index evaluates to a number.
</xsl:call-template>
</name>
<value>
<xsl:value-of select="."/>
</value>
</field>
</xsl:for-each>
</record>
</xsl:template>

</xsl:transform>

Jul 20 '05 #2
ag*****@earl-grey.cloud9.net (A. Bolmarcich) wrote in message news:<slrnc9di56.e5e.ag*****@earl-grey.cloud9.net>...
In article <fa**************************@posting.google.com >, Mike Whittemore wrote:
I am trying to convert an HTML table into a list of name-value pairs,
one pair per field in the table. I believe my XSLT is correct, but
I've tried both Xalan and Saxon, which both fail with different
results. Below I've listed my HTML input, my expected XML output, my
XSLT, and the actual output from both Saxon and Xalan. Thanks in
advance.


[snipped most of helpful example]
<xsl:transform version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:variable name="fields" select="//th" />

<xsl:template name="lookup-field">
<xsl:param name="at-index"/>
<xsl:value-of select="$fields[$at-index]" />
</xsl:template>

<xsl:template match="/html/body/table">
<records>
<xsl:apply-templates select="tr[td]"/>
</records>
</xsl:template>

<xsl:template match="tr[td]">
<record>
<xsl:for-each select="td">
<field>
<name>
<xsl:call-template name="lookup-field">
<xsl:with-param name="at-index">
<xsl:value-of select="position()"/>
</xsl:with-param>


Replace the above three lines with

<xsl:with-param name="at-index" select="position()"/>

What you have sets the param to a result tree fragment. You need to set the param
to a number, so that in the called template $at-index evaluates to a number.
</xsl:call-template>
</name>
<value>
<xsl:value-of select="."/>
</value>
</field>
</xsl:for-each>
</record>
</xsl:template>

</xsl:transform>


Thanks for your response. That worked perfectly for the Saxon and
Microsoft engines, but I still get a null pointer exception from the
Xalan engine. I suppose this show's it is a good idea to test your XSL
transformations on multiple engines if you want them to increase the
chances of them being portable. Below I've posted a different solution
that works for all 3 engines mentioned. I'm still new at this, so if
you spot a more elegant solution I'd appreciate seeing it. Thanks
again.

"Portable" XSLT Solution:
-------------------------
<xsl:transform version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:template match="/html/body/table">
<records>
<xsl:apply-templates select="tr[td]"/>
</records>
</xsl:template>

<xsl:template match="tr[td]">
<record>
<xsl:for-each select="td">
<field>
<name>
<xsl:variable name="pos" select="position()"
/>
<xsl:value-of select="/descendant::th[$pos]"/>
</name>
<value>
<xsl:value-of select="."/>
</value>
</field>
</xsl:for-each>
</record>
</xsl:template>

</xsl:transform>

PS. I'm not sure why I need to assign position() to a variable first,
but without doing it this way it was always equating to "1".
Jul 20 '05 #3
mi****************@baesystems.com (Mike Whittemore) wrote in message news:<fa**************************@posting.google. com>...
ag*****@earl-grey.cloud9.net (A. Bolmarcich) wrote in message news:<slrnc9di56.e5e.ag*****@earl-grey.cloud9.net>...
In article <fa**************************@posting.google.com >, Mike Whittemore wrote:
I am trying to convert an HTML table into a list of name-value pairs,
one pair per field in the table. I believe my XSLT is correct, but
I've tried both Xalan and Saxon, which both fail with different
results. Below I've listed my HTML input, my expected XML output, my
XSLT, and the actual output from both Saxon and Xalan. Thanks in
advance.


[snipped most of helpful example]
<xsl:transform version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:variable name="fields" select="//th" />

<xsl:template name="lookup-field">
<xsl:param name="at-index"/>
<xsl:value-of select="$fields[$at-index]" />
</xsl:template>

<xsl:template match="/html/body/table">
<records>
<xsl:apply-templates select="tr[td]"/>
</records>
</xsl:template>

<xsl:template match="tr[td]">
<record>
<xsl:for-each select="td">
<field>
<name>
<xsl:call-template name="lookup-field">
<xsl:with-param name="at-index">
<xsl:value-of select="position()"/>
</xsl:with-param>


Replace the above three lines with

<xsl:with-param name="at-index" select="position()"/>

What you have sets the param to a result tree fragment. You need to set the param
to a number, so that in the called template $at-index evaluates to a number.
</xsl:call-template>
</name>
<value>
<xsl:value-of select="."/>
</value>
</field>
</xsl:for-each>
</record>
</xsl:template>

</xsl:transform>


Thanks for your response. That worked perfectly for the Saxon and
Microsoft engines, but I still get a null pointer exception from the
Xalan engine. I suppose this show's it is a good idea to test your XSL
transformations on multiple engines if you want them to increase the
chances of them being portable. Below I've posted a different solution
that works for all 3 engines mentioned. I'm still new at this, so if
you spot a more elegant solution I'd appreciate seeing it. Thanks
again.

"Portable" XSLT Solution:
-------------------------
<xsl:transform version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:template match="/html/body/table">
<records>
<xsl:apply-templates select="tr[td]"/>
</records>
</xsl:template>

<xsl:template match="tr[td]">
<record>
<xsl:for-each select="td">
<field>
<name>
<xsl:variable name="pos" select="position()"
/>
<xsl:value-of select="/descendant::th[$pos]"/>
</name>
<value>
<xsl:value-of select="."/>
</value>
</field>
</xsl:for-each>
</record>
</xsl:template>

</xsl:transform>

PS. I'm not sure why I need to assign position() to a variable first,
but without doing it this way it was always equating to "1".


My last post on this. I switched from using the version of Xalan (2.2)
that shipped with my JVM, to the latest 2.6. After reading the Xalan
FAQ to figure out how to override the default version of Xalan, I ran
my test and it succeeded. Thanks again for the help.
Jul 20 '05 #4

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

1
by: WindAndWaves | last post by:
Hi Gurus How do I provide links that search engines can follow if my site is created in PHP and MySql and I always put the session ID in the link (header)? Are there any special tricks? ...
0
by: R. Rajesh Jeba Anbiah | last post by:
Q: Is PHP search engine friendly? Q: Will search engine spiders crawl my PHP pages? A: Spiders should crawl anything provided they're accessible. Since, nowadays most of the websites are been...
2
by: ted | last post by:
Was wondering if XSLT alone is appropriate for the following situation. From XML, I'm creating a small website (around 50 pages) with pages that link to each other through a nav menu and a...
2
by: Tom Corcoran | last post by:
I am working to ease updating of a html page by transforming 2 xml files. I was going to use xslt for this and had bought 2 unopened books, wrox xslt and o'reilly's xslt cookbook. But am now...
5
by: Mike Judkins | last post by:
I'm looking for examples of websites (preferably large and well known companies, not personal sites or developer-to-developer sites) that use XML and XSLT as a technology platform from which to...
8
by: Soren Kuula | last post by:
Hi, everyone, I'm beginning work on my Master's thesis in computer science ... I will start out with a pretty advanced, not yet published algorithm for computing quite accurate control flow...
64
by: Manfred Kooistra | last post by:
I am building a website with identical content in four different languages. On a first visit, the search engine determines the language of the content by the IP address of the visitor. What the...
3
by: Andy Dingley | last post by:
>From a thread over in c.i.w.a.h "RFC: From XHTML to HTML via XSLT" http://groups.google.co.uk/group/comp.infosystems.www.authoring.html/msg/f112c230061ffe86 As is well-known, the XSLT HTML...
13
by: Josip | last post by:
I'm trying to limit a value stored by object (either int or float): class Limited(object): def __init__(self, value, min, max): self.min, self.max = min, max self.n = value def...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.