private static function transformAttrSelector($expression)
    {
        if (preg_match('|@?([a-z0-9_]+)(([\!\*\^\$\~\|]{0,1})=)[\'"]([^\'"]+)[\'"]|i', $expression, $matches)) {
            if ($matches[3] === '') { // arbitrary attribute strict value equality
                return '[@' . strtolower($matches[1]) . "='" . $matches[4] . "']";
            } elseif ($matches[3] === '!') { // arbitrary attribute negation strict value
                return '[@' . strtolower($matches[1]) . "!='" . $matches[4] . "']";
            } elseif ($matches[3] === '~') { // arbitrary attribute value contains full word
                return "[contains(concat(' ', normalize-space(@" . strtolower($matches[1]) . "), ' '), ' ". $matches[4] . " ')]";
            } elseif ($matches[3] === '*') {  // arbitrary attribute value contains specified content
                return "[contains(@" . strtolower($matches[1]) . ", '" . $matches[4] . "')]";
            } elseif ($matches[3] === '^') { // attribute value starts with specified content
                return "[starts-with(@" . strtolower($matches[1]) . ", '" . $matches[4] . "')]";
            } elseif ($matches[3] === '$') { // attribute value ends with specified content
                return "[@".$matches[1]." and substring(@".$matches[1].", string-length(@".$matches[1].")-".
                (\strlen($matches[4])-1).") = '".$matches[4]."']";
            } elseif ($matches[3] === '|') { // attribute has prefix selector
                return '[@' . strtolower($matches[1]) . "='" . $matches[4] . "' or starts-with(@".
                strtolower($matches[1]) . ", '" . $matches[4].'-' . "')]";
            }
        }

        // attribute without value
        if (preg_match('|([a-z0-9_]{1})([a-z0-9_-]*)|i', $expression, $matches)) {
            return "[@" . $matches[1].$matches[2] . "]";
        }

        throw new \Exception('Attribute selector is malformed or contains unsupported characters.');
    }
private static function transformAttrSelector($expression)
    {
        if (preg_match('|@?([a-z0-9_]+)(([\!\*\^\$\~\|]{0,1})=)[\'"]([^\'"]+)[\'"]|i', $expression, $matches)) {
            if ($matches[3] === '') { // arbitrary attribute strict value equality
                return '[@' . strtolower($matches[1]) . "='" . $matches[4] . "']";
            } elseif ($matches[3] === '!') { // arbitrary attribute negation strict value
                return '[@' . strtolower($matches[1]) . "!='" . $matches[4] . "']";
            } elseif ($matches[3] === '~') { // arbitrary attribute value contains full word
                return "[contains(concat(' ', normalize-space(@" . strtolower($matches[1]) . "), ' '), ' ". $matches[4] . " ')]";
            } elseif ($matches[3] === '*') {  // arbitrary attribute value contains specified content
                return "[contains(@" . strtolower($matches[1]) . ", '" . $matches[4] . "')]";
            } elseif ($matches[3] === '^') { // attribute value starts with specified content
                return "[starts-with(@" . strtolower($matches[1]) . ", '" . $matches[4] . "')]";
            } elseif ($matches[3] === '$') { // attribute value ends with specified content
                return "[@".$matches[1]." and substring(@".$matches[1].", string-length(@".$matches[1].")-".
                (\strlen($matches[4])-1).") = '".$matches[4]."']";
            } elseif ($matches[3] === '|') { // attribute has prefix selector
                return '[@' . strtolower($matches[1]) . "='" . $matches[4] . "' or starts-with(@".
                strtolower($matches[1]) . ", '" . $matches[4].'-' . "')]";
            }
        }

        // attribute without value
        if (preg_match('|([a-z0-9_]{1})([a-z0-9_-]*)|i', $expression, $matches)) {
            return "[@" . $matches[1].$matches[2] . "]";
        }

        throw new \Exception('Attribute selector is malformed or contains unsupported characters.');
    }
private static function transformAttrSelector ( $ expression ) { if ( preg_match ( '|@?([a-z0-9_]+)(([\!\*\^\$\~\|]{0,1})=)[\'"]([^\'"]+)[\'"]|i' , $ expression , $ matches ) ) { if ( $ matches [ 3 ] === '' ) { // arbitrary attribute strict value equality return '[@' . strtolower ( $ matches [ 1 ] ) . "='" . $ matches [ 4 ] . "']" ; } elseif ( $ matches [ 3 ] === '!' ) { // arbitrary attribute negation strict value return '[@' . strtolower ( $ matches [ 1 ] ) . "!='" . $ matches [ 4 ] . "']" ; } elseif ( $ matches [ 3 ] === '~' ) { // arbitrary attribute value contains full word return "[contains(concat(' ', normalize-space(@" . strtolower ( $ matches [ 1 ] ) . "), ' '), ' " . $ matches [ 4 ] . " ')]" ; } elseif ( $ matches [ 3 ] === '*' ) { // arbitrary attribute value contains specified content return "[contains(@" . strtolower ( $ matches [ 1 ] ) . ", '" . $ matches [ 4 ] . "')]" ; } elseif ( $ matches [ 3 ] === '^' ) { // attribute value starts with specified content return "[starts-with(@" . strtolower ( $ matches [ 1 ] ) . ", '" . $ matches [ 4 ] . "')]" ; } elseif ( $ matches [ 3 ] === '$' ) { // attribute value ends with specified content return "[@" . $ matches [ 1 ] . " and substring(@" . $ matches [ 1 ] . ", string-length(@" . $ matches [ 1 ] . ")-" . ( \ strlen ( $ matches [ 4 ] ) - 1 ) . ") = '" . $ matches [ 4 ] . "']" ; } elseif ( $ matches [ 3 ] === '|' ) { // attribute has prefix selector return '[@' . strtolower ( $ matches [ 1 ] ) . "='" . $ matches [ 4 ] . "' or starts-with(@" . strtolower ( $ matches [ 1 ] ) . ", '" . $ matches [ 4 ] . '-' . "')]" ; } } // attribute without value if ( preg_match ( '|([a-z0-9_]{1})([a-z0-9_-]*)|i' , $ expression , $ matches ) ) { return "[@" . $ matches [ 1 ] . $ matches [ 2 ] . "]" ; } throw new \ Exception ( 'Attribute selector is malformed or contains unsupported characters.' ) ; }
Transform 'css attribute selector' expression to xpath expression

@param string $expression

@return string transformed expression (xpath)
Transform css attribute selector expression to xpath expression