Работа с недопустимыми шестнадцатеричными символами XML

Я пытаюсь отправить XML-документ по проводу, но получаю следующее исключение:

"MY LONG EMAIL STRING" was specified for the 'Body' element. ---> System.ArgumentException: '', hexadecimal value 0x02, is an invalid character.
   at System.Xml.XmlUtf8RawTextWriter.InvalidXmlChar(Int32 ch, Byte* pDst, Boolean entitize)
   at System.Xml.XmlUtf8RawTextWriter.WriteElementTextBlock(Char* pSrc, Char* pSrcEnd)
   at System.Xml.XmlUtf8RawTextWriter.WriteString(String text)
   at System.Xml.XmlUtf8RawTextWriterIndent.WriteString(String text)
   at System.Xml.XmlRawWriter.WriteValue(String value)
   at System.Xml.XmlWellFormedWriter.WriteValue(String value)
   at Microsoft.Exchange.WebServices.Data.EwsServiceXmlWriter.WriteValue(String value, String name)
   --- End of inner exception stack trace ---

Я не имеем никакого контроля над тем, что я пытаюсь отправить, потому что строка собрана из электронной почты. Как я могу кодировать свою строку, чтобы она была действительной XML при сохранении незаконных символов?

Я хотел бы сохранить оригинальные символы так или иначе.

7 ответов


byte[] toEncodeAsBytes
            = System.Text.ASCIIEncoding.ASCII.GetBytes(toEncode);
      string returnValue
            = System.Convert.ToBase64String(toEncodeAsBytes);

Это один из способов сделать это


следующий код удаляет недопустимые символы в XML-строку и возвращает новую строку без них:

public static string CleanInvalidXmlChars(string text) 
{ 
     // From xml spec valid chars: 
     // #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF]     
     // any Unicode character, excluding the surrogate blocks, FFFE, and FFFF. 
     string re = @"[^\x09\x0A\x0D\x20-\xD7FF\xE000-\xFFFD\x10000-x10FFFF]"; 
     return Regex.Replace(text, re, ""); 
}

следующее решение удаляет любые недопустимые символы XML, но это делает так, что я думаю о том, как это можно сделать, и, в частности, это делает не выделите новый StringBuilder, а также новую строку, если уже не определено, что в строке есть какие-либо недопустимые символы. Таким образом, горячая точка заканчивается только одним циклом for на символах, а проверка заканчивается тем, что часто не более двух больше / меньше числовых сравнений на каждый шар. Если ничего не найдено, он просто возвращает исходную строку. Это особенно полезно, когда подавляющее большинство строк просто отлично для начала, приятно иметь их как можно быстрее (без ненужных выделений и т. д.).

-- update --

см. ниже как можно напрямую написать XElement, который имеет эти недопустимые символы, хотя он использует этот код:

некоторые из этого кода повлияли г-ном Томом Богла решение здесь. См. также в том же потоке полезную информацию в post by скачать. Все это, однако, всегда создает экземпляр нового StringBuilder и string still.

использование:

    string xmlStrBack = XML.ToValidXmlCharactersString("any string");

я нахожусь на принимающей стороне решения @parapurarajkumar, где незаконные символы правильно загружаются в XmlDocument, но, нарушив XmlWriter когда я пытаюсь сохранить вывод.

Контекст

Я смотрю журналы исключений/ошибок с веб-сайта с помощью Elmah. Elmah возвращает состояние сервера на момент исключения, в виде XML-документа. Для нашего механизма отчетности я довольно-печать XML с XmlWriter.

во время атаки на веб-сайт я заметил, что некоторые xmls не анализируются и получают это '.', hexadecimal value 0x00, is an invalid character. исключения.

NON-РАЗРЕШЕНИЕ: я преобразовал документ в byte[] и очистил его от 0x00, но он не нашел ни одного.

когда я сканировал xml-документ, я нашел следующее:

...
<form>
...
<item name="SomeField">
   <value
     string="C:\boot.ini&#x0;.htm" />
 </item>
...

был байт nul, закодированный как сущность html &#x0; !!!

: исправить кодировка, Я заменил &#x0; значение перед загрузкой его в my XmlDocument, потому что загрузка его создаст байт nul, и будет трудно санировать его из объекта. Вот весь мой процесс:

XmlDocument xml = new XmlDocument();
details.Xml = details.Xml.Replace("&#x0;", "[0x00]");  // in my case I wanted to see it, otherwise just replace with ""
xml.LoadXml(details.Xml);

string formattedXml = null;

// I stuff this all in a helper function, but put it in-line for this example
StringBuilder sb = new StringBuilder();
XmlWriterSettings settings = new XmlWriterSettings {
    OmitXmlDeclaration = true,
    Indent = true,
    IndentChars = "\t",
    NewLineHandling = NewLineHandling.None,
};
using (XmlWriter writer = XmlWriter.Create(sb, settings)) {
    xml.Save(writer);
    formattedXml = sb.ToString();
}

УРОК: санировать для незаконных байтов с помощью связанного объекта html, если ваши входящие данные кодируются html при вводе.


Работа для меня:

XmlWriterSettings xmlWriterSettings = new XmlWriterSettings { Encoding = Encoding.UTF8, CheckCharacters = false };

не удается очистить строку с помощью:

System.Net.WebUtility.HtmlDecode()

?


другой способ удалить неправильные символы XML в C# с помощью XmlConvert.Метод IsXmlChar (доступно начиная с .NET Framework 4.0)

public static string RemoveInvalidXmlChars(string content)
{
   return new string(content.Where(ch => System.Xml.XmlConvert.IsXmlChar(ch)).ToArray());
}

.NET Fiddle -https://dotnetfiddle.net/v1TNus