Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I parse an HTML using XSLT?

Tags:

html

parsing

xslt

I have to parse a big HTML file, and Im only interested in a small section (a table). So I thought about using an XSLT to simplify/transform the HTML in something simpler that I could then easily process.

The problem Im having is that the is not finding my table. So I don't know if its even possible to parse HTML using a XSL stylesheet.

By the way, the HTML file has this look (schematic, missing tags):

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html id="ctl00_htmlDocumento" xmlns="http://www.w3.org/1999/xhtml" lang="es-ES" xml:lang="es-ES">
<div> some content </div>
<div class="NON_IMPORTANT"></div>
<div class="IMPORTANT_FATHER>
    <div class="IMPORTANT">
        <table>
            HERE IS THE DATA IM LOOKING FOR
        </table>
    </div>
</div>

as per request, here is my xsl

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:template match="tbody">
        tbody found, lets process it
    <xsl:for-each select="tr">
        new tf found, lets process it
    </xsl:for-each>
    </xsl:template>

</xsl:stylesheet>

The full HTML is quite big so I dont know how to present it here... I've tested for valid document on Oxygen, and it says its valid.

Thanks in advance. Gonso

like image 615
gonso Avatar asked Dec 14 '22 01:12

gonso


1 Answers

You're not using XPath correctly in your match attributes. You need the xmlns:xhtml="http://www.w3.org/1999/xhtml" attribute in your xsl:stylesheet element, and then you'll need to use the xhtml: prefix in your XPath expressions (you need a prefix; XPath does not obey default namespaces).

After this, you'll still get the problem that it will process everything else too. I don't know if there's a better solution to this, but I think you will need to explicitly process things on the path to the tbody element, something like

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

and the same thing for body and so on until you get to your tbody match.

XPath also supports more complex matching than just a specific child as above. For instance, matching the third child div tag can be done with

<xsl:template match="xhtml:div[3]">

and matching an element with a specific attribute with

<xsl:template match="xhtml:div[@class='IMPORTANT']">

Here the [] surrounds an additional condition that needs to be fulfilled for the element to be considered a match. A plain number means to index into the matches and take only the one that has that index (the indexing is 1-based), an @ sign precedes an attribute, but you can have arbitrarily complex XPath in there, so you can match pretty much any substructure you'd like.

like image 81
JaakkoK Avatar answered Dec 30 '22 08:12

JaakkoK