Escape caracteres XML inválidos em c #

Eu tenho uma string que contém caracteres XML inválidos. Como posso escaping (ou remover) caracteres XML inválidos antes de analisar a cadeia?

Como forma de remover caracteres XML inválidos, sugiro que você use o método XmlConvert.IsXmlChar . Foi adicionado desde o .NET Framework 4 e é apresentado também no Silverlight. Aqui está a pequena amostra:

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 como o caminho para escaping de caracteres XML inválidos eu sugiro que você use o método XmlConvert.EncodeName . Aqui está a pequena amostra:

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

Atualização: Deve-se mencionar que a operação de codificação produz uma string com um comprimento que é maior ou igual a um comprimento de uma string de origem. Pode ser importante armazenar uma string codificada em um database em uma coluna de string com limitação de comprimento e validar o comprimento da string de origem no aplicativo para que ela se ajuste à limitação da coluna de dados.

Use o 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 você estiver escrevendo xml, use as classs fornecidas pela estrutura para criar o xml. Você não terá que se preocupar em fugir ou nada.

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

Saída

 < > & 

Se você precisar ler um arquivo XML mal formado, não use expressões regulares. Em vez disso, use o Html Agility Pack .

O método RemoveInvalidXmlChars fornecido pelo Irishman não suporta caracteres substitutos. Para testá-lo, use o seguinte exemplo:

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

Isso retorna uma string vazia, mas não deveria! Ele deve retornar “\ U00010330” porque o caractere U + 10330 é um caractere XML válido.

Para suportar caracteres substitutos, sugiro usar o seguinte método:

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

Aqui está uma versão otimizada do método RemoveInvalidXmlChars acima, que não cria uma nova matriz em todas as chamadas, enfatizando assim o GC unnessesarily:

 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\.@-]", ""); 

O padrão de expressão regular [^ \ w. @ -] corresponde a qualquer caractere que não seja um caractere de palavra, um ponto final, um símbolo @ ou um hífen. Um caractere de palavra é qualquer letra, dígito decimal ou conector de pontuação, como um sublinhado. Qualquer caractere que corresponda a esse padrão será substituído por String.Empty, que é a sequência definida pelo padrão de substituição. Para permitir caracteres adicionais na input do usuário, inclua esses caracteres na class de caractere no padrão de expressão regular. Por exemplo, o padrão de expressão regular [^ \ w. @ – \%] também permite um símbolo de porcentagem e uma barra invertida em uma sequência de input.

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

Consulte isso também:

Removendo caracteres inválidos da marca de nome XML – RegEx C #

Aqui está uma function para remover os caracteres de uma string XML especificada:

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