[ Index ]
 

Code source de Symfony 1.0.0

Accédez au Source d'autres logiciels libresSoutenez Angelica Josefina !

title

Body

[fermer]

/lib/util/ -> sfDomCssSelector.class.php (source)

   1  <?php
   2  
   3  /*
   4   * This file is part of the symfony package.
   5   * (c) 2004-2006 Fabien Potencier <fabien.potencier@symfony-project.com>
   6   * 
   7   * For the full copyright and license information, please view the LICENSE
   8   * file that was distributed with this source code.
   9   */
  10  
  11  /**
  12   * sfDomCssSelector allows to navigate a DOM with CSS selector.
  13   *
  14   * based on getElementsBySelector version 0.4 - Simon Willison, March 25th 2003
  15   * http://simon.incutio.com/archive/2003/03/25/getElementsBySelector
  16   *
  17   * @package    symfony
  18   * @subpackage util
  19   * @author     Fabien Potencier <fabien.potencier@symfony-project.com>
  20   * @version    SVN: $Id: sfDomCssSelector.class.php 3053 2006-12-16 16:01:30Z fabien $
  21   */
  22  class sfDomCssSelector
  23  {
  24    protected $dom = null;
  25  
  26    public function __construct($dom)
  27    {
  28      $this->dom = $dom;
  29    }
  30  
  31    public function getTexts($selector)
  32    {
  33      $texts = array();
  34      foreach ($this->getElements($selector) as $element)
  35      {
  36        $texts[] = $element->nodeValue;
  37      }
  38  
  39      return $texts;
  40    }
  41  
  42    public function getElements($selector)
  43    {
  44      $all_nodes = array();
  45      foreach ($this->tokenize_selectors($selector) as $selector)
  46      {
  47        $nodes = array($this->dom);
  48        foreach ($this->tokenize($selector) as $token)
  49        {
  50          $combinator = $token['combinator'];
  51          $token = trim($token['name']);
  52          $pos = strpos($token, '#');
  53          if (false !== $pos && preg_match('/^[A-Za-z0-9]*$/', substr($token, 0, $pos)))
  54          {
  55            // Token is an ID selector
  56            $tagName = substr($token, 0, $pos);
  57            $id = substr($token, $pos + 1);
  58            $xpath = new DomXPath($this->dom);
  59            $element = $xpath->query(sprintf("//*[@id = '%s']", $id))->item(0);
  60            if (!$element || ($tagName && strtolower($element->nodeName) != $tagName))
  61            {
  62              // tag with that ID not found
  63              return array();
  64            }
  65  
  66            // Set nodes to contain just this element
  67            $nodes = array($element);
  68  
  69            continue; // Skip to next token
  70          }
  71  
  72          $pos = strpos($token, '.');
  73          if (false !== $pos && preg_match('/^[A-Za-z0-9]*$/', substr($token, 0, $pos)))
  74          {
  75            // Token contains a class selector
  76            $tagName = substr($token, 0, $pos);
  77            if (!$tagName)
  78            {
  79              $tagName = '*';
  80            }
  81            $className = substr($token, $pos + 1);
  82  
  83            // Get elements matching tag, filter them for class selector
  84            $founds = $this->getElementsByTagName($nodes, $tagName, $combinator);
  85            $nodes = array();
  86            foreach ($founds as $found)
  87            {
  88              if (preg_match('/\b'.$className.'\b/', $found->getAttribute('class')))
  89              {
  90                $nodes[] = $found;
  91              }
  92            }
  93  
  94            continue; // Skip to next token
  95          }
  96  
  97          // Code to deal with attribute selectors
  98          if (preg_match('/^(\w*)(\[.+\])$/', $token, $matches))
  99          {
 100            $tagName = $matches[1] ? $matches[1] : '*';
 101            preg_match_all('/
 102              \[
 103                (\w+)                 # attribute
 104                ([=~\|\^\$\*]?)       # modifier (optional)
 105                =?                    # equal (optional)
 106                (
 107                  "([^"]*)"           # quoted value (optional)
 108                  |
 109                  ([^\]]*)            # non quoted value (optional)
 110                )
 111              \]
 112            /x', $matches[2], $matches, PREG_SET_ORDER);
 113  
 114            // Grab all of the tagName elements within current node
 115            $founds = $this->getElementsByTagName($nodes, $tagName, $combinator);
 116            $nodes = array();
 117            foreach ($founds as $found)
 118            {
 119              $ok = false;
 120              foreach ($matches as $match)
 121              {
 122                $attrName = $match[1];
 123                $attrOperator = $match[2];
 124                $attrValue = $match[4];
 125  
 126                switch ($attrOperator)
 127                {
 128                  case '=': // Equality
 129                    $ok = $found->getAttribute($attrName) == $attrValue;
 130                    break;
 131                  case '~': // Match one of space seperated words
 132                    $ok = preg_match('/\b'.preg_quote($attrValue, '/').'\b/', $found->getAttribute($attrName));
 133                    break;
 134                  case '|': // Match start with value followed by optional hyphen
 135                    $ok = preg_match('/^'.preg_quote($attrValue, '/').'-?/', $found->getAttribute($attrName));
 136                    break;
 137                  case '^': // Match starts with value
 138                    $ok = 0 === strpos($found->getAttribute($attrName), $attrValue);
 139                    break;
 140                  case '$': // Match ends with value
 141                    $ok = $attrValue == substr($found->getAttribute($attrName), -strlen($attrValue));
 142                    break;
 143                  case '*': // Match ends with value
 144                    $ok = false !== strpos($found->getAttribute($attrName), $attrValue);
 145                    break;
 146                  default :
 147                    // Just test for existence of attribute
 148                    $ok = $found->hasAttribute($attrName);
 149                }
 150  
 151                if (false == $ok)
 152                {
 153                  break;
 154                }
 155              }
 156  
 157              if ($ok)
 158              {
 159                $nodes[] = $found;
 160              }
 161            }
 162  
 163            continue; // Skip to next token
 164          }
 165  
 166          // If we get here, token is JUST an element (not a class or ID selector)
 167          $nodes = $this->getElementsByTagName($nodes, $token, $combinator);
 168        }
 169  
 170        foreach ($nodes as $node)
 171        {
 172          if (!$node->getAttribute('sf_matched'))
 173          {
 174            $node->setAttribute('sf_matched', true);
 175            $all_nodes[] = $node;
 176          }
 177        }
 178      }
 179  
 180      foreach ($all_nodes as $node)
 181      {
 182        $node->removeAttribute('sf_matched');
 183      }
 184  
 185      return $all_nodes;
 186    }
 187  
 188    protected function getElementsByTagName($nodes, $tagName, $combinator = ' ')
 189    {
 190      $founds = array();
 191      foreach ($nodes as $node)
 192      {
 193        switch ($combinator)
 194        {
 195          case ' ':
 196            foreach ($node->getElementsByTagName($tagName) as $element)
 197            {
 198              $founds[] = $element;
 199            }
 200            break;
 201          case '>':
 202            foreach ($node->childNodes as $element)
 203            {
 204              if ($tagName == $element->nodeName)
 205              {
 206                $founds[] = $element;
 207              }
 208            }
 209            break;
 210          case '+':
 211            $element = $node->childNodes->item(0);
 212            if ($element && $tagName == $element->nodeName)
 213            {
 214              $founds[] = $element;
 215            }
 216            break;
 217        }
 218      }
 219  
 220      return $founds;
 221    }
 222  
 223    protected function tokenize_selectors($selector)
 224    {
 225      // split tokens by , except in an attribute selector
 226      $tokens = array();
 227      $quoted = false;
 228      $token = '';
 229      for ($i = 0, $max = strlen($selector); $i < $max; $i++)
 230      {
 231        if (',' == $selector[$i] && !$quoted)
 232        {
 233          $tokens[] = trim($token);
 234          $token = '';
 235        }
 236        else if ('"' == $selector[$i])
 237        {
 238          $token .= $selector[$i];
 239          $quoted = $quoted ? false : true;
 240        }
 241        else
 242        {
 243          $token .= $selector[$i];
 244        }
 245      }
 246      if ($token)
 247      {
 248        $tokens[] = trim($token);
 249      }
 250  
 251      return $tokens;
 252    }
 253  
 254    protected function tokenize($selector)
 255    {
 256      // split tokens by space except if space is in an attribute selector
 257      $tokens = array();
 258      $combinators = array(' ', '>', '+');
 259      $quoted = false;
 260      $token = array('combinator' => ' ', 'name' => '');
 261      for ($i = 0, $max = strlen($selector); $i < $max; $i++)
 262      {
 263        if (in_array($selector[$i], $combinators) && !$quoted)
 264        {
 265          // remove all whitespaces around the combinator
 266          $combinator = $selector[$i];
 267          while (in_array($selector[$i + 1], $combinators))
 268          {
 269            if (' ' != $selector[++$i])
 270            {
 271              $combinator = $selector[$i];
 272            }
 273          }
 274  
 275          $tokens[] = $token;
 276          $token = array('combinator' => $combinator, 'name' => '');
 277        }
 278        else if ('"' == $selector[$i])
 279        {
 280          $token['name'] .= $selector[$i];
 281          $quoted = $quoted ? false : true;
 282        }
 283        else
 284        {
 285          $token['name'] .= $selector[$i];
 286        }
 287      }
 288      if ($token['name'])
 289      {
 290        $tokens[] = $token;
 291      }
 292  
 293      return $tokens;
 294    }
 295  }


Généré le : Fri Mar 16 22:42:14 2007 par Balluche grâce à PHPXref 0.7