Существует ли функция c ++, которая заменяет специальный символ xml своей escape-последовательностью? - PullRequest
6 голосов
/ 28 марта 2012

Я много раз искал в Интернете и не нашел функцию c ++, которая заменяет специальный символ xml их escape-последовательностью?Есть ли что-то подобное?

Я знаю следующее:

Special Character   Escape Sequence Purpose  
&                   &           Ampersand sign 
'                   '          Single quote 
"                   "          Double quote
>                   >            Greater than 
<                   &lt;            Less than

есть еще?как насчет записи шестнадцатеричного значения, такого как 0 × 00, это тоже проблема?

Ответы [ 6 ]

10 голосов
/ 28 марта 2012

Написание собственного достаточно просто, но сканирование строки несколько раз для поиска / замены отдельных символов может быть неэффективным:

std::string escape(const std::string& src) {
    std::stringstream dst;
    for (char ch : src) {
        switch (ch) {
            case '&': dst << "&amp;"; break;
            case '\'': dst << "&apos;"; break;
            case '"': dst << "&quot;"; break;
            case '<': dst << "&lt;"; break;
            case '>': dst << "&gt;"; break;
            default: dst << ch; break;
        }
    }
    return dst.str();
}

Примечание.удобство, но вы можете легко сделать то же самое с итератором.

6 голосов
/ 12 февраля 2014

Эти типы функций должны быть стандартными, и нам никогда не придется их переписывать. Если вы используете VS, взгляните на atlenc.h Этот файл является частью установки VS. Внутри файла есть функция EscapeXML, которая гораздо более полна, чем любой из приведенных выше примеров.

6 голосов
/ 28 марта 2012

Как уже было сказано, можно было бы написать свой собственный.Для пример :

#include <iostream>
#include <string>
#include <map>

int main()
{
    std::string xml("a < > & ' \" string");
    std::cout << xml << "\n";

    // Characters to be transformed.
    //
    std::map<char, std::string> transformations;
    transformations['&']  = std::string("&amp;");
    transformations['\''] = std::string("&apos;");
    transformations['"']  = std::string("&quot;");
    transformations['>']  = std::string("&gt;");
    transformations['<']  = std::string("&lt;");

    // Build list of characters to be searched for.
    //
    std::string reserved_chars;
    for (auto ti = transformations.begin(); ti != transformations.end(); ti++)
    {
        reserved_chars += ti->first;
    }

    size_t pos = 0;
    while (std::string::npos != (pos = xml.find_first_of(reserved_chars, pos)))
    {
        xml.replace(pos, 1, transformations[xml[pos]]);
        pos++;
    }

    std::cout << xml << "\n";

    return 0;
}

Вывод:

a < > & ' " string
a &lt; &gt; &amp; &apos; &quot; string

Добавить запись в transformations для введения новых преобразований.

2 голосов
/ 28 марта 2012

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

void replace_all(std::string& str, const std::string& old, const std::string& repl) {
    size_t pos = 0;
    while ((pos = str.find(old, pos)) != std::string::npos) {
        str.replace(pos, old.length(), repl);
        pos += repl.length();
    }
}

std::string escape_xml(std::string str) {
    replace_all(str, std::string("&"), std::string("&amp;"));
    replace_all(str, std::string("'"), std::string("&apos;"));
    replace_all(str, std::string("\""), std::string("&quot;"));
    replace_all(str, std::string(">"), std::string("&gt;"));
    replace_all(str, std::string("<"), std::string("&lt;"));

    return str;
}
1 голос
/ 11 мая 2012

Я немного модифицировал решение Ферруччо, чтобы также исключить другие находящиеся в пути символы, например что-либо <0x20 и т. Д. (Найденные где-то в Интернете).Протестировано и работает. </p>

    void strip_tags(string* s) {
    regex kj("</?(.*)>");
    *s = regex_replace(*s, kj, "", boost::format_all);

    std::map<char, std::string> transformations;
    transformations['&']  = std::string("&amp; ");
    transformations['\''] = std::string("&apos; ");
    transformations['"']  = std::string("&quot; ");
    transformations['>']  = std::string("&gt; ");
    transformations['<']  = std::string("&lt; ");

  // Build list of characters to be searched for.
    //
    std::string reserved_chars;
    for ( std::map<char, std::string>::iterator ti = transformations.begin(); ti != transformations.end(); ti++)
    {
        reserved_chars += ti->first;
    }

    size_t pos = 0;
    while (std::string::npos != (pos = (*s).find_first_of(reserved_chars, pos)))
    {
        s->replace(pos, 1, transformations[(*s)[pos]]);
        pos++;
    }



}


string removeTroublesomeCharacters(string inString)
{

    if (inString.empty()) return "";

    string newString;
    char ch;

    for (int i = 0; i < inString.length(); i++)
    {

        ch = inString[i];
        // remove any characters outside the valid UTF-8 range as well as all control characters
        // except tabs and new lines
        if ((ch < 0x00FD && ch > 0x001F) || ch == '\t' || ch == '\n' || ch == '\r')
        {
            newString.push_back(ch);
        }
    }
    return newString;

Так что в этом случае есть две функции.Мы можем получить результат с помощью чего-то вроде:

string StartingString ("Some_value");
string FinalString = removeTroublesomeCharacters(strip_tags(&StartingString));

Надеюсь, что это поможет!

(Ах да: кредит на другую функцию идет к автору ответа здесь: Какудалить недопустимые шестнадцатеричные символы из источника данных на основе XML до создания XmlReader или XPathDocument, который использует данные? )

0 голосов
/ 28 марта 2012

Похоже, вы хотите создать XML самостоятельно. Я думаю, что вам нужно быть намного понятнее и читать спецификацию XML, если вы хотите добиться успеха. Это единственные специальные символы XML, вы говорите: «Я знаю, что есть больше специальных символов, таких как иностранные языки и знаки валюты» ... они не определены в XML, если вы не подразумеваете кодирование как кодовые точки (например, £). Вы думаете HTML или какой-то другой DTD?

Единственный способ избежать двойного кодирования - это кодировать вещи только один раз. Если вы получили строку "& gt;", как вы узнаете, если она уже закодирована, и я хочу представить строку ">", или я хочу представить строку "& gt;".

Лучший способ - представить ваш XML в виде DOM (со строками в виде некодированных строк) и использовать XML-сериализатор, например, Xerces

Да, и помните, что в XML нет возможности представлять символы размером менее 0x20 (кроме & x9 ;, & xA; и & xD; - пробела).

...