Jump to content

DOMDocument remove whitespace does not remove all whitespace?


Andy-H

Recommended Posts

Hi, I'm working on a template system which uses DOMDocument, I set preserveWhitespace before calling loadHTML but still the unnecessary spaces are not removed, anyone got any experience in this area?

 

 

My code:

Template.class.php

[size=78%]<?php[/size]
namespace phantom\classes\templating;
class Template {
   protected $_document;
   protected $_settings = array(
      'version'             => '4.01',
      'encoding'            => 'UTF-8',
      'template_dir'        => 'templates',
      'template_ext'        => 'tmpl.php',
      'preserve_whitespace' => false
   );
   
   public function __construct($tmpl_file, array $data = array(), array $settings = array())
   {
      $this->_settings = array_merge($this->_settings, $settings);
      $this->_document = new \DOMDocument($this->_settings['version'], $this->_settings['encoding']);
      $this->_document->preserveWhiteSpace = $this->_settings['preserve_whitespace'];
      $this->_document->loadHTML($this->_getContent($tmpl_file, $data));
   }
   public function getFragment($file_name, array $data = array())
   {
      return new TemplateFragment($this->_getContent($file_name, $data), $this->_document);
   }
   public function getContents()
   {
      return $this->_document->saveHTML();
   }
   public function printContents()
   {
      $this->_document->saveHTMLFile('php://output');
   }
   protected function _getContent($file_name, array $data = array())
   {
      ob_start();
      extract($data, EXTR_SKIP);
      include $this->_settings['template_dir'] . DIRECTORY_SEPARATOR . $file_name .'.'. $this->_settings['template_ext'];
      return ob_get_clean();
   }
}

 

 

TemplateFragment.class.php

[size=78%]<?php[/size]
namespace phantom\classes\templating;
class TemplateFragment {
   protected $_content;
   protected $_document;
   
   public function __construct($content, \DOMDocument $document)
   {
      $this->_document = $document;
      $this->_content  = $this->_document->createDocumentFragment();
      $this->_content->appendXML($content);
   }
   public function appendTo($selector)
   {
      $this->_insertNode($selector, false, true);
   }
   public function prependTo($selector)
   {
      $this->_insertNode($selector, true, true);
   }
   public function insertBefore($selector)
   {
      $this->_insertNode($selector, true, false);
   }
   public function insertAfter($selector)
   {
      $this->_insertNode($selector, false, false);
   }
   protected function _insertNode($selector, $top, $inside)
   {
      $node = $this->_getElement($selector);
      if ( $inside && $top )
      {
         $node = $node->insertBefore($this->_content, $node->firstChild);
      }
      elseif ( !$inside && $top )
      {
         $node = $node->parentNode->insertBefore($this->_content, $node);
      }
      elseif ( $inside && !$top )
      {
         $node = $node->appendChild($this->_content);
      }
      elseif ( !$inside && !$top )
      {
         if( $node->nextSibling )
         {
            $node = $node->parentNode->insertBefore($this->_content, $node->nextSibling);
         }
         else
         {
            $node = $node->parentNode->appendChild($this->_content);
         }
      }
      $this->_document->loadHTML($this->_document->saveHTML());
   }
   protected function _getElement($selector)
   {
      if ( substr($selector, 0, 1) == '#' )
      {
         $elem = $this->_document->getElementById(substr($selector, 1));
         if ( is_null($elem) )
            throw new \Exception('No element found in document with that ID');
         return $elem;
      }
      $XPath = new \DOMXPath($this->_document);
      $pos   = strpos($selector, '[');
      if ( $pos !== false )
      {
         $index = (int)substr($selector, $pos+1, strpos($selector, ']')-1);
         $selector = substr($selector, 0, $pos);
      }
      else
      {
         $index = 0;
      }
      $query    = $this->_parse_selector($selector);
      $nodeList = $XPath->query($query);
      if ( $nodeList->length < $index )
         throw new \Exception('XPath query did not return '. number_format($index, 0) .' or more NodeList in TemplateFragment::_getElement(".classname")');
      return $nodeList->item($index);
   }
   protected function _parse_selector($selector)
   {
      preg_match('~([^#|^.]?)([\.?|#?])(.+)~', $selector, $matches);
      $query  = '//';
      $query .= !empty($matches[1]) ? $matches[1] : '*';
      if ( isset($matches[2]) )
      {
         $query .= str_replace(array('.', '#'), array("[@class='", "[@id='"), $matches[2]);
         if ( isset($matches[3]) ) $query .= $matches[3] ."']";
      }
      return $query;
   }
}

 

 

templates/default.tmpl.php


<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html lang="en">
   <head>
      <title>Phantom - Tracking Ststems and Accessories</title>
      <!-- META //-->
      <meta name="description"
         content="" >
      <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" >
      <!-- LINKS AND SCRIPTS //-->
      <link rel="stylesheet" href="css/layout.css" type="text/css" >
   </head>
   <body>
      <div id="clouds"><>
      <div id="container">
         <!-- HEADER //-->
         <div id="header">
            <h1>
               <a href="/">
                  <img src="images/layout/b2c/phantom.png" alt="Phantom vehicle tracking and accessories" >
               </a>
            </h1>
            <div id="header_right">
               <ul id="header_nav" class="navigation">
                  <li class="first"><a href="#">About</a></li>
                  <li><a href="#">News</a></li>
               </ul>
               <img class="telephone" src="images/layout/b2c/tel.png" alt="Telephone number" >
            <>
         <>
         <!-- CONTENT //-->
         <div id="content">
            <div class="clr"><>
         <>
      <>
      <!-- FOOTER //-->
      <div id="footer">
         <div id="logo"><>
         <div class="green_banner">
            <div id="motto">Protect, Secure, Enjoy<>
         <>
         <div class="blue_banner"><>
      <>
   </body>
</html>

 

 

NOTE: This is one of many template files involved

 

 

index.php


<?php
include 'phantom/classes/templating/Template.class.php';
include 'phantom/classes/templating/TemplateFragment.class.php';


use \phantom\classes\templating as tmpl;
try
{
   $page = new tmpl\Template('default');
   $page->getFragment('b2c/navigation')->insertAfter('#header');
   $page->getFragment('default/slider')->insertAfter('#main_nav');
   $page->getFragment('b2c/product_nav')->insertAfter('#slider');
   $page->getFragment('default/content_lr_divider')->prependTo('#content');
   $page->getFragment('content/videos')->prependTo('#left_content');
   $page->getFragment('content/news')->insertAfter('#video');
   $page->getFragment('content/twitter')->appendTo('#left_content');
   $page->getFragment('content/index/main_content')->appendTo('#right_content');
   $page->getFragment('content/mini_product_slider')->appendTo('#right_content');
   
   echo $page->printContents();
}
catch ( Exception $e )
{
   echo $e->getMessage();
}

 

 

OUTPUT:

 

 




<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html lang="en"><head><title>Phantom - Tracking Ststems and Accessories</title><!-- META //--><meta name="description" content=""><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><!-- LINKS AND SCRIPTS //--><link rel="stylesheet" href="css/layout.css" type="text/css"></head><body><div id="clouds"><><div id="container">


         <!-- HEADER //-->


         <div id="header">


            <h1>


               <a href="/">


                  <img src="images/layout/b2c/phantom.png" alt="Phantom vehicle tracking and accessories"></a>


            </h1>


            <div id="header_right">


               <ul id="header_nav" class="navigation"><li class="first"><a href="#">About</a></li>


                  <li><a href="#">News</a></li>


               </ul><img class="telephone" src="images/layout/b2c/tel.png" alt="Telephone number"><>


         <><!-- MAIN NAVIGATION //-->
<ul id="main_nav" class="navigation"><li class="first"><a href="#">Home</a></li>
   <li><a href="#">Tracking</a></li>
   <li><a href="#">Remapping</a></li>
   <li><a href="#">Tyre protector</a></li>
   <li><a href="#">Alarms</a></li>
   <li><a href="#">Cameras and sensors</a></li>
   <li><a href="#">Insurance</a></li>
   <li><a href="#">Contact us</a></li>
</ul><!-- SLIDER //--><div id="slider">
<><!-- PRODUCT NAVLIGATION IMAGES //-->
<ul id="product_navigation"><li class="first"><a href="#" id="remap">Engine ECU remapping</a></li>
   <li><a href="#" id="tyre-pro">Tyre protector</a></li>
   <li><a href="#" id="sat-dish">Caravan and motorhome satellite dish</a></li>
   <li><a href="#" id="reverse-sensor">Reverse sensor</a></li>
   <li><a href="#" id="in-car-cam">In car camera</a></li>
   <li><a href="#" id="alarms">Caravan and motorhome alarms</a></li>
   <li><a href="#" id="tracking">Caravan and motorhome tracking</a></li>
   <li><a href="#" id="subs">Renew tracking subscription</a></li>
</ul><!-- CONTENT //--><div id="content"><!-- LEFT CONTENT //-->
<div id="left_content"><!-- VIDEOS //-->
<div class="horizontal_grey" id="video">
   <div class="video_still"><>
   <strong class="title">Watch videos</strong>
   <ul><li><a href="#">Engine remapping</a></li>
      <li><a href="#">Reversing camera</a></li>
      <li><a href="#">Tyre protector</a></li>
      <li><a href="#">Mobile-home Satellite TV</a></li>
      <li><a href="#">Alarms</a></li>
      <li><a href="#">Tracking</a></li>
   </ul><><!-- NEWS //-->
<div class="orange_bg" id="news">
   <strong class="title">News in brief</strong>
   <h2><a href="#">From complete GPS tracking</a></h2>
   <p>
      and security packages, through to engine (ECU) remaps,
      tyre protectors, alarms and hands-free-kits, all our 
      products... <a href="#">more</a>
   </p>
   <h3><a href="#">From complete GPS tracking</a></h3>
   <p>
      and security packages, through to engine (ECU) remaps,
      tyre protectors, alarms and hands-free-kits, all our 
      products... <a href="#">more</a>
   </p>
   <h3><a href="#">From complete GPS tracking</a></h3>
   <p>
      and security packages, through to engine (ECU) remaps,
      tyre protectors, alarms and hands-free-kits, all our 
      products... <a href="#">more</a>
   </p>
<>
<!-- TWITTER //-->
<div class="vertical_grey">
   <div id="twitter"><>
   <strong class="title">Tweets</strong>
   <p>
      From complete GPS tracking and security packages through 
      to engine (ECU) remaps, tyre protectors
   </p>
   <p>
      From complete GPS tracking and security packages through 
      to engine (ECU) remaps, tyre protectors
   </p>
<><>
<!-- RIGHT CONTENT //-->
<div id="right_content">
<!-- MAIN CONTENT //-->
<div class="grey_bg">
   <p>
      Phantom offers a comprehensive range of leisure and 
      business monitoring services that will protect, enhance 
      and increase your enjoyment of your vehicle.
   </p>
   <p>
      From complete GPS tracking and security packages through 
      to engine (ECU) remaps, tyre protectors, alarms and hands 
      free kits all our products can be installed in caravans, 
      motorhomes, cars, trucks and business fleet vehicles.
   </p>
   <p>
      Our specialist mobile satellite team can assist you in the 
      purchase of the correct satellite dish. Allowing you to 
      recieve all your faviroute TV programs while travelling across Europe.
      Not only do we offer national custom-fitting vehicle 
      service, we can even bespoke our GPS monitoring and 
      tracking software to meet your individual and business 
      requirements.
   </p>
   <p>
      So why not take advantage of our nationwide fitting service 
      to protect and enhance your vehicle today.
   </p>
<><!-- MINI SLIDER //-->
<div class="dark_blue_bg" id="mini_slider">
   <strong class="title">Other products</strong>
   <a href="#" class="first"><img src="images/product_small/product_small.jpg" alt="product1" title="product1"></a>
   <a href="#"><img src="images/product_small/product_small.jpg" alt="product1" title="product1"></a>
   <a href="#"><img src="images/product_small/product_small.jpg" alt="product1" title="product1"></a>
   <a href="#"><img src="images/product_small/product_small.jpg" alt="product1" title="product1"></a>
   <a href="#"><img src="images/product_small/product_small.jpg" alt="product1" title="product1"></a>
<><>


            <div class="clr"><>


         <>


      <><!-- FOOTER //--><div id="footer">


         <div id="logo"><>


         <div class="green_banner">


            <div id="motto">Protect, Secure, Enjoy<>


         <>


         <div class="blue_banner"><>


      <></body></html>

 

 

NOTE: In the view source it didn't have the double line breaks, but they appeared when I pasted into notepad++ to remove formatting ( I have notepad++ setup to use UTF-8 without BOM) could this be something to do with it? The whitespace messes up at the first double line break.

 

 

Sorry for the long code samples.

 

 

Thanks for any help.

Link to comment
Share on other sites

Never thought, if it removed all whitespace outside of tags, <b>hello</b> <i>PHPFreaks</i> would result as <b>hello</b><i>PHPFreaks</i>

 

 

return preg_replace('~\s+~i', ' ', ob_get_clean());

 

 

Seemed like a pretty safe bet :)

Link to comment
Share on other sites

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.