Evita caratteri XML non validi in C #

Ho una stringa che contiene caratteri XML non validi. Come posso sfuggire (o rimuovere) caratteri XML non validi prima di analizzare la stringa?

Come metodo per rimuovere caratteri XML non validi ti suggerisco di utilizzare il metodo XmlConvert.IsXmlChar . È stato aggiunto da .NET Framework 4 e viene presentato anche in Silverlight. Ecco il piccolo campione:

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

E come modo per evitare caratteri XML non validi ti suggerisco di usare il metodo XmlConvert.EncodeName . Ecco il piccolo campione:

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

Aggiornamento: Va detto che l’operazione di codifica produce una stringa con una lunghezza maggiore o uguale a una lunghezza di una stringa sorgente. Potrebbe essere importante quando si memorizza una stringa codificata in un database in una colonna di stringhe con limitazioni di lunghezza e si convalida la lunghezza della stringa di origine nell’app per adattarla alla limitazione della colonna di dati.

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

Se stai scrivendo xml, usa semplicemente le classi fornite dal framework per creare l’xml. Non dovrai preoccuparti di scappare o di qualsiasi altra cosa.

 Console.Write(new XElement("Data", "<> &")); 

Uscirà

 < > & 

Se è necessario leggere un file XML non valido, non utilizzare espressioni regolari. Utilizzare invece il pacchetto agilità Html .

Il metodo RemoveInvalidXmlChars fornito da Irishman non supporta i caratteri surrogati. Per testarlo, utilizzare il seguente esempio:

 static void Main() { const string content = "\v\U00010330"; string newContent = RemoveInvalidXmlChars(content); Console.WriteLine(newContent); } 

Questo restituisce una stringa vuota ma non dovrebbe! Dovrebbe restituire “\ U00010330” perché il carattere U + 10330 è un carattere XML valido.

Per supportare i caratteri surrogati, suggerisco di utilizzare il seguente metodo:

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

Ecco una versione ottimizzata del metodo precedente RemoveInvalidXmlChars che non crea un nuovo array su ogni chiamata, sottolineando così il GC in modo unesuo:

 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(); } 
 // Replace invalid characters with empty strings. Regex.Replace(inputString, @"[^\w\.@-]", ""); 

Il modello di espressione regolare [^ \ w. @ -] corrisponde a qualsiasi carattere che non sia un carattere di parola, un punto, un simbolo @ o un trattino. Un carattere di parola è qualsiasi lettera, cifra decimale o connettore di punteggiatura come un trattino basso. Qualsiasi carattere che corrisponde a questo modello viene sostituito da String.Empty, che è la stringa definita dal modello di sostituzione. Per consentire caratteri aggiuntivi nell’input dell’utente, aggiungere quei caratteri alla class di caratteri nel modello di espressione regolare. Ad esempio, il modello di espressione regolare [^ \ w. @ – \%] consente anche un simbolo percentuale e una barra rovesciata in una stringa di input.

 Regex.Replace(inputString, @"[!@#$%_]", ""); 

Riferiscilo anche a:

Rimozione di caratteri non validi dal tag nome XML – RegEx C #

Ecco una funzione per rimuovere i caratteri da una stringa XML specificata:

 using System; using System.IO; using System.Text; using System.Text.RegularExpressions; namespace XMLUtils { class Standards { ///  /// 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 ///  /// contents /// XML Specification to use. Can be 1.0 or 1.1 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; } } }