1

I cannot figure out how to suppress the default attribute shape="rect" in an xhtml output document when using xsl:copy-of.

Sample XML:

<div class="table">
<p class="table-caption"><span class="table-label">Table 7.2</span> Foo<a class="tabfn-ref"
        href="#s9781483390086.i825" id="s9781483390086.i808" shape="rect"><sup>a</sup></a> in
    Pricing</p>
<img alt="Table 11" class="table-image" src="10.4135_9781483390086-table11.jpg"/>
<table>
    <tgroup cols="3">
        <colspec align="left" colname="1" colnum="1"/>
        <colspec align="left" colname="2" colnum="2"/>
        <colspec align="left" colname="3" colnum="3"/>
        <thead>
            <row rowsep="1">
                <entry align="left">
                    <p/>
                </entry>
                <entry align="left">
                    <p>N</p>
                </entry>
                <entry align="left">
                    <p>%</p>
                </entry>
            </row>
        </thead>
        <tbody>
            <row>
                <entry>
                    <p>Foo<a class="tabfn-ref" href="#s9781483390086.i826"
                            id="s9781483390086.i809" shape="rect"><sup>b</sup></a></p>
                    <p>1–12</p>
                    <p>13–24</p>
                    <p>25–36</p>
                    <p>37–48</p>
                    <p>49–60</p>
                    <p>61–72</p>
                    <p>73–84</p>
                    <p>85–96</p>
                    <p>More than 96</p>
                </entry>
            </row>
            <row>
                <entry>
                    <p>Bar<a class="tabfn-ref" href="#s9781483390086.i827"
                            id="s9781483390086.i810" shape="rect"><sup>c</sup></a></p>
                    <p>1–20%</p>
                    <p>21–40%</p>
                    <p>41–60%</p>
                    <p>61–80%</p>
                    <p>More than 80%</p>
                </entry>
            </row>
        </tbody>
    </tgroup>
</table>
<div class="table-notes" id="s9781483390086.i825a">
    <p class="table-note" id="s9781483390086.i825b"><span class="label-fn"><a class="tabfn-ref"
                href="#s9781483390086.i808" id="s9781483390086.i825" shape="rect"
                ><sup>a</sup></a></span> Foo</p>
    <p class="table-note" id="s9781483390086.i825c"><span class="label-fn"><a class="tabfn-ref"
                href="#s9781483390086.i809" id="s9781483390086.i826" shape="rect"
                ><sup>b</sup></a></span> Bar</p>
    <p class="table-note" id="s9781483390086.i825d"><span class="label-fn"><a class="tabfn-ref"
                href="#s9781483390086.i810" id="s9781483390086.i827" shape="rect"
                ><sup>c</sup></a></span> Too</p>
</div>

Sample XSLT:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xhtml="http://www.w3.org/1999/xhtml"
    exclude-result-prefixes="xs xhtml" xmlns="http://www.w3.org/1999/xhtml"
    version="2.0">

    <xsl:output method="xhtml" indent="yes"/>

    <!-- Suppress default shape attribute -->
    <xsl:template match="*/@shape"/>

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

    <xsl:template priority="1" match="//div[@class='table']//p[@class='table-caption']"/>

    <xsl:template match="table">
        <xsl:element name="table">
            <xsl:attribute name="hidden" select="'hidden'"/>
            <xsl:element name="caption">
                <xsl:copy-of select="preceding-sibling::p[@class='table-caption'] | *[not(preceding::a/@shape)]"/>
            </xsl:element>
            <xsl:apply-templates/>
        </xsl:element>
    </xsl:template>



</xsl:stylesheet>

I need to suppress the shape="rect" from the output. As you can see, it is suppressed from the output for all anchors, except for the one using xsl:copy-of. How can I specify suppression in the line:

<xsl:copy-of select="preceding-sibling::p[@class='table-caption'] | *[not(preceding::a/@shape)]"/>

This is obviously not working.

Output:

    <div class="table">
   <img alt="Table 11" class="table-image" src="10.4135_9781483390086-table11.jpg"/>
   <table xmlns="http://www.w3.org/1999/xhtml" hidden="hidden">
      <caption>
         <p xmlns="" class="table-caption">
            <span class="table-label">Table 7.2</span> Foo <a class="tabfn-ref"
               href="#s9781483390086.i825" id="s9781483390086.i808" shape="rect">
               <sup>a</sup>
            </a> in Pricing </p>
      </caption>
      <tgroup xmlns="" cols="3">
         <colspec align="left" colname="1" colnum="1"/>
         <colspec align="left" colname="2" colnum="2"/>
         <colspec align="left" colname="3" colnum="3"/>
         <thead>
            <row rowsep="1">
               <entry align="left">
                  <p/>
               </entry>
               <entry align="left">
                  <p>N</p>
               </entry>
               <entry align="left">
                  <p>%</p>
               </entry>
            </row>
         </thead>
         <tbody>
            <row>
               <entry>
                  <p>Foo <a class="tabfn-ref" href="#s9781483390086.i826" id="s9781483390086.i809">
                        <sup>b</sup>
                     </a>
                  </p>
                  <p>1–12</p>
                  <p>13–24</p>
                  <p>25–36</p>
                  <p>37–48</p>
                  <p>49–60</p>
                  <p>61–72</p>
                  <p>73–84</p>
                  <p>85–96</p>
                  <p>More than 96</p>
               </entry>
            </row>
            <row>
               <entry>
                  <p>Bar <a class="tabfn-ref" href="#s9781483390086.i827" id="s9781483390086.i810">
                        <sup>c</sup>
                     </a>
                  </p>
                  <p>1–20%</p>
                  <p>21–40%</p>
                  <p>41–60%</p>
                  <p>61–80%</p>
                  <p>More than 80%</p>
               </entry>
            </row>
         </tbody>
      </tgroup>
   </table>
   <div class="table-notes" id="s9781483390086.i825a">
      <p class="table-note" id="s9781483390086.i825b">
         <span class="label-fn">
            <a class="tabfn-ref" href="#s9781483390086.i808" id="s9781483390086.i825">
               <sup>a</sup>
            </a>
         </span> Foo </p>
      <p class="table-note" id="s9781483390086.i825c">
         <span class="label-fn">
            <a class="tabfn-ref" href="#s9781483390086.i809" id="s9781483390086.i826">
               <sup>b</sup>
            </a>
         </span> Bar </p>
      <p class="table-note" id="s9781483390086.i825d">
         <span class="label-fn">
            <a class="tabfn-ref" href="#s9781483390086.i810" id="s9781483390086.i827">
               <sup>c</sup>
            </a>
         </span> Too </p>
   </div>
</div>

In the first a class="tabfn-ref" the shape attribute is retained (due to copy-of). I need this to be suppressed.

Mads Hansen
  • 63,927
  • 12
  • 112
  • 147
user2093335
  • 197
  • 1
  • 2
  • 12
  • Please post **valid** code (preferably minimized to only what's necessary), so we can reproduce the issue. In general, does a deep copy - you cannot pick and choose. – michael.hor257k Nov 05 '14 at 22:03

1 Answers1

2

You do not have the ability to exclude attributes or nodes when using xsl:copy-of. It performs a deep copy of the selected node.

Since you are already using the identity transformation with an empty template to suppress the @shape attribute and already have an empty template matching //div[@class='table']//p[@class='table-caption'], the easiest thing to do would be to change the <xsl:copy-of> to <xsl:apply-templates> with a mode and define a template in that mode to copy and apply-templates.

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema" 
    xmlns:xhtml="http://www.w3.org/1999/xhtml"
    exclude-result-prefixes="xs xhtml" xmlns="http://www.w3.org/1999/xhtml"
    version="2.0">

    <xsl:output method="xhtml" indent="yes"/>

    <!-- Suppress default shape attribute -->
    <xsl:template match="*/@shape"/>

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

    <xsl:template priority="1" 
                  match="//div[@class='table']//p[@class='table-caption']"/>

    <xsl:template match="//div[@class='table']//p[@class='table-caption']"
                  mode="caption">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="table">
        <table hidden="hidden">
            <caption>
                <xsl:apply-templates 
                               select="preceding-sibling::p[@class='table-caption'] 
                                     | *[not(preceding::a/@shape)]" mode="caption"/>
            </caption>
            <xsl:apply-templates/>
        </table>
    </xsl:template>

</xsl:stylesheet>
Mads Hansen
  • 63,927
  • 12
  • 112
  • 147
  • Thank you Mads, this is exactly what I needed. I was having trouble coming up with a solution using apply-templates here as I needed to suppress the output of the table-caption where it stood in the XML. Using mode works wonderfully. Thanks again. – user2093335 Nov 06 '14 at 16:26