用boost精神解析html转义序列

Parse html escape sequence with boost spirit

我尝试用 html 转义序列解析文本,并想用 utf8 等价物来改变这个转义:

  - 0xC2A0 utf8 representation
­ - 0xC2AD utf8 representation

并且有语法来解决这个问题

template <typename Iterator>
struct HTMLEscape_grammar : qi::grammar<Iterator, std::string()>
{
    HTMLEscape_grammar() :
        HTMLEscape_grammar::base_type(text)
    {
        htmlescapes.add("&nbsp;", 0xC2AD);
        htmlescapes.add("&shy;", 0xC2AD);

        text = +((+(qi::char_ - htmlescapes)) | htmlescapes);
    }

private:
    qi::symbols<char, uint32_t> htmlescapes;
    qi::rule<Iterator, std::string()> text;
};

但是当我们解析

std::string l_test = "test&shy;as test simple&shy;test";
HTMLEscape_grammar<std::string::const_iterator> l_gramar;

std::string l_ast;
bool result = qi::parse(l_test.begin(), l_test.end(), l_gramar, l_ast);

我们没有得到utf-8字符串,utf8符号的0xC2部分简单的切掉了,我们得到的只是ascii字符串。此解析器是更强大系统的构建块,因此需要 utf8 输出。

我不知道您如何认为公开 uint32_t 会神奇地输出 UNICODE 代码点。更不用说某些东西会为此神奇地执行 UTF8 编码了。

现在让我说清楚。您希望将选择的 HTML 实体引用 替换为 슭(HANGUL SYLLABLE SEULG)。在 UTF-8 中是 0xEC 0x8A 0xAD。

只需自己进行编码(无论如何,您正在编写一个 UTF8 代码单元的输出流):

Live On Coliru

#include <boost/spirit/include/qi.hpp>
#include <iostream>
#include <iomanip>

namespace qi = boost::spirit::qi;

template <typename Iterator>
struct HTMLEscape_grammar : qi::grammar<Iterator, std::string()>
{
    HTMLEscape_grammar() :
        HTMLEscape_grammar::base_type(text)
    {
        htmlescapes.add("&nbsp;", { '\xEC', '\x8A', '\xAD' });
        htmlescapes.add("&shy;",  { '\xEC', '\x8A', '\xAD' });

        text = *(htmlescapes | qi::char_);
    }

private:
    qi::symbols<char, std::vector<char> > htmlescapes;
    qi::rule<Iterator, std::string()> text;
};

int main() {
    std::string const l_test = "test&shy;as test simple&shy;test";
    HTMLEscape_grammar<std::string::const_iterator> l_gramar;

    std::string l_ast;
    bool result = qi::parse(l_test.begin(), l_test.end(), l_gramar, l_ast);

    if (result) {
        std::cout << "Parse success\n";
        for (unsigned char ch : l_ast)
            std::cout << std::setw(2) << std::setfill('0') << std::hex << std::showbase << static_cast<int>(ch) << " ";
    } else
    {
        std::cout << "Parse failure\n";
    }
}

版画

Parse success
0x74 0x65 0x73 0x74 0xec 0x8a 0xad 0x61 0x73 0x20 0x74 0x65 0x73 0x74 0x20 0x73 0x69 0x6d 0x70 0x6c 0x65 0xec 0x8a 0xad 0x74 0x65 0x73 0x74