1
votes

I need to concat/filter a number of XHTML files based upon an XML index file containing a reference to the root name of each XHTML file. The XSLT stylesheet is applied on the XML index file.

I validated the process with XML files instead of XHTML files.

But when I use XHTML files instead of XML files the document() instruction applied to my XHTML files returns nothing.

According to posts I read on the forum, this is probable a problem of namespaces but I did not manage to make it work according to what I understood.

In the XSLT file, I added : xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://www.w3.org/1999/xhtml" and the h: prefixes thinking it would help but it did not. My understanding is this area is very little at this stage.

I copied the full header of the actual XHTML files in the example used below : mails.xhml.

Thank you for help.

The XML index file :

<?xml version="1.0" encoding="UTF-8"?>

<mail_list>
    <file name="mailx.xhtml" />
    ...
</mail_list>

The mailx.xhtml file model :

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <style xmlns:xhtml="http://www.w3.org/1999/xhtml" type="text/css" xml:space="preserve"/>
        <meta content="text/html; charset=us-ascii" http-equiv="Content-Type" />
    </head>

    <body class="entry">
        <p class="name">first_name last_name</p>
        <p class="address">[email protected]</p>
    </body>
</html

Ths XSLT file :

<?xml version="1.0" encoding="UTF-8"?>

<xsl:stylesheet version="2.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://www.w3.org/1999/xhtml"

exclude-result-prefixes="h">

<xsl:output method="xml"/>
<xsl:template match="/">
    <xsl:for-each select="/mail_list/file">
        <xsl:apply-templates select="document(@name)/h:entry" />
    </xsl:for-each>
</xsl:template>

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

<xsl:template match="h:name">Name: <xsl:value-of select="." />
</xsl:template>

<xsl:template match="h:address">Email Address: <xsl:value-of select="." />
</xsl:template>
</xsl:stylesheet>
1
Simply use <xsl:copy-of select="document(@name)"/> to check whether the document functions loads the document. As for selecting elements in the XHTML namespace, neither XHTML as defined by the W3C nor your sample has any elements named entry or name or address, you only have elements with a class attribute value of e.g. entry`. - Martin Honnen
<xsl:copy-of select="document(@name)"/> was successful and your questioning was absolutely correct. Thank you Martin. Here below Mads provided the full correction. - Bin31

1 Answers

0
votes

You are matching on h:entry but that file does not have any elements named entry.

There is a <body class="entry"> which is a body element with a @class attribute with a value of entry that is a child of the h:html element: /h:html/h:body[@class='entry']

So, change

<xsl:apply-templates select="document(@name)/h:html/h:body[@class='entry']" />

or more generically:

<xsl:apply-templates select="document(@name)//*[@class='entry']" />

And then change:

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

to either:

<xsl:template match="h:body[@class='entry']">
    <xsl:apply-templates />
</xsl:template>

or more generically:

<xsl:template match="*[@class='entry']">
    <xsl:apply-templates />
</xsl:template>

The same applies to the templates matching h:name and h:address instead of elements that have @class values.

When I run the following stylesheet:

<xsl:stylesheet version="2.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns="http://www.w3.org/1999/xhtml"
    xmlns:h="http://www.w3.org/1999/xhtml"
    
    exclude-result-prefixes="h">
    
    <xsl:output method="xml"/>
    <xsl:template match="/">
        <xsl:for-each select="/mail_list/file">
            <xsl:apply-templates select="document(@name)//*[@class='entry']" />
        </xsl:for-each>
    </xsl:template>
    
    <xsl:template match="*[@class='entry']">
        <xsl:apply-templates />
    </xsl:template>
    
    <xsl:template match="*[@class='name']">Name: <xsl:value-of select="." />
    </xsl:template>
    
    <xsl:template match="*[@class='address']">Email Address: <xsl:value-of select="." />
    </xsl:template>
</xsl:stylesheet>

against an input XML file that has the mailx.xhtml in the same directory, it produces the following output:

<?xml version="1.0" encoding="UTF-8"?>Name: first_name last_nameEmail Address: [email protected]