title: How to recursively delete some xml elements using XSLT
body: <p>So I got this situation which sucks. I have an XML like this</p>
  
  <pre>
  
  <code>
  &lt;table border=&quot;1&quot; cols=&quot;200 100pt 200&quot;&gt;
    &lt;tr&gt;
      &lt;td&gt;isbn&lt;/td&gt;
      &lt;td&gt;title&lt;/td&gt;
      &lt;td&gt;price&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td /&gt;
      &lt;td /&gt;
      &lt;td&gt;
        &lt;span type=&quot;champsimple&quot; id=&quot;9b297fb5-d12b-46b1-8899-487a2df0104e&quot; categorieid=&quot;a1c70692-0427-425b-983c-1a08b6585364&quot; champcoderef=&quot;01f12b93-b4c5-401b-9da1-c9385d77e43f&quot;&gt;
          [pr&#233;nom]
        &lt;/span&gt;
        &lt;span type=&quot;champsimple&quot; id=&quot;e103a6a5-d1be-4c34-8a54-d234179fb4ea&quot; categorieid=&quot;a1c70692-0427-425b-983c-1a08b6585364&quot; champcoderef=&quot;01f12b93-b4c5-401b-9da1-c9385d77e43f&quot;&gt;[nom]&lt;/span&gt;
        &lt;span&gt;&lt;/span&gt;
      &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;&lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;/td&gt;
      &lt;td&gt;Phill It in&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;table id=&quot;cas1&quot;&gt;
        &lt;tr&gt;
          &lt;td &gt;&lt;/td&gt;
          &lt;td &gt;foo&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td &gt;bar&lt;/td&gt;
          &lt;td &gt;boo&lt;/td&gt;
        &lt;/tr&gt;
      &lt;/table&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;table id=&quot;cas2&quot;&gt;
        &lt;tr&gt;
          &lt;td &gt;&lt;/td&gt;
          &lt;td &gt;foo&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td &gt;&lt;/td&gt;
          &lt;td &gt;boo&lt;/td&gt;
        &lt;/tr&gt;
      &lt;/table&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;table id=&quot;cas3&quot;&gt;
        &lt;tr&gt;
          &lt;td &gt;bar&lt;/td&gt;
          &lt;td &gt;&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td &gt;foo&lt;/td&gt;
          &lt;td &gt;boo&lt;/td&gt;
        &lt;/tr&gt;
      &lt;/table&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;table id=&quot;cas4&quot;&gt;
        &lt;tr&gt;
          &lt;td /&gt;
          &lt;td /&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;foo&lt;/td&gt;
          &lt;td&gt;boo&lt;/td&gt;
        &lt;/tr&gt;
      &lt;/table&gt;
    &lt;/tr&gt;
    &lt;table id=&quot;cas4&quot;&gt;
      &lt;tr&gt;
        &lt;td /&gt;
        &lt;td /&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
        &lt;td&gt;foo&lt;/td&gt;
        &lt;td&gt;boo&lt;/td&gt;
      &lt;/tr&gt;
    &lt;/table&gt;
    &lt;tr&gt;
      &lt;td /&gt;
      &lt;td /&gt;
    &lt;/tr&gt;
  &lt;/table&gt;
  </code>
  
  </pre>
  
  <p>Now the question is how would I recursively delete all empty td, tr and table elements?</p>
  
  <p>Now I use this XSLT</p>
  
  <pre>
  
  <code>
  &lt;xsl:stylesheet version=&quot;1.0&quot; xmlns:xsl=&quot;http://www.w3.org/1999/XSL/Transform&quot;&gt;
    &lt;xsl:output omit-xml-declaration=&quot;yes&quot; indent=&quot;yes&quot;/&gt;
    &lt;xsl:strip-space elements=&quot;*&quot; /&gt;
  
    &lt;xsl:template match=&quot;node()|@*&quot;&gt;
      &lt;xsl:copy&gt;
        &lt;xsl:apply-templates select=&quot;node()|@*&quot;/&gt;
      &lt;/xsl:copy&gt;
    &lt;/xsl:template&gt;
  
    &lt;xsl:template match=&quot;td[not(node())]&quot; /&gt;
    &lt;xsl:template match=&quot;tr[not(node())]&quot; /&gt;
    &lt;xsl:template match=&quot;table[not(node())]&quot; /&gt;
  
  &lt;/xsl:stylesheet&gt;
  </code>
  
  </pre>
  
  <p>But it doesn't do very well. After I delete td, a tr becomes empty but it doesn't handle that. Too bad. See the <strong>table</strong> element with "cas4".</p>
  
  <pre>
  
  <code>
  &lt;table border=&quot;1&quot; cols=&quot;200 100pt 200&quot;&gt;
    &lt;tr&gt;
      &lt;td&gt;isbn&lt;/td&gt;
      &lt;td&gt;title&lt;/td&gt;
      &lt;td&gt;price&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;
        &lt;span type=&quot;champsimple&quot; id=&quot;9b297fb5-d12b-46b1-8899-487a2df0104e&quot; categorieid=&quot;a1c70692-0427-425b-983c-1a08b6585364&quot; champcoderef=&quot;01f12b93-b4c5-401b-9da1-c9385d77e43f&quot;&gt;
          [pr&#233;nom]
        &lt;/span&gt;
        &lt;span type=&quot;champsimple&quot; id=&quot;e103a6a5-d1be-4c34-8a54-d234179fb4ea&quot; categorieid=&quot;a1c70692-0427-425b-983c-1a08b6585364&quot; champcoderef=&quot;01f12b93-b4c5-401b-9da1-c9385d77e43f&quot;&gt;[nom]&lt;/span&gt;
        &lt;span /&gt;
      &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Phill It in&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;table id=&quot;cas1&quot;&gt;
        &lt;tr&gt;
          &lt;td&gt;foo&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;bar&lt;/td&gt;
          &lt;td&gt;boo&lt;/td&gt;
        &lt;/tr&gt;
      &lt;/table&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;table id=&quot;cas2&quot;&gt;
        &lt;tr&gt;
          &lt;td&gt;foo&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;boo&lt;/td&gt;
        &lt;/tr&gt;
      &lt;/table&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;table id=&quot;cas3&quot;&gt;
        &lt;tr&gt;
          &lt;td&gt;bar&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;foo&lt;/td&gt;
          &lt;td&gt;boo&lt;/td&gt;
        &lt;/tr&gt;
      &lt;/table&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;table id=&quot;cas4&quot;&gt;
        &lt;tr /&gt;
        &lt;tr&gt;
          &lt;td&gt;foo&lt;/td&gt;
          &lt;td&gt;boo&lt;/td&gt;
        &lt;/tr&gt;
      &lt;/table&gt;
    &lt;/tr&gt;
    &lt;table id=&quot;cas4&quot;&gt;
      &lt;tr /&gt;
      &lt;tr&gt;
        &lt;td&gt;foo&lt;/td&gt;
        &lt;td&gt;boo&lt;/td&gt;
      &lt;/tr&gt;
    &lt;/table&gt;
    &lt;tr /&gt;
  &lt;/table&gt;
  </code>
  
  </pre>
  
  <h3>How would you solve this problem?</h3>