Избегайте недопустимых символов XML в C # - PullRequest
74 голосов
/ 30 ноября 2011

У меня есть строка, содержащая недопустимые символы XML. Как я могу избежать (или удалить) недопустимые символы XML перед тем, как проанализировать строку?

Ответы [ 7 ]

99 голосов
/ 16 февраля 2013

В качестве способа удаления недопустимых символов XML я предлагаю использовать метод XmlConvert.IsXmlChar . Он был добавлен начиная с .NET Framework 4 и также представлен в Silverlight. Вот небольшой образец:

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

И как способ избежать недопустимых символов XML, я предлагаю вам использовать XmlConvert.EncodeName метод. Вот небольшой образец:

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

Обновление: Следует отметить, что операция кодирования создает строку с длиной, которая больше или равна длине исходной строки. Это может быть важно, когда вы храните закодированную строку в базе данных в столбце строк с ограничением длины и проверяете длину строки источника в своем приложении, чтобы соответствовать ограничению столбца данных.

61 голосов
/ 01 декабря 2011

Использование SecurityElement.Escape

using System;
using System.Security;

class Sample {
  static void Main() {
    string text = "Escape characters : < > & \" \'";
    string xmlText = SecurityElement.Escape(text);
//output:
//Escape characters : &lt; &gt; &amp; &quot; &apos;
    Console.WriteLine(xmlText);
  }
}
19 голосов
/ 30 ноября 2011

Если вы пишете XML, просто используйте классы, предоставляемые платформой для создания XML. Вам не придется беспокоиться о побеге или чем-либо еще.

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

Будет выводить

<Data>&lt; &gt; &amp;</Data>

Если вам нужно прочитать поврежденный XML-файл, не используйте регулярное выражение . Вместо этого используйте Html Agility Pack .

4 голосов
/ 19 июля 2013

Метод RemoveInvalidXmlChars, предоставленный Irishman, не поддерживает суррогатные символы.Чтобы проверить это, используйте следующий пример:

static void Main()
{
    const string content = "\v\U00010330";

    string newContent = RemoveInvalidXmlChars(content);

    Console.WriteLine(newContent);
}

Возвращает пустую строку, но не должно!Должно возвращаться «\ U00010330», поскольку символ U + 10330 является допустимым символом XML.

Для поддержки суррогатных символов я предлагаю использовать следующий метод:

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();
}
3 голосов
/ 27 апреля 2016

Вот оптимизированная версия вышеупомянутого метода RemoveInvalidXmlChars, который не создает новый массив при каждом вызове, подчеркивая, таким образом, GC без необходимости:

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

}
1 голос
/ 30 ноября 2011
// Replace invalid characters with empty strings.
   Regex.Replace(inputString, @"[^\w\.@-]", ""); 

Шаблон регулярного выражения [^ \ w. @ -] соответствует любому символу, который не является символом слова, точкой, символом @ или дефисом. Символ слова - это любая буква, десятичная цифра или соединитель пунктуации, например подчеркивание. Любой символ, соответствующий этому шаблону, заменяется на String.Empty, который является строкой, определенной шаблоном замены. Чтобы разрешить дополнительные символы в пользовательском вводе, добавьте эти символы в класс символов в шаблоне регулярного выражения. Например, шаблон регулярного выражения [^ \ w. @ - \%] также допускает использование символа процента и обратной косой черты во входной строке.

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

См. Также:

Удаление недопустимых символов из тега имени XML - RegEx C #

Вот функция для удаления символов из указанной строки XML:

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;
        }
    }
}
0 голосов
/ 16 мая 2019
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);
}

Этот простой метод заменяет недопустимые символы тем же значением, но принятым в контексте XML.


Для записи строки используйте XMLWriteStringWithoutIllegalCharacters (строка UnfilteredString).
Для чтения строки используйте XMLReadStringWithoutIllegalCharacters (строка FilteredString).

...