Esempio n. 1
0
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);
 }