Как обрабатывать двойные кавычки в строке перед оценкой XPath? - PullRequest
4 голосов
/ 27 января 2011

В приведенной ниже функции, когда строка в ключевом слове $ содержит двойные кавычки, она создает "Предупреждение: DOMXPath ::valu (): Неверное выражение" :

$keyword = 'This is "causing" an error';
$xPath->evaluate('boolean(//img[contains(@alt, "'.$keyword.'")])');

Что я должен сделать, чтобы подготовить $keyword для выражения вычисления xpath?

Полный код функции:

$keyword = trim(strtolower(rseo_getKeyword($post)));

function sx_function($heading, $post){
    $content = $post->post_content;
    if($content=="" || !class_exists('DOMDocument')) return false;
    $keyword = trim(strtolower(rseo_getKeyword($post)));
    @$dom = new DOMDocument;
    @$dom->loadHTML(strtolower($post->post_content));
    $xPath = new DOMXPath(@$dom);
    switch ($heading)
        {
        case "img-alt": return $xPath->evaluate('boolean(//img[contains(@alt, "'.$keyword.'")])');
        default: return $xPath->evaluate('boolean(/html/body//'.$heading.'[contains(.,"'.$keyword.'")])');
        }
}   

Ответы [ 2 ]

6 голосов
/ 10 октября 2012

PHP имеет Xpath 1.0, если у вас есть строка с двойными и одинарными кавычками, обходной путь - использование функции Xpath concat().Вспомогательная функция может решить, когда что использовать.Пример / Использование:

xpath_string('I lowe "double" quotes.');
// xpath:    'I lowe "double" quotes.'

xpath_string('It\'s my life.');
// xpath:    "It's my life."

xpath_string('Say: "Hello\'sen".');
// xpath:    concat('Say: "Hello', "'", "'sen".')

Вспомогательная функция:

/**
 * xpath string handling xpath 1.0 "quoting"
 *
 * @param string $input
 * @return string
 */
function xpath_string($input) {

    if (false === strpos($input, "'")) {
        return "'$input'";
    }

    if (false === strpos($input, '"')) {
        return "\"$input\"";
    }

    return "concat('" . strtr($input, array("'" => '\', "\'", \'')) . "')";
}
4 голосов
/ 27 января 2011

Чтобы избежать строковых разделителей в строковых литералах XPath 2.0 , необходимо заменить каждый отдельный разделитель на два, поэтому " необходимо заменить на "":

[74]      StringLiteral      ::=      ('"' (EscapeQuot | [^"])* '"') | ("'" (EscapeApos | [^'])* "'") /* ws: explicit */
[75]      EscapeQuot     ::=      '""'
[76]      EscapeApos     ::=      "''"

Я не уверен, есть ли уже функция для этого, но вы можете использовать эту функцию:

function xpath_quote($str, $quotation='"') {
    if ($quotation != '"' && $quotation != "'") return false;
    return str_replace($quotation, $quotation.$quotation, $str);
}

И использование:

'boolean(/html/body//'.$heading.'[contains(.,"'.xpath_quote($keyword).'")])'
...