Ich habe eine Zeichenfolge, die ungültige XML-Zeichen enthält. Wie kann ich ungültige XML-Zeichen maskieren (oder entfernen), bevor ich die Zeichenfolge analysiere?
Ich habe eine Zeichenfolge, die ungültige XML-Zeichen enthält. Wie kann ich ungültige XML-Zeichen maskieren (oder entfernen), bevor ich die Zeichenfolge analysiere?
Antworten:
Um ungültige XML-Zeichen zu entfernen, empfehle ich die Verwendung der XmlConvert.IsXmlChar- Methode. Es wurde seit .NET Framework 4 hinzugefügt und wird auch in Silverlight dargestellt. Hier ist das kleine Beispiel:
void Main() {
string content = "\v\f\0";
Console.WriteLine(IsValidXmlString(content)); // False
content = RemoveInvalidXmlChars(content);
Console.WriteLine(IsValidXmlString(content)); // True
}
static string RemoveInvalidXmlChars(string text) {
var validXmlChars = text.Where(ch => XmlConvert.IsXmlChar(ch)).ToArray();
return new string(validXmlChars);
}
static bool IsValidXmlString(string text) {
try {
XmlConvert.VerifyXmlChars(text);
return true;
} catch {
return false;
}
}
Um ungültigen XML-Zeichen zu entgehen, empfehle ich die Verwendung der XmlConvert.EncodeName- Methode. Hier ist das kleine Beispiel:
void Main() {
const string content = "\v\f\0";
Console.WriteLine(IsValidXmlString(content)); // False
string encoded = XmlConvert.EncodeName(content);
Console.WriteLine(IsValidXmlString(encoded)); // True
string decoded = XmlConvert.DecodeName(encoded);
Console.WriteLine(content == decoded); // True
}
static bool IsValidXmlString(string text) {
try {
XmlConvert.VerifyXmlChars(text);
return true;
} catch {
return false;
}
}
Update: Es sollte erwähnt werden, dass die Codierungsoperation eine Zeichenfolge mit einer Länge erzeugt, die größer oder gleich einer Länge einer Quellzeichenfolge ist. Dies kann wichtig sein, wenn Sie eine codierte Zeichenfolge in einer Datenbank in einer Zeichenfolgenspalte mit Längenbeschränkung speichern und die Länge der Quellzeichenfolge in Ihrer App überprüfen, um sie an die Beschränkung der Datenspalten anzupassen.
XmlConvert.VerifyXmlChars
löst keine Ausnahme aus, wenn das Argument ungültige Zeichen enthält, sondern gibt die Nullzeichenfolge zurück (und gibt das Argument zurück, wenn alle enthaltenen Zeichen gültig sind). Versuchen Sie es einfach return XmlConvert.VerifyXmlChars (text) != null
.
Verwenden Sie SecurityElement.Escape
using System;
using System.Security;
class Sample {
static void Main() {
string text = "Escape characters : < > & \" \'";
string xmlText = SecurityElement.Escape(text);
//output:
//Escape characters : < > & " '
Console.WriteLine(xmlText);
}
}
Wenn Sie XML schreiben, verwenden Sie einfach die vom Framework bereitgestellten Klassen, um die XML zu erstellen. Sie müssen sich nicht um Flucht oder ähnliches kümmern.
Console.Write(new XElement("Data", "< > &"));
Wird ausgegeben
<Data>< > &</Data>
Wenn Sie eine XML - Datei zu lesen , die ungültig ist, nicht verwendet regulären Ausdruck. Verwenden Sie stattdessen das HTML Agility Pack .
<Data>&</Data>
?
Die von Irishman bereitgestellte RemoveInvalidXmlChars-Methode unterstützt keine Ersatzzeichen. Verwenden Sie zum Testen das folgende Beispiel:
static void Main()
{
const string content = "\v\U00010330";
string newContent = RemoveInvalidXmlChars(content);
Console.WriteLine(newContent);
}
Dies gibt eine leere Zeichenfolge zurück, sollte es aber nicht! Es sollte "\ U00010330" zurückgeben, da das Zeichen U + 10330 ein gültiges XML-Zeichen ist.
Um Ersatzzeichen zu unterstützen, empfehle ich die folgende Methode:
public static string RemoveInvalidXmlChars(string text)
{
if (string.IsNullOrEmpty(text))
return text;
int length = text.Length;
StringBuilder stringBuilder = new StringBuilder(length);
for (int i = 0; i < length; ++i)
{
if (XmlConvert.IsXmlChar(text[i]))
{
stringBuilder.Append(text[i]);
}
else if (i + 1 < length && XmlConvert.IsXmlSurrogatePair(text[i + 1], text[i]))
{
stringBuilder.Append(text[i]);
stringBuilder.Append(text[i + 1]);
++i;
}
}
return stringBuilder.ToString();
}
Hier ist eine optimierte Version der oben genannten Methode RemoveInvalidXmlChars, die nicht bei jedem Aufruf ein neues Array erstellt, wodurch der GC unnötig belastet wird:
public static string RemoveInvalidXmlChars(string text)
{
if (text == null)
return text;
if (text.Length == 0)
return text;
// a bit complicated, but avoids memory usage if not necessary
StringBuilder result = null;
for (int i = 0; i < text.Length; i++)
{
var ch = text[i];
if (XmlConvert.IsXmlChar(ch))
{
result?.Append(ch);
}
else if (result == null)
{
result = new StringBuilder();
result.Append(text.Substring(0, i));
}
}
if (result == null)
return text; // no invalid xml chars detected - return original text
else
return result.ToString();
}
?.
Syntax? in der Schlange result?.Append(ch);
?
// Replace invalid characters with empty strings.
Regex.Replace(inputString, @"[^\w\.@-]", "");
Das Muster für reguläre Ausdrücke [^ \ w. @ -] entspricht jedem Zeichen, das kein Wortzeichen, kein Punkt, kein @ -Symbol oder kein Bindestrich ist. Ein Wortzeichen ist ein beliebiger Buchstabe, eine Dezimalstelle oder ein Satzzeichen, z. B. ein Unterstrich. Jedes Zeichen, das diesem Muster entspricht, wird durch String.Empty ersetzt. Dies ist die Zeichenfolge, die durch das Ersetzungsmuster definiert wird. Um zusätzliche Zeichen in der Benutzereingabe zuzulassen, fügen Sie diese Zeichen der Zeichenklasse im Muster für reguläre Ausdrücke hinzu. Das Muster für reguläre Ausdrücke [^ \ w. @ - \%] ermöglicht beispielsweise auch ein Prozentzeichen und einen Backslash in einer Eingabezeichenfolge.
Regex.Replace(inputString, @"[!@#$%_]", "");
Siehe auch dies:
Ungültige Zeichen aus dem XML-Namensschild entfernen - RegEx C #
Hier ist eine Funktion zum Entfernen der Zeichen aus einer angegebenen XML-Zeichenfolge:
using System;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;
namespace XMLUtils
{
class Standards
{
/// <summary>
/// Strips non-printable ascii characters
/// Refer to http://www.w3.org/TR/xml11/#charsets for XML 1.1
/// Refer to http://www.w3.org/TR/2006/REC-xml-20060816/#charsets for XML 1.0
/// </summary>
/// <param name="content">contents</param>
/// <param name="XMLVersion">XML Specification to use. Can be 1.0 or 1.1</param>
private void StripIllegalXMLChars(string tmpContents, string XMLVersion)
{
string pattern = String.Empty;
switch (XMLVersion)
{
case "1.0":
pattern = @"#x((10?|[2-F])FFF[EF]|FDD[0-9A-F]|7F|8[0-46-9A-F]9[0-9A-F])";
break;
case "1.1":
pattern = @"#x((10?|[2-F])FFF[EF]|FDD[0-9A-F]|[19][0-9A-F]|7F|8[0-46-9A-F]|0?[1-8BCEF])";
break;
default:
throw new Exception("Error: Invalid XML Version!");
}
Regex regex = new Regex(pattern, RegexOptions.IgnoreCase);
if (regex.IsMatch(tmpContents))
{
tmpContents = regex.Replace(tmpContents, String.Empty);
}
tmpContents = string.Empty;
}
}
}
string XMLWriteStringWithoutIllegalCharacters(string UnfilteredString)
{
if (UnfilteredString == null)
return string.Empty;
return XmlConvert.EncodeName(UnfilteredString);
}
string XMLReadStringWithoutIllegalCharacters(string FilteredString)
{
if (UnfilteredString == null)
return string.Empty;
return XmlConvert.DecodeName(UnfilteredString);
}
Diese einfache Methode ersetzt die ungültigen Zeichen durch denselben Wert, wird jedoch im XML-Kontext akzeptiert.
Verwenden Sie zum Schreiben einer Zeichenfolge XMLWriteStringWithoutIllegalCharacters (Zeichenfolge UnfilteredString).
Verwenden Sie zum Lesen von Zeichenfolgen XMLReadStringWithoutIllegalCharacters (Zeichenfolge FilteredString).