1
votes

"disable-output-escaping" is not supported in Firefox, I'm looking for another XSLT way to process the following XML file

<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="test.xsl"?>
<text>
<title>Any title</title>
<para>First para</para>
<para>Second para</para>
<para>Third para</para>
</text>

in order to produce an HTML file have a <div> box (with a blue border) around the content of all the <para> tags. The "bad" solution using "disable-output-escaping" is

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

<xsl:template match="/">

    <html>
    <head>
    </head>
    <body>
    <xsl:apply-templates/>
    <xsl:text disable-output-escaping="yes">&lt;/div></xsl:text>
    </body>
    </html>
</xsl:template>

<xsl:template match="title">
    <div style="border: 3px solid red;">
        <h1><xsl:value-of select="."/></h1>
    </div>
    <xsl:text disable-output-escaping="yes">&lt;div style="border: 3px solid blue></xsl:text>
</xsl:template>

<xsl:template match="para">
    <div style="border: 3px solid green;">
        <xsl:value-of select="."/>
    </div>
</xsl:template>

</xsl:stylesheet>

Any suggestion ?

2
It looks like you are trying to wrap consecutive para tags in a div. Will these para tags always be preceded by a title tag?Tim C
Yes, the &lt;para> tags are always preceded by only one &lt;title> tag ; moreover it could exist other tags, e.g. &lt;image> tags, "mixed" with the &lt;para> tags that should be included similarly in the &lt;div> tag.J.Richelle
I don't understand the problem here. Why can't you simply apply templates to the title, then open a div tag (in a "good" way), apply templates to all the other nodes, and close the div tag?michael.hor257k
I don't see how to apply the templates to all the other types of nodes (&lt;para>, &lt;image>, and possibly also others) without "invoquing" also the rule for &lt;title>, as it is the case with &lt;xsl:apply-templates/> ; I want to keep the order of the &lt;para>, &lt;image>, so I can't apply first the &lt;para> rule and next the &lt;image>, etc.J.Richelle
Do you have a list of all the possible "other types of nodes" you need to process? If not, how will you prepare templates to handle them?michael.hor257k

2 Answers

0
votes

This one is very simple.

<xsl:template match="/">
    <html>
    <body>
    <xsl:apply-templates select="title"/>
    <div>
       <xsl:apply-templates select="para"/>
    </div>
    </body>
    </html>
</xsl:template>

It gets more difficult if you have to process a sequence like

title para para title para para title para

For that the appropriate technique in XSLT 1.0 is "sibling recursion" - apply templates to the first child, and within the template for that child, apply templates to its first following sibling. Better, move to XSLT 2.0+ and use xsl:for-each-group. (In the browser, that requires a third-party processor such as Saxon-JS).

0
votes

I don't see how to apply the templates to all the other types of nodes

Quite simply:

<xsl:apply-templates select="*[not(self::title)]"/>

That is, make your first template:

<xsl:template match="/text">
    <html>
        <head/>
        <body>
            <xsl:apply-templates select="title"/>
            <div style="border: 3px solid blue;">
                <xsl:apply-templates select="*[not(self::title)]"/>
            </div>
        </body>
    </html>
</xsl:template>

then add the templates to handle title, para, image and any other node that may appear in the input.


Alternatively, if you have a list of all the nodes that can possibly appear in the input, apply templates to them explicitly:

<xsl:template match="/text">
    <html>
        <head/>
        <body>
            <xsl:apply-templates select="title"/>
            <div style="border: 3px solid blue;">
                <xsl:apply-templates select="para | image | other | another"/>
            </div>
        </body>
    </html>
</xsl:template>