function match_selector($selector, $root) { switch ($selector[0]) { case SELECTOR_TAG: if ($selector[1] == strtolower($root->tagname())) { return true; } break; case SELECTOR_ID: if ($selector[1] == strtolower($root->get_attribute('id'))) { return true; } break; case SELECTOR_CLASS: if (node_have_class($root, $selector[1])) { return true; } if ($selector[1] == strtolower($root->get_attribute('class'))) { return true; } break; case SELECTOR_TAG_CLASS: if (node_have_class($root, $selector[2]) && $selector[1] == strtolower($root->tagname())) { return true; } break; case SELECTOR_SEQUENCE: foreach ($selector[1] as $subselector) { if (!match_selector($subselector, $root)) { return false; } } return true; case SELECTOR_PARENT: case SELECTOR_PARENT_LOW_PRIORITY: $node = $root->parent(); while ($node && $node->node_type() == XML_ELEMENT_NODE) { if (match_selector($selector[1], $node)) { return true; } $node = $node->parent(); } return false; case SELECTOR_DIRECT_PARENT: $node = $root->parent(); if ($node && $node->node_type() == XML_ELEMENT_NODE) { if (match_selector($selector[1], $node)) { return true; } } return false; case SELECTOR_ATTR: $attr_name = $selector[1]; return $root->has_attribute($attr_name); case SELECTOR_ATTR_VALUE: // Note that CSS 2.1 standard does not says strictly if attribute case // is significiant: // """ // Attribute values must be identifiers or strings. The case-sensitivity of attribute names and // values in selectors depends on the document language. // """ // As we've met several problems with pages having INPUT type attributes in upper (or ewen worse - mixed!) // case, the following decision have been accepted: attribute values should not be case-sensitive $attr_name = $selector[1]; $attr_value = $selector[2]; if (!$root->has_attribute($attr_name)) { return false; } return strtolower($root->get_attribute($attr_name)) == strtolower($attr_value); case SELECTOR_ATTR_VALUE_WORD: // Note that CSS 2.1 standard does not says strictly if attribute case // is significiant: // """ // Attribute values must be identifiers or strings. The case-sensitivity of attribute names and // values in selectors depends on the document language. // """ // As we've met several problems with pages having INPUT type attributes in upper (or ewen worse - mixed!) // case, the following decision have been accepted: attribute values should not be case-sensitive $attr_name = $selector[1]; $attr_value = $selector[2]; if (!$root->has_attribute($attr_name)) { return false; } $words = preg_split("/\\s+/", $root->get_attribute($attr_name)); foreach ($words as $word) { if (strtolower($word) == strtolower($attr_value)) { return true; } } return false; case SELECTOR_PSEUDOCLASS_LINK: return $root->tagname() == "a" && $root->has_attribute('href'); case SELECTOR_PSEUDOCLASS_LINK_LOW_PRIORITY: return $root->tagname() == "a" && $root->has_attribute('href'); // Note that :before and :after always match // Note that :before and :after always match case SELECTOR_PSEUDOELEMENT_BEFORE: return true; case SELECTOR_PSEUDOELEMENT_AFTER: return true; case SELECTOR_LANGUAGE: // FIXME: determine the document language return true; case SELECTOR_ANY: return true; } return false; }
function match($root) { return match_selector($this->selector, $root); }