solardb
solardb

Reputation: 21

XSL Template-match replace element

I have scoured the forums and and still not clear on this. I'm very new to the topic.

I have HTML output that is being sent to a browser email client (Outlook). Outlook overwrites the characteristics of the <p> tag and introduces large spacing.

I would like to set up a template-match to replace all <p> tags with <div> or <span>.

For complicated reasons which will not be addressed in this post, I cannot stop the HTML from being rendered with <p> tags in it.

So lets say that I have:

<p xmlns="http://www.w3.org/1999/xhtml">
   <span>Some text</span>
</p>

I would want the output to be

<span>Some text</span>

with the <p> tags removed.

If I have

<p xmlns="http://www.w3.org/1999/xhtml">
  <b>Some other text</b>
</p>

then I would be happy with either:

<b>Some other text</b>

or

<span>
   <b>Some other text</b>
</span>

Just as long as it gets rid of the <p> tags.

It would also need to recognize <p> without any attributes.

I thought about something like

<xsl:template match="@*|node()">
    <xsl:copy>
        <xsl:apply-templates select="@*|node()" />
    </xsl:copy>
</xsl:template>
<xsl:template match="p">
    <span>
        <xsl:apply-templates select="@*|node()" />
    </span>
</xsl:template>

but this does not work. The <p> tags still appear.

It is possible to write an adapter which will intercept the HTML before it is sent to the smtp server and manipulate it, but there are considerable difficulties in this approach which I am looking to avoid.

Is it even possible to do what I am attempting? Any help greatly appreciated.

Upvotes: 2

Views: 1187

Answers (1)

Mathias M&#252;ller
Mathias M&#252;ller

Reputation: 22647

Your input documents, this sample for instance:

<p xmlns="http://www.w3.org/1999/xhtml">
   <span>Some text</span>
</p>

Have a default namespace. And that's a good thing because a valid XHTML document must be in a namespace.

This means that this namespace applies to all elements in the document by default, and you have to account for this in your XSLT stylesheet. Redeclare this namespace there:

<xsl:stylesheet xmlns:xhtml="http://www.w3.org/1999/xhtml">

and whenever you make a reference to an element from the input document, prefix the element with xhtml::

<xsl:template match="xhtml:p">
    <span>
        <xsl:apply-templates select="@*|node()" />
    </span>
</xsl:template>

This should get you started. You have not told us yet if the output document should also be in a namespace or not.

Currently, only modifying the two templates you already have, a structure like

<p>
  <span/>
</p>

will end up as

<span>
  <span/>
</span>

Is this acceptable for you? If not, there must be an additional rule (template) about p elements that contain span elements:

<xsl:template match="xhtml:p[xhtml:span]">

or perhaps

<xsl:template match="xhtml:p[//xhtml:span]">

Upvotes: 1

Related Questions