rajat sethi
rajat sethi

Reputation: 57

Can we use multiple elements with except operator in xslt 1

I want to add multiple matches in except operator. Example:

<root>
  <div>
    <span style="font-family:'Work Sans', sans-serif;">
    </span>
    <h3>hi</h3>
    <ol><li>hello</li></ol>
    <ul><li>hello</li></ul>
    <p>name</p>
</div>
</root>

Expected result: Want to convert div tag to p tag and then move only h3,ol,ul,p tag out of it if present.

<root>
  <p>
    <span style="font-family:'Work Sans', sans-serif;">
    </span>
  </p>
    <h3>hi</h3>
    <ol><li>hello</li></ol>
    <ul><li>hello</li></ul>
    <p>name</p>
</root>

I tried this:

     <xsl:template match="div">
   <p>
      <xsl:copy-of select="* except h3"/>
   </p>
          <xsl:copy-of select="h3"/>    
  </xsl:template>

Above xslt results to :

 <root>
      <p>
        <span style="font-family:'Work Sans', sans-serif;">
        </span>
        <ol><li>hello</li></ol>
        <ul><li>hello</li></ul>
        <p>name</p>
      </p>
        <h3>hi</h3>
    </root>

Is there any way to add mutiple element names in except operator like <xsl:copy-of select="* except h3 and ol"/>

Another approach i tried:

 <xsl:template match="div[p | ol | ul | h3 | h2]">
        <xsl:apply-templates/>
    </xsl:template>

    <!-- convert <div> to <p> if it's direct child is not one of p,ol,ul -->
    <xsl:template match="div[not(p | ol | ul | h3 | h2)]">
        <p>
            <xsl:apply-templates/>
        </p>
    </xsl:template>

And this results to which is wrong as i still want span tag to be under p tag:

 <root><span style="font-family:'Work Sans', sans-serif;">
    </span>
    <h3>hi</h3>
    <ol><li>hello</li></ol>
    <ul><li>hello</li></ul>
    <p>name</p></root>

Upvotes: 1

Views: 716

Answers (2)

Siebe Jongebloed
Siebe Jongebloed

Reputation: 4870

In stead of using xsl:copy you could just use the xsl:apply-templates approach like this:

<xsl:stylesheet
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
  
  <xsl:strip-space elements="*"/>  
  <xsl:output indent="yes"/>
  
  <xsl:template match="node()|@*" name="copy">
    <xsl:copy>
      <xsl:apply-templates select="node()|@*"/>
    </xsl:copy>
  </xsl:template>
  
  <xsl:template match="div">
    <xsl:apply-templates/>
  </xsl:template>

  <xsl:template match="div/span">
    <p>
      <xsl:call-template name="copy"/>
    </p>
  </xsl:template>

</xsl:stylesheet>

Upvotes: 2

Martin Honnen
Martin Honnen

Reputation: 167716

The except operator was introduced in XPath 2.0 so it doesn't make any sense on how to use it with XSLT 1.0 which uses XPath 1.0.

As for its use where supported, you can of course do e.g. * except (h3, ol).

In XPath 1.0 you can try e.g. *[not(self::h3|self::ol)].

Upvotes: 1

Related Questions