Ersatzzeichenpaare in einem XML-Dokument
Ein Ersatzzeichenpaar ist ein Paar aus 16-Bit-Unicodewerten, die zusammen ein einziges Zeichen darstellen. Der wichtigste Punkt hierbei ist, dass Ersatzzeichenpaare eigentlich einzelne 32-Bit-Zeichen sind. Es kann nicht davon ausgegangen werden, dass ein 16-Bit-Unicodewert genau einem Zeichen zugeordnet wird.
Arbeiten mit Ersatzzeichenpaaren
Der erste Wert des Ersatzzeichenpaares ist das hohe Ersatzzeichen. Er ist ein 16-Bit-Code-Wert im Bereich von U+D800 bis U+DBFF. Der zweite Wert des Paares, das niedere Ersatzzeichen, liegt im Bereich von U+DC00 bis U+DFFF. Durch die Verwendung von Ersatzzeichenpaaren kann ein 16-Bit-Unicode-System mehr als eine Million zusätzliche Zeichen (2^20) ansprechen, die durch den Unicodestandard definiert werden.
Sie können Ersatzzeichen in jeder Zeichenfolge verwenden, die an eine XmlTextWriter-Methode übergeben wird. Allerdings sollte das Ersatzzeichen in dem XML-Code, den Sie schreiben, gültig sein. Beispielsweise lässt die W3C-Empfehlung (Word Wide Web Consortium) keine Ersatzzeichen innerhalb von Element- oder Attributnamen zu. Wenn die Zeichenfolge ein ungültiges Ersatzzeichenpaar enthält, wird eine Ausnahme ausgelöst.
Darüber hinaus können Sie mit WriteSurrogateCharEntity die einem Ersatzzeichenpaar entsprechende Zeichenentität schreiben. Die Zeichenentität wird im Hexadezimalformat geschrieben und mit folgender Formel generiert:
(highChar -0xD800) * 0x400 + (lowChar -0xDC00) + 0x10000
Wenn die Zeichenfolge ein ungültiges Ersatzzeichenpaar enthält, wird eine Ausnahme ausgelöst. Im folgenden Beispiel wird die WriteSurrogateCharEntity-Methode mit einem Ersatzzeichenpaar als Eingabe veranschaulicht.
// The following line writes 𐀀.
WriteSurrogateCharEntity ('\uDC00', '\uD800');
Im folgenden Beispiel wird eine Datei mit Ersatzzeichenpaaren erstellt, in den XmlReader geladen und die Datei mit einem neuen Namen herausgeschrieben. Anschließend werden die ursprüngliche und die neue Datei zu Vergleichszwecken wieder in der Anwendung in die DOM-Struktur (XML Document Objekt Model) geladen.
char lowChar, highChar;
char [] charArray = new char[10];
FileStream targetFile = new FileStream("SurrogatePair.xml",
FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite);
lowChar = Convert.ToChar(0xDC00);
highChar = Convert.ToChar(0xD800);
XmlTextWriter tw = new XmlTextWriter(targetFile, null);
tw.Formatting = Formatting.Indented;
tw.WriteStartElement("root");
tw.WriteStartAttribute("test", null);
tw.WriteSurrogateCharEntity(lowChar, highChar);
lowChar = Convert.ToChar(0xDC01);
highChar = Convert.ToChar(0xD801);
tw.WriteSurrogateCharEntity(lowChar, highChar);
lowChar = Convert.ToChar(0xDFFF);
highChar = Convert.ToChar(0xDBFF);
tw.WriteSurrogateCharEntity(lowChar, highChar);
// Add 10 random surrogate pairs.
// As Unicode, the high bytes are in lower
// memory; for example, word 6A21 as 21 6A.
// The high or low is in the logical sense.
Random random = new Random();
for (int i = 0; i < 10; ++i) {
lowChar = Convert.ToChar(random.Next(0xDC00, 0xE000));
highChar = Convert.ToChar(random.Next(0xD800, 0xDC00));
charArray[i] = highChar;
charArray[++i] = lowChar;
}
tw.WriteChars(charArray, 0, charArray.Length);
for (int i = 0; i < 10; ++i) {
lowChar = Convert.ToChar(random.Next(0xDC00, 0xE000));
highChar = Convert.ToChar(random.Next(0xD800, 0xDC00));
tw.WriteSurrogateCharEntity(lowChar, highChar);
}
tw.WriteEndAttribute();
tw.WriteEndElement();
tw.Flush();
tw.Close();
XmlTextReader r = new XmlTextReader("SurrogatePair.xml");
r.Read();
r.MoveToFirstAttribute();
targetFile = new FileStream("SurrogatePairFromReader.xml",
FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite);
tw = new XmlTextWriter(targetFile, null);
tw.Formatting = Formatting.Indented;
tw.WriteStartElement("root");
tw.WriteStartAttribute("test", null);
tw.WriteString(r.Value);
tw.WriteEndAttribute();
tw.WriteEndElement();
tw.Flush();
tw.Close();
// Load both result files into the DOM and compare.
XmlDocument doc1 = new XmlDocument();
XmlDocument doc2 = new XmlDocument();
doc1.Load("SurrogatePair.xml");
doc2.Load("SurrogatePairFromReader.xml");
if (doc1.InnerXml != doc2.InnerXml) {
Console.WriteLine("Surrogate Pair test case failed");
}
Beim Schreiben mit der WriteChars-Methode, die immer einen Datenpuffer einzeln schreibt, besteht die Gefahr, dass ein Ersatzzeichenpaar in der Eingabe versehentlich über einen Puffer hinweg aufgespaltet wird. Da Ersatzzeichenwerte wohldefiniert sind, erkennt die WriteChars einen gefundenen Unicode-Wert aus dem oberen oder dem unteren Bereich als eine Hälfte eines Ersatzzeichenpaars. Wenn der Fall eintritt, dass WriteChars beim Schreiben aus dem Puffer das Ersatzzeichenpaar aufspalten würde, wird eine Ausnahme ausgelöst. Mit der IsHighSurrogate-Methode können Sie überprüfen, ob das letzte Zeichen des Puffers ein hohes Ersatzzeichen ist. Wenn das letzte Zeichen des Puffers kein hohes Ersatzzeichen ist, kann der Puffer der WriteChars-Methode übergeben werden.
Siehe auch
Konzepte
Erstellen von wohlgeformtem XML mit "XmlTextWriter"