How to remove the content with element by using the attribute value?

66 views Asked by At

I want to remove the two paragraphs by using that attribute value, I tried the below things, but it's occurring in output,

My input XML is:

<chapter outputclass="chapter-Body">
<body class="- chapter/body ">
<p class="- chapter/p ">why now?</p>
<p class="- chapter/p " outputclass="Image_Size">Banner</p>
<fig>
<image href="3.jpg" outputclass="Fig-Image_Ref"/>
</fig>
<p class="- chapter/p ">But for others, it may not be.</p>
<image ref="4.png" outputclass="Image_Ref"/>
<p class="- chapter/p " outputclass="Image_Size">Small</p>
<p class="- chapter/p ">As result</p>
</body>
</chapter>

XSL I used:

<xsl:stylesheet version="2.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:template match="chapter[@outputclass='chapter-Body']">
<body>
<text>
<text_top><p><xsl:value-of select="body/fig/preceding-sibling::p[1]"/></p>
 </text_top>

<text_bottom><p><xsl:value-of select="body/fig/following-sibling::p[1]"/></p>
  <p><xsl:value-of select="body/fig/following-sibling::p[2]"/></p>
 </text_bottom>
</text> 
<xsl:apply-templates/>
</body>
</xsl:template>

<xsl:template match="p[@outputclass='Image_Size']"/>

</xsl:stylesheet>

XML output I got as:

<body>
<text>
<text_top>
<p>Banner</p>
</text_top>
<text_bottom>
<p>But for others, it may not be.</p>
<p>Small</p>
</text_bottom>
</text>
</body>

But I'm expecting to be like:

<body>
<text>
<text_top>
<p>why now?</p>
</text_top>
<text_bottom>
<p>But for others, it may not be.</p>
<p>As result</p>
</text_bottom>
</text>
</body>

I used apply templates of that particular two paras but it's coming in output. How can I fix this using the same XSLT?

1

There are 1 answers

3
Tim C On BEST ANSWER

The order of the preceding-sibling axis is the reverse document order, so when you do body/fig/preceding-sibling::p[1], this gets the p that immediately precedes the fig element. You need the one before, so you should be doing body/fig/preceding-sibling::p[2].

Similarly, you want the 1st and 3rd p elements following fig so you should adjust the indexes accordingly for that too. Note that your current template that matches p[@outputclass='Image_Size'] does not get used at all, because there is nothing in the XSLT that does an xsl:apply-templates to select them.

Try this XSLT

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
   <xsl:output method="xml" indent="yes"/>

   <xsl:template match="chapter[@outputclass='chapter-Body']">
      <body>
         <text>
            <text_top>
               <p><xsl:value-of select="body/fig/preceding-sibling::p[2]"/></p>
            </text_top>

            <text_bottom>
               <p><xsl:value-of select="body/fig/following-sibling::p[1]"/></p>
               <p><xsl:value-of select="body/fig/following-sibling::p[3]"/></p>
            </text_bottom>
         </text> 
      </body>
   </xsl:template>
</xsl:stylesheet>

Having said that, it looks what you are trying to achieve is to select all p elements preceding and following the fig, with the exception of the ones with an outputclass of "Image_Size".

If that is the case, try this more generic XSLT. Note how the template that matches p[@outputclass='Image_Size'] is now used, because of the xsl:apply-templates in the first template.

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
   <xsl:output method="xml" indent="yes"/>

   <xsl:template match="chapter[@outputclass='chapter-Body']">
      <body>
         <text>
            <text_top>
               <xsl:apply-templates select="body/fig/preceding-sibling::p" />
            </text_top>

            <text_bottom>
               <xsl:apply-templates select="body/fig/following-sibling::p" />
            </text_bottom>
         </text> 
      </body>
   </xsl:template>

   <xsl:template match="p[@outputclass='Image_Size']"/>

   <xsl:template match="p">
       <p><xsl:value-of select="." /></p>
   </xsl:template>
</xsl:stylesheet>