kevin sufferdini
kevin sufferdini

Reputation: 121

xslt matching a dynamic template

I am having an xslt issue that I cannot seem to solve. Right now I have this template match: <xsl:template match="bodytext/p[position() = 4]">

And this works fine. When the 4th paragraph renders I include some content. The issue is that sometimes the <p> element can have a class class="exclude"

I am trying to find a good way to exclude the <p> tags that have that class attribute. The problem is that there can be as many <p class="exclude"> as wanted/needed before or at the 4th paragraph while still rendering the 1st, 2nd, and 3rd paragraphs that do not have "exclude" class. So if a document looks like:

<p></p>
<p class="exclude"></p>
<p class="exclude"></p>
<p class="exclude"></p>
<p></p>
<p class="exclude"></p>
<p></p>
<p></p>

I only want to match the template:

<p></p>
<p></p>
<p></p>
<p></p>

Another example would be an input of:

<p></p>
<p></p>
<p></p>
<p class="exclude"></p>
<p class="exclude"></p>
<p class="exclude"></p>
<p class="exclude"></p>
<p class="exclude"></p>
<p class="exclude"></p>
<p></p>

and output of:

<p></p>
<p></p>
<p></p>
<p></p>

Thanks in advance

Upvotes: 0

Views: 301

Answers (2)

Martin Honnen
Martin Honnen

Reputation: 167401

Use

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

<xsl:template match="bodytext/p[@class = 'exclude']"/>

<xsl:template match="bodytext/p[not(@class = 'exclude')][4]">
  <xsl:copy>
    <!-- new content goes here -->
    <xsl:apply-templates/>
  </xsl:copy>
</xsl:template>

Upvotes: 0

Pavel Veller
Pavel Veller

Reputation: 6115

You can do it like this:

<xsl:apply-templates 
    select="bodytext/p[not(@class = 'exclude')][position() = 4]"/>

Here's the test case. Applying the following transformation:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output omit-xml-declaration="yes" indent="yes"/>
    <xsl:strip-space elements="*"/>

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

    <xsl:template match="/">
        <xsl:apply-templates 
            select="bodytext/p[not(@class = 'exclude')][position() = 4]"/>
    </xsl:template>

</xsl:stylesheet>

To:

<bodytext>
    <p></p>
    <p class="exclude"></p>
    <p class="exclude"></p>
    <p class="exclude"></p>
    <p></p>
    <p class="exclude"></p>
    <p></p>
    <p>test</p>
</bodytext>

Produces:

<p>test</p>

Upvotes: 2

Related Questions