Каким будет аналог Boost::regexp для функции PHP`preg_match_all`?

Итак, у меня есть такая функция php, которую я хочу перевести на C++:

protected function htmlTag($content, $tag, $attrName, $attrValue, $valueName)
{
    preg_match_all("#<{$tag}[^>]*$attrName=['\"].*?$attrValue.*?['\"][^>]*$valueName=['\"](.+?)['\"][^>]*/?>#i", $content, $matches1);
    preg_match_all("#<{$tag}[^>]*$valueName=['\"](.+?)['\"][^>]*$attrName=['\"].*?$attrValue.*?['\"][^>]*/?>#i", $content, $matches2);

    $result = array_merge($matches1[1], $matches2[1]);
    return empty($result)?false:$result[0];
}

использовать пример:

            $location = $this->htmlTag($content, 'meta', 'http-equiv', 'X-XRDS-Location', 'content');
            $server   = $this->htmlTag($content, 'link', 'rel', 'openid.server', 'href');
            $delegate = $this->htmlTag($content, 'link', 'rel', 'openid.delegate', 'href');

(контент является результатом $content= curl_exec($curl);)

preg_match_all — ищет предмет для всех совпадений с регулярным выражением данных в шаблоне и помещает их в совпадения в порядке, указанном флагами. После того, как найдено первое совпадение, последующие поиски продолжаются с конца последнего совпадения.

Как это перевести с помощью boost::regexp?


person Rella    schedule 17.07.2011    source источник
comment
Не могли бы вы объяснить нам словами, что на самом деле должна делать эта функция или для чего она используется? Вы также можете взглянуть на этот предыдущий вопрос: stackoverflow.com/questions/1732348/   -  person John Zwinck    schedule 17.07.2011
comment
Я знаю, что синтаксический анализ xml (html\xhtml) через регулярное выражение плохой. Но мне очень нужно, чтобы он работал так, как это было в php...   -  person Rella    schedule 17.07.2011


Ответы (1)


Что-то вроде этого:

boost::optional<std::string> htmlTag(const std::string& content,
    const std::string& tag, const std::string& attrName,
    const std::string& attrValue, const std::string& valueName)
{
    const std::string
        expr1 = boost::format("#<%1[^>]*%2=['\"].*?%3.*?['\"][^>]"
                "*%4=['\"](.+?)['\"][^>]*/?>#i")
                % tag % attrName % attrValue % valueName,
        expr2 = boost::format("#<%1[^>]*%2=['\"](.+?)['\"][^>]*"
                "%3=['\"].*?%4.*?['\"][^>]*/?>#i")
                % tag % attrName % attrValue % valueName;

    boost::match_results<std::string::const_iterator>
        matches1, matches2, result;

    // do the searches (note: these probably need to be loops as shown at the bottom of this page:
    // http://www.boost.org/doc/libs/1_47_0/libs/regex/doc/html/boost_regex/ref/regex_search.html
    if (!regex_search(content, matches1, expr1))
        return boost::none;
    if (!regex_search(content, matches2, expr2))
        return boost::none;

    result = // merge matches1[1] and matches2[1] somehow
    if (result.empty())
        return boost::none;
    else
        return result[0];
}

Я уверен, что ошибся в некоторых деталях (во-первых, я думаю, что вам нужно снова и снова вызывать regex_search в соответствии с комментарием), но, надеюсь, вы сможете проработать эти детали и опубликовать готовое решение.

person John Zwinck    schedule 17.07.2011
comment
Насколько я вижу, array_merge похож на (заменить, если существует | | присоединяйтесь)... Позже я опубликую свои результаты портирования lightopenid на каком-нибудь проекте google code. - person Rella; 17.07.2011
comment
Возможно, вы сможете эмулировать это с помощью std::set_union (matches2 будет идти перед match1, так что его значениям отдается предпочтение. - person John Zwinck; 17.07.2011