2012-03-28 3 views
5

Ich suche das Web viel und fand keine C++ - Funktion, die XML-Sonderzeichen mit ihrer Escape-Sequenz ersetzen? Gibt es so etwas?Gibt es C++ - Funktion, die XML-Sonderzeichen mit ihrer Escape-Sequenz ersetzen?

Ich weiß um den folgenden:

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

ist es mehr? Was ist mit dem Schreiben hexadezimaler Wert wie 0 × 00, Ist das auch ein Problem?

+0

Warum es selbst tun? 5 string ersetzt zum Beispiel –

+0

@stefanbachert zuerst Ich weiß, es gibt mehr Sonderzeichen, lke Fremdsprachen und Währungszeichen, zweitens, was zu verhindern, Doppelcodierung? Ich möchte nicht doppelt codieren & .. und warum das Rad erfinden? vielleicht gibt es jemanden, der über Dinge nachdachte, mit denen ich nicht vertraut bin. –

+2

Die obigen 5 Standard-Spezialeinheiten werden durch XML selbst definiert. Andere Entitäten können durch den Doctype oder das Schema definiert werden. Am Ende könnte jeder Wesen definieren. Sie werden also keine Standardfunktion finden. –

Antwort

6

Wie bereits erwähnt, wäre es möglich, Ihre eigenen zu schreiben. Für example:

#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; 
} 

Ausgang:

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

einen Eintrag hinzufügen in transformations neue Transformationen einzuführen.

2

Es ist eine Funktion, ich habe es nämlich gerade geschrieben habe:

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; 
} 
0

Es scheint, dass Sie XML selbst generieren möchten. Ich denke, dass Sie viel klarer sein müssen, und lesen Sie die XML-Spezifikation, wenn Sie erfolgreich sein wollen. Das sind die einzigen XML-Sonderzeichen, Sie sagen "Ich weiß, dass es mehr Sonderzeichen, Fremdsprachen und Währungszeichen gibt" ... diese sind nicht in XML definiert, außer Sie meinen das durch Codieren als Codepunkte (& # 163; Beispiel)). Denkst du an HTML oder eine andere DTD?

Die einzige Möglichkeit, doppelte Codierung zu vermeiden, besteht darin, die Objekte nur einmal zu codieren. Wenn Sie die Zeichenfolge "& gt;" erhalten, woher wissen Sie, ob es bereits codiert ist und ich die Zeichenfolge ">" darstellen wollte, oder ich möchte die Zeichenfolge "& gt;" darstellen.

Der beste Weg ist, Ihre XML als DOM darstellen (mit Strings als un-kodierten Strings), und verwenden Sie und XML Serializer wie Xerces

Oh, und denken Sie daran gibt es keine Möglichkeit, Zeichen unter 0x20 in XML darzustellen (außer & x9; & xA; und & xD; - Leerzeichen).

+0

Die meisten XML-Generatoren und XML-Reader sind sehr großzügig mit Zeichen unter 0x20; Das wäre also kein großes Problem. Der xml 1.1-Standard akzeptiert sie sogar formal (als Zeichenreferenzen, nicht die Zeichen selbst). Die Ausnahme ist 0x00, was in keiner Form erlaubt ist. –

+0

@MrLister dies lesen http://seattlesoftware.wordpress.com/2008/09/11/hexadecimal-value-0-is-an-invalid-character/ –

+0

Ja, dieser Artikel bestätigt, dass Sie nicht 0x00 Zeichen in speichern können eine XML-Datei und demonstriert, wie sie entfernt werden. Hilft dir das? –

10

Schreiben Sie Ihre eigenen leicht genug, aber das Scannen der Zeichenfolge mehrmals einzelne Zeichen suchen/ersetzen kann ineffizient sein:

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(); 
} 

Anmerkung: Ich habe eine C++ 11 bereichsbasierte for-Schleife für die Bequemlichkeit , aber Sie können das gleiche mit einem Iterator leicht tun.

1

Ich modifizierte leicht Ferruccios Lösung, um auch die anderen Zeichen zu eliminieren, die in der Art sind, wie irgendetwas < 0x20 und so weiter (irgendwo im Internet gefunden). Getestet und funktioniert.

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; 

Also in diesem Fall gibt es zwei Funktionen. Wir können das Ergebnis mit etwas wie erhalten:

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

Hoffe es hilft!

(Oh yeah: Kredit für die andere Funktion geht an den Autor der Antwort hier: How do you remove invalid hexadecimal characters from an XML-based data source prior to constructing an XmlReader or XPathDocument that uses the data?)

5

Diese Arten von Funktionen sollten Standard sein, und wir sollten sie nie umschreiben. Wenn Sie VS verwenden, sehen Sie sich atlenc.h an Diese Datei ist Teil der VS-Installation. Innerhalb der Datei gibt es eine Funktion namens EscapeXML, die viel vollständiger ist als jedes der obigen Beispiele.