Was sind ungültige Zeichen in XML

228

Ich arbeite mit XML, das Zeichenfolgen enthält wie:

<node>This is a string</node>

Einige der Saiten , dass ich zu den Knoten am Übergang haben Zeichen wie &, #, $, etc .:

<node>This is a string & so is this</node>

Dies gilt nicht wegen &.

Ich kann diese Zeichenfolgen nicht in CDATA einbinden, da sie so sein müssen, wie sie sind. Ich habe versucht, nach einer Liste von Zeichen zu suchen, die nicht in XML-Knoten eingefügt werden können, ohne sich in einer CDATA zu befinden.

Kann mich jemand in die Richtung eines zeigen oder mir eine Liste illegaler Charaktere geben?

RailsSon
quelle
4
Gibt es einen gültigen Grund für die Nichtverwendung von CDATA?
Peter Perháč
1
Ja, ich übergebe die Zeichenfolge an ein CMS namens Fatwire und der Knoten mit den Daten kann sich nicht in einer CDATA befinden. Ich bin mir nicht sicher, warum Fatwire so funktioniert :(
RailsSon
@Peter: Wie kann ich CDATA in meinem Fall verwenden? stackoverflow.com/questions/6906705/…
Radek

Antworten:

147

Die einzigen ungültigen Zeichen sind &, <und >(wie auch "oder 'in Attribute).

Sie werden mithilfe von XML-Entitäten maskiert , in diesem Fall &amp;für &.

In Wirklichkeit sollten Sie jedoch ein Tool oder eine Bibliothek verwenden, die XML für Sie schreibt und solche Dinge für Sie abstrahiert, damit Sie sich darüber keine Sorgen machen müssen.

Welbog
quelle
82
Einige Steuerzeichen sind ebenfalls nicht zulässig. Siehe meine Antwort unten.
Dolmen
43
Eigentlich stimmt das nicht ganz. Einige niedrigere ASCII-Zeichen sind ebenfalls ungültig. Wenn Sie versuchen, 0x03 in ein XML-Dokument zu schreiben, wird normalerweise eine Fehlermeldung angezeigt. Wenn Sie es schaffen, es ordnungsgemäß in ein XML-Dokument zu maskieren, beschweren sich die meisten Betrachter über das ungültige Zeichen. Rand Fall, aber es passiert.
Rick Strahl
16
Diese Antwort ist absolut falsch. Hier ist meine XML-Ausnahme mit dem unzulässigen 0x12-Zeichen 'System.Xml.XmlException:' ', Hexadezimalwert 0x12, ist ein ungültiges Zeichen'
George
8
Es ist auch in der anderen Richtung falsch; Neben dem Fehlen jedes einzelnen illegalen Zeichens sind die von ihm behaupteten illegalen Zeichen vollkommen legal, wenn auch mit besonderer Bedeutung im Kontext.
Jon Hanna
6
In XML 1.0 gibt es viele unzulässige Zeichen. Selbst die Verwendung einer Zeichenentität für die meisten Steuerzeichen führt beim Parsen zu einem Fehler.
Thayne
218

OK, lassen Sie uns die Frage der Zeichen trennen, die:

  1. sind in keinem XML-Dokument gültig.
  2. müssen entkommen werden.

Die Antwort von @dolmen in " Was sind ungültige Zeichen in XML ?" Ist weiterhin gültig, muss jedoch mit der XML 1.1-Spezifikation aktualisiert werden.

1. Ungültige Zeichen

Die hier beschriebenen Zeichen sind alle Zeichen, die in ein XML-Dokument eingefügt werden dürfen.

1.1. In XML 1.0

Die globale Liste der zulässigen Zeichen lautet:

[2] Char ::= #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF] /* any Unicode character, excluding the surrogate blocks, FFFE, and FFFF. */

Grundsätzlich sind Steuerzeichen und Zeichen außerhalb der Unicode-Bereiche nicht zulässig. Dies bedeutet auch, dass das Aufrufen beispielsweise der Zeichenentität &#x3;verboten ist.

1.2. In XML 1.1

Die globale Liste der zulässigen Zeichen lautet:

[2] Char ::= [#x1-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF] /* any Unicode character, excluding the surrogate blocks, FFFE, and FFFF. */

[2a] RestrictedChar ::= [#x1-#x8] | [#xB-#xC] | [#xE-#x1F] | [#x7F-#x84] | [#x86-#x9F]

Diese Überarbeitung der XML-Empfehlung hat die zulässigen Zeichen erweitert, sodass Steuerzeichen zulässig sind, und berücksichtigt eine neue Überarbeitung des Unicode-Standards. Diese sind jedoch weiterhin nicht zulässig: NUL (x00) , xFFFE , xFFFF ...

Von der Verwendung von Steuerzeichen und undefinierten Unicode-Zeichen wird jedoch abgeraten.

Es kann auch festgestellt werden, dass dies nicht immer von allen Parsern berücksichtigt wird und XML-Dokumente mit Steuerzeichen möglicherweise abgelehnt werden.

2. Zeichen, die maskiert werden müssen (um ein wohlgeformtes Dokument zu erhalten):

Das <muss mit einer &lt;Entität maskiert werden, da davon ausgegangen wird, dass es der Anfang eines Tags ist.

Das &muss mit einer &amp;Entität maskiert werden, da davon ausgegangen wird, dass es der Anfang einer Entitätsreferenz ist

Das >sollte mit &gt;Entität maskiert werden. Es ist nicht obligatorisch - es hängt vom Kontext ab - aber es wird dringend empfohlen, ihm zu entkommen.

Das 'sollte mit einer &apos;Entität maskiert werden - obligatorisch in Attributen, die in einfachen Anführungszeichen definiert sind. Es wird jedoch dringend empfohlen, diese immer zu maskieren.

Das "sollte mit einer &quot;Entität maskiert werden - obligatorisch in Attributen, die in doppelten Anführungszeichen definiert sind. Es wird jedoch dringend empfohlen, diese immer zu maskieren.

Potame
quelle
171

Die Liste der gültigen Zeichen befindet sich in der XML-Spezifikation :

Char       ::=      #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF]  /* any Unicode character, excluding the surrogate blocks, FFFE, and FFFF. */
Dolmen
quelle
7
Sie sollten beachten, dass sie zwar legale Zeichen & < > " 'sind, in bestimmten Kontexten jedoch maskiert werden müssen.
D. Shawley
7
"Legal" bedeutet in diesem Zusammenhang, dass ihre endgültig dekodierten Werte legal sind und nicht, dass sie im Stream legal sind. Wie oben müssen einige rechtliche Werte im Stream maskiert werden.
SilverbackNet
Ich habe ein Problem, bei dem 0x1c ein illegaler Charakter ist ... Ich suche nach einer Möglichkeit in Java, wie
ich
Eine schöne Übersicht, welche Zeichen gültig sind und welche nicht, finden Sie hier validchar.com/d/xml10/xml10_namestart
Dr. Max Völkel
8
@xamde Diese Liste ist nett, zeigt aber nur die Zeichen, die zum Starten eines XML-Elements verwendet werden können. Es geht darum, welche Zeichen in einer XML-Datei im Allgemeinen gültig sind. Es gibt bestimmte Zeichen, die nirgendwo erlaubt sind.
Jon Senchyna
59

Dies ist ein C # -Code zum Entfernen der ungültigen XML-Zeichen aus einer Zeichenfolge und zum Zurückgeben einer neuen gültigen Zeichenfolge.

public static string CleanInvalidXmlChars(string text) 
{ 
    // From xml spec valid chars: 
    // #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF]     
    // any Unicode character, excluding the surrogate blocks, FFFE, and FFFF. 
    string re = @"[^\x09\x0A\x0D\x20-\uD7FF\uE000-\uFFFD\u10000-\u10FFFF]"; 
    return Regex.Replace(text, re, ""); 
}
mathifonseca
quelle
6
Für Java wäre das Regex-Muster dasselbe. Und dann können Sie die Methode replaceAll in der Klasse String verwenden, die ein Regex-Muster als Parameter erwartet. Überprüfen Sie dies: docs.oracle.com/javase/6/docs/api/java/lang/…
mathifonseca
2
Ich habe solche ungültigen Zeichen in meiner Zeichenfolge: SUSITARIMO D & # x5; L DARBO SUTARTIES Dieser Code entfernt & # x5; Das XML-Dokument kann also nicht initiiert werden.
Dainius Kreivys
Ich glaube, Sie können dieses Muster nicht einfach in einen .NET-Regex-Konstruktor einfügen. Ich glaube nicht, dass es erkennt \u10000und \u10FFFFals einzelne Zeichen, da sie jeweils zwei utf-16- charInstanzen erfordern , und laut den Dokumenten gibt es möglicherweise nicht mehr als 4 Ziffern. [\u10000-\u10FFFF]höchstwahrscheinlich als [analysiert wird \u1000, 0-\u10FF, F, F] , das ist seltsam aus , aber legal.
GSerg
17

Die zuvor deklarierten Zeichen sind:

& < > " '

Weitere Informationen finden Sie unter " Was sind die Sonderzeichen in XML? ".

cgp
quelle
Falsch. Diese sind nicht alle ungültig. Nur & und <sind im Text immer ungültig.
rghome
7

Zusätzlich zu Potames Antwort, wenn Sie mit einem CDATA-Block entkommen möchten.

Wenn Sie Ihren Text in einen CDATA-Block einfügen, müssen Sie kein Escapezeichen verwenden . In diesem Fall können Sie alle Zeichen im folgenden Bereich verwenden :

grafische Darstellung möglicher Zeichen

Hinweis: Darüber hinaus dürfen Sie die ]]>Zeichenfolge nicht verwenden. Weil es mit dem Ende des CDATA-Blocks übereinstimmen würde.

Wenn es immer noch ungültige Zeichen gibt (z. B. Steuerzeichen), ist es wahrscheinlich besser, eine Art Codierung zu verwenden (z. B. base64).

bvdb
quelle
3
Ob in einem CDATA-Block oder nicht, einige Zeichen sind in XML verboten.
Dolmen
4
Genau, habe ich das nicht geschrieben? Zitat: "Alle Zeichen im folgenden Bereich ". Damit meine ich nur die Zeichen in diesem bestimmten Bereich. Andere Zeichen sind nicht erlaubt. - Stimme voll zu ; aber ich verstehe die Ablehnung nicht. - Keine harten Gefühle.
Bvdb
6

Ein weiterer einfacher Weg, um potenziell unerwünschten XML / XHTML-Zeichen in C # zu entkommen, ist:

WebUtility.HtmlEncode(stringWithStrangeChars)
tiands
quelle
Ungültige Zeichen
Dolmen
1
Er schrieb Xml nicht Html.
Emanuele
6

Eine andere Möglichkeit, falsche XML-Zeichen in C # zu entfernen, ist die Verwendung von XmlConvert.IsXmlChar(Verfügbar seit .NET Framework 4.0).

public static string RemoveInvalidXmlChars(string content)
{
   return new string(content.Where(ch => System.Xml.XmlConvert.IsXmlChar(ch)).ToArray());
}

oder Sie können überprüfen, ob alle Zeichen XML-gültig sind:

public static bool CheckValidXmlChars(string content)
{
   return content.All(ch => System.Xml.XmlConvert.IsXmlChar(ch));
}

.Net Geige

Beispielsweise ist das vertikale Tabulatorsymbol ( \v) für XML nicht gültig, es ist gültig für UTF-8, aber nicht für XML 1.0, und selbst viele Bibliotheken (einschließlich libxml2) vermissen es und geben stillschweigend ungültiges XML aus.

Alex Vazhev
quelle
2

Zusammenfassend sind gültige Zeichen im Text:

  • Tab, Zeilenvorschub und Wagenrücklauf.
  • Alle Nicht-Steuerzeichen außer & und sind gültig <.
  • >ist nicht gültig, wenn folgendes ]].

Die Abschnitte 2.2 und 2.4 der XML-Spezifikation geben die Antwort im Detail:

Zeichen

Zulässige Zeichen sind Tabulator, Wagenrücklauf, Zeilenvorschub und die zulässigen Zeichen von Unicode und ISO / IEC 10646

Zeichendaten

Das kaufmännische Und-Zeichen (&) und die linke spitze Klammer (<) dürfen nicht in ihrer wörtlichen Form erscheinen, es sei denn, sie werden als Markup-Begrenzer oder in einem Kommentar, einer Verarbeitungsanweisung oder einem CDATA-Abschnitt verwendet. Wenn sie an anderer Stelle benötigt werden, müssen sie entweder mit numerischen Zeichenreferenzen oder mit den Zeichenfolgen "&" bzw. "<" maskiert werden. Die rechtwinklige Klammer (>) kann mit der Zeichenfolge ">" dargestellt werden und muss aus Kompatibilitätsgründen entweder mit ">" oder einer Zeichenreferenz maskiert werden, wenn sie in der Zeichenfolge "]]>" im Inhalt erscheint Zeichenfolge markiert nicht das Ende eines CDATA-Abschnitts.

rghome
quelle
2

" XmlWriter und niedrigere ASCII-Zeichen " haben bei mir funktioniert

string code = Regex.Replace(item.Code, @"[\u0000-\u0008,\u000B,\u000C,\u000E-\u001F]", "");
Kalpesh Popat
quelle
1
ampersand (&) is escaped to &amp;

double quotes (") are escaped to &quot;

single quotes (') are escaped to &apos; 

less than (<) is escaped to &lt; 

greater than (>) is escaped to &gt;

Verwenden System.Security.SecurityElement.Escapeoder verwenden Sie System.Net.WebUtility.HtmlEncodein C # diese unzulässigen Zeichen.

string xml = "<node>it's my \"node\" & i like it 0x12 x09 x0A  0x09 0x0A <node>";
string encodedXml1 = System.Security.SecurityElement.Escape(xml);
string encodedXml2= System.Net.WebUtility.HtmlEncode(xml);


encodedXml1
"&lt;node&gt;it&apos;s my &quot;node&quot; &amp; i like it 0x12 x09 x0A  0x09 0x0A &lt;node&gt;"

encodedXml2
"&lt;node&gt;it&#39;s my &quot;node&quot; &amp; i like it 0x12 x09 x0A  0x09 0x0A &lt;node&gt;"
Live-Liebe
quelle
1

Für Java-Benutzer verfügt Apache über eine Utility-Klasse ( StringEscapeUtils) mit einer Hilfsmethode, mit escapeXmlder Zeichen in einer Zeichenfolge mithilfe von XML-Entitäten maskiert werden können.

Ein Nullzeiger
quelle
1

Im Woodstox-XML-Prozessor werden ungültige Zeichen durch diesen Code klassifiziert:

if (c == 0) {
    throw new IOException("Invalid null character in text to output");
}
if (c < ' ' || (c >= 0x7F && c <= 0x9F)) {
    String msg = "Invalid white space character (0x" + Integer.toHexString(c) + ") in text to output";
    if (mXml11) {
        msg += " (can only be output using character entity)";
    }
    throw new IOException(msg);
}
if (c > 0x10FFFF) {
    throw new IOException("Illegal unicode character point (0x" + Integer.toHexString(c) + ") to output; max is 0x10FFFF as per RFC");
}
/*
 * Surrogate pair in non-quotable (not text or attribute value) content, and non-unicode encoding (ISO-8859-x,
 * Ascii)?
 */
if (c >= SURR1_FIRST && c <= SURR2_LAST) {
    throw new IOException("Illegal surrogate pair -- can only be output via character entities, which are not allowed in this content");
}
throw new IOException("Invalid XML character (0x"+Integer.toHexString(c)+") in text to output");

Quelle von hier

Hieronymus Saint-Yves
quelle
-1

Hat das jemand versucht System.Security.SecurityElement.Escape(yourstring)? Dadurch werden ungültige XML-Zeichen in einer Zeichenfolge durch ihre gültigen Entsprechungen ersetzt.

klaydze
quelle
-5

Für XSL (an wirklich faulen Tagen) verwende ich:

capture="&amp;(?!amp;)" capturereplace="&amp;amp;"

um alle & -Zeichen zu übersetzen, denen nicht gefolgt wird på amp; zu den richtigen.

Wir haben Fälle, in denen die Eingabe in CDATA erfolgt, das System, das das XML verwendet, dies jedoch nicht berücksichtigt. Es ist eine schlampige Lösung, Vorsicht ...

Samson Wiklund
quelle
8
Wenn es schlampig ist, ist es wirklich notwendig, es hier zu posten?
Dolmen