title: Issues selecting and deleting nodes with XPATH and PHP DOM
body: <p>Probably a stupid question but so far I can't figure this out...</p>
  
  <p>I have an XHTML document as a string. It's in <code>$temp</code> So far so good. I want to do two things. I want to select all meta tags in the body (they are there because of their use in conjunction with microdata) and then delete them. After deleting the microdata properties that is.</p>
  
  <pre><code>    $xml=new DOMDocument();
      $xml-&gt;loadXML($temp);
      $xpath = new DOMXPath($xml);
      $attr = $xpath-&gt;query("//@itemscope|//@itemprop|//@itemtype|//@itemid|//@itemref");
      foreach ($attr as $entry)
          $entry-&gt;parentNode-&gt;removeAttribute($entry-&gt;nodeName);
  </code></pre>
  
  <p>That works. But I can't manage to select any nodes with Xpath.</p>
  
  <pre><code>$xpath = new DOMXPath($xml); // thought I had to update this after changing the XML
  echo $xpath-&gt;query("//body")-&gt;length; // =&gt; 0
  echo $xml-&gt;getElementsByTagName("body")-&gt;length; // =&gt; 1
  </code></pre>
  
  <p>So Question No. 1: How do I select nodes with Xpath. Why doesn't this work?</p>
  
  <p>This works to get the node list though:</p>
  
  <pre><code>$node = $xml-&gt;getElementsByTagName("body")-&gt;item(0)-&gt;getElementsByTagName("meta");
  </code></pre>
  
  <p>I figured to remove the nodes I'd use this: (similar to removing the attributes above)</p>
  
  <pre><code>foreach ($node as $entry)
  {
      $entry-&gt;parentNode-&gt;removeChild($entry);
  }
  </code></pre>
  
  <p>But the nodes remain. </p>
  
  <p>So there is Question No. 2: How to remove nodes from an XML file. </p>
  
  <p>Specifically meta nodes anywhere in any body node.</p>
  
  <p>Thanks.</p>
  
  <p><strong>UPDATE</strong></p>
  
  <p>Let me add an HTML test case:</p>
  
  <pre><code>$temp='&lt;!DOCTYPE html&gt;
  &lt;html xmlns="http://www.w3.org/1999/xhtml" xml:lang="de" lang="de"&gt;
      &lt;head&gt;
          &lt;meta charset="utf-8"/&gt;
      &lt;/head&gt;
      &lt;body id="dok" itemscope="itemscope" itemtype="http://schema.org/WebPage" &gt;
          &lt;div&gt;&lt;div&gt;&lt;div&gt;&lt;meta itemprop="dummy" content="something"/&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;
          &lt;span&gt;&lt;meta itemprop="dummy2" content="something2"/&gt;&lt;/span&gt;
      &lt;/body&gt;
  &lt;/html&gt;';
  </code></pre>
  
  <p>With the above the xPath trying to select the body give me a length of 0 and I can't remove all meta tags from the body...</p>
  
  <p><strong>UPDATE</strong></p>
  
  <p>This works with the loadXML() method:</p>
  
  <pre><code>$xpath = new DOMXPath($xml);
  $xpath-&gt;registerNamespace("x","http://www.w3.org/1999/xhtml");
  echo $xpath-&gt;query("//x:body")-&gt;length;
  </code></pre>
  
  <p><strong>SOLUTION without namespaces</strong></p>
  
  <p>It was about the <code>xmlns="http://www.w3.org/1999/xhtml"</code> namespace in the root <code>html</code> tag all along. <code>//body</code> selects any body tag that is <strong>NOT</strong> part of any namespace. Since we did specify a default namespace and <code>body</code> is part of that namespace <code>//body</code>won't select it. I have no idea under what name to access the namespace already intrinsic to the XHTML without declaring it under a name but if we strip it off before creating the XML all is fine. After we're done we can add it back in..</p>
  
  <pre><code>    $temp =  str_replace('xmlns="http://www.w3.org/1999/xhtml"','',$temp);
      $xml=new DOMDocument();
      $xml-&gt;loadXML($temp);
      $xpath = new DOMXPath($xml);    
      $attr = $xpath-&gt;query("//@itemscope|//@itemprop|//@itemtype|//@itemid|//@itemref");
      foreach ($attr as $entry)
          $entry-&gt;parentNode-&gt;removeAttribute($entry-&gt;nodeName);
      $node = $xpath-&gt;query("//body//meta");
      foreach ($node as $entry)
      {
          $entry-&gt;parentNode-&gt;removeChild($entry);
      }   
      $temp=$xml-&gt;saveXML();
      $temp =  str_replace('&lt;html','&lt;html xmlns="http://www.w3.org/1999/xhtml"',$temp);
  </code></pre>
  
  <p>that way <code>//body//meta</code> works just as expected...</p>