Échapper aux caractères XML non valides en C #

J’ai une chaîne qui contient des caractères XML non valides. Comment puis-je échapper (ou supprimer) des caractères XML non valides avant d’parsingr la chaîne?

Comme moyen de supprimer les caractères XML non valides, je vous suggère d’utiliser la méthode XmlConvert.IsXmlChar . Il a été ajouté depuis .NET Framework 4 et est également présenté dans Silverlight. Voici le petit échantillon:

void Main() { ssortingng content = "\v\f\0"; Console.WriteLine(IsValidXmlSsortingng(content)); // False content = RemoveInvalidXmlChars(content); Console.WriteLine(IsValidXmlSsortingng(content)); // True } static ssortingng RemoveInvalidXmlChars(ssortingng text) { var validXmlChars = text.Where(ch => XmlConvert.IsXmlChar(ch)).ToArray(); return new ssortingng(validXmlChars); } static bool IsValidXmlSsortingng(ssortingng text) { try { XmlConvert.VerifyXmlChars(text); return true; } catch { return false; } } 

Et comme moyen d’échapper aux caractères XML non valides, je vous suggère d’utiliser la méthode XmlConvert.EncodeName . Voici le petit échantillon:

 void Main() { const ssortingng content = "\v\f\0"; Console.WriteLine(IsValidXmlSsortingng(content)); // False ssortingng encoded = XmlConvert.EncodeName(content); Console.WriteLine(IsValidXmlSsortingng(encoded)); // True ssortingng decoded = XmlConvert.DecodeName(encoded); Console.WriteLine(content == decoded); // True } static bool IsValidXmlSsortingng(ssortingng text) { try { XmlConvert.VerifyXmlChars(text); return true; } catch { return false; } } 

Mise à jour: il convient de mentionner que l’opération de codage produit une chaîne d’une longueur supérieure ou égale à la longueur d’une chaîne source. Il peut être important lorsque vous stockez une chaîne codée dans une firebase database dans une colonne de chaîne avec une limitation de longueur et validez la longueur de la chaîne source dans votre application pour l’adapter à la limitation de la colonne de données.

Utilisez SecurityElement.Escape

 using System; using System.Security; class Sample { static void Main() { ssortingng text = "Escape characters : < > & \" \'"; ssortingng xmlText = SecurityElement.Escape(text); //output: //Escape characters : < > & " ' Console.WriteLine(xmlText); } } 

Si vous écrivez xml, utilisez simplement les classes fournies par le framework pour créer le fichier XML. Vous n’aurez plus à vous échapper ni à rien.

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

Va sortir

 < > & 

Si vous avez besoin de lire un fichier XML mal formé, n’utilisez pas d’ expression régulière. Au lieu de cela, utilisez le Html Agility Pack .

La méthode RemoveInvalidXmlChars fournie par Irishman ne prend pas en charge les caractères de substitution. Pour le tester, utilisez l’exemple suivant:

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

Cela retourne une chaîne vide mais ça ne devrait pas! Il doit renvoyer “\ U00010330” car le caractère U + 10330 est un caractère XML valide.

Pour prendre en charge les caractères de substitution, je suggère d’utiliser la méthode suivante:

 public static ssortingng RemoveInvalidXmlChars(ssortingng text) { if (ssortingng.IsNullOrEmpty(text)) return text; int length = text.Length; SsortingngBuilder ssortingngBuilder = new SsortingngBuilder(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(); } 

Voici une version optimisée de la méthode ci-dessus RemoveInvalidXmlChars qui ne crée pas de nouveau tableau à chaque appel, ce qui met le GC à l’épreuve:

 public static ssortingng RemoveInvalidXmlChars(ssortingng text) { if (text == null) return text; if (text.Length == 0) return text; // a bit complicated, but avoids memory usage if not necessary SsortingngBuilder 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 ssortingngs. Regex.Replace(inputSsortingng, @"[^\w\.@-]", ""); 

Le modèle d’expression régulière [^ \ w. @ -] correspond à tout caractère autre qu’un mot, un point, un symbole @ ou un trait d’union. Un caractère de mot est une lettre, un chiffre décimal ou un connecteur de ponctuation tel qu’un trait de soulignement. Tout caractère correspondant à ce modèle est remplacé par Ssortingng.Empty, qui est la chaîne définie par le motif de remplacement. Pour autoriser des caractères supplémentaires dans la saisie de l’utilisateur, ajoutez ces caractères à la classe de caractères du modèle d’expression régulière. Par exemple, le modèle d’expression régulière [^ \ w. @ – \%] autorise également un symbole de pourcentage et une barre oblique inverse dans une chaîne d’entrée.

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

Référer ceci aussi:

Suppression de caractères incorrects de l’étiquette de nom XML – RegEx C #

Voici une fonction pour supprimer les caractères d’une chaîne XML spécifiée:

 using System; using System.IO; using System.Text; using System.Text.RegularExpressions; namespace XMLUtils { class Standards { ///  /// Ssortingps 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 SsortingpIllegalXMLChars(ssortingng tmpContents, ssortingng XMLVersion) { ssortingng pattern = Ssortingng.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, Ssortingng.Empty); } tmpContents = ssortingng.Empty; } } }