Неверные символы в XML

Я сейчас работаю с некоторыми XML.

У меня есть узлы, которые содержат строки, как показано ниже:

<node>This is a string</node>

Некоторые строки, которые я передаю узлам, будут содержать символы, такие как &, #, $ и т. Д.

<node>This is a string & so is this</node>

Это недействительно из-за &

Я не могу обернуть эти строки в CDATA, так как они должны быть такими, какие они есть. Я попытался найти в Интернете список символов, которые нельзя поместить в узлы XML без CDATA.

Кто-нибудь может указать мне направление одного или предоставить мне список нелегальных персонажей?

16 ответов

Решение

Единственные нелегальные персонажи &, < а также > (так же как " или же ' в атрибутах).

Они экранированы с использованием сущностей XML, в этом случае вы хотите &amp; за &,

Однако на самом деле вы должны использовать инструмент или библиотеку, которая пишет для вас XML и абстрагирует подобные вещи, чтобы вам не пришлось об этом беспокоиться.

Хорошо, давайте разделим вопрос о (1) символах, которые вообще недопустимы в любом документе XML, и (2) символах, которые необходимо экранировать:

Ответ, предоставленный @dolmen Недопустимые символы в XML, все еще действителен, но его необходимо обновить с помощью спецификации XML 1.1.

1. Недопустимые символы

Описанные здесь символы - это все символы, которые разрешено вставлять в документ XML.

1.1. В XML 1.0

Глобальный список разрешенных символов:

[2] Char ::= #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF] /* any Unicode character, excluding the surrogate blocks, FFFE, and FFFF. */

В основном, управляющие символы и символы вне диапазонов Unicode не допускаются. Это также означает, что вызов, например, сущности персонажа &#x3; запрещен.

1.2. В XML 1.1

Глобальный список разрешенных символов:

[2] Char ::= [#x1-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF] /* any Unicode character, excluding the surrogate blocks, FFFE, and FFFF. */

[2a] RestrictedChar ::= [#x1-#x8] | [#xB-#xC] | [#xE-#x1F] | [#x7F-#x84] | [#x86-#x9F]

Эта редакция рекомендации XML расширила допустимые символы, чтобы разрешить управляющие символы, и учитывает новую редакцию стандарта Unicode, но они по-прежнему недопустимы: NUL (x00), xFFFE, xFFFF...

Однако использование управляющих символов и неопределенного символа Unicode не рекомендуется.

Также можно заметить, что все парсеры не всегда учитывают это, и документы XML с управляющими символами могут быть отклонены.

2. Символы, которые необходимо экранировать (чтобы получить правильно оформленный документ):

< должен быть сброшен с &lt; сущность, поскольку предполагается, что это начало тега.

& должен быть сброшен с &amp; объект, поскольку предполагается, что он является началом ссылки на объект

> следует избегать с &gt; юридическое лицо. Это не обязательно - это зависит от контекста - но настоятельно рекомендуется избегать его.

' следует избегать с &apos; entity - обязателен в атрибутах, определенных в одинарных кавычках, но настоятельно рекомендуется всегда избегать его.

" следует избегать с &quot; сущность - обязательна в атрибутах, определенных в двойных кавычках, но настоятельно рекомендуется всегда избегать ее.

Список допустимых символов приведен в спецификации XML:

Char       ::=      #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF]  /* any Unicode character, excluding the surrogate blocks, FFFE, and FFFF. */

Это код C# для удаления недопустимых символов 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-\uD7FF\uE000-\uFFFD\u10000-\u10FFFF]"; 
    return Regex.Replace(text, re, ""); 
}

Предварительно объявленные символы:

& < > " '

http://xml.silmaril.ie/specials.html

В дополнение к ответу Потаме, если вы хотите сбежать с помощью блока CDATA.

Если вы поместите свой текст в блок CDATA, вам не нужно использовать экранирование. В этом случае вы можете использовать все символы в следующем диапазоне:

графическое представление возможных символов

Примечание. Кроме того, вы не можете использовать ]]> последовательность символов Потому что это будет соответствовать концу блока CDATA.

Если все еще есть недопустимые символы (например, управляющие символы), то, вероятно, лучше использовать какую-то кодировку (например, base64).

Другой способ удалить неправильные символы 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());
}

или вы можете проверить, что все символы допустимы в формате XML.

public static bool CheckValidXmlChars(string content)
{
   return content.All(ch => System.Xml.XmlConvert.IsXmlChar(ch));
}

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

Например, символ вертикальной вкладки (\v) недопустим для XML, он является допустимым UTF-8, но не допустимым XML 1.0, и даже многие библиотеки (включая libxml2) пропускают его и выводят недействительный XML-код.

Другой простой способ избежать потенциально нежелательных символов XML / XHTML в C#:

WebUtility.HtmlEncode(stringWithStrangeChars)

Для Java-пользователей Apache имеет служебный класс (StringEscapeUtils), который имеет вспомогательный метод escapeXml, который можно использовать для экранирования символов в строке с использованием сущностей XML.

Этот ответ работал для меня

string code = Regex.Replace(item.Code, @"[\u0000-\u0008,\u000B,\u000C,\u000E-\u001F]", "");

Подробности в этой ссылке на блог

В итоге, допустимые символы в тексте:

  • табуляция, перевод строки и возврат каретки;
  • допустимы все неконтролируемые символы, кроме & и <;
  • > не действует, если следует]].

Разделы 2.2 и 2.4 спецификации XML дают подробный ответ:

Персонажи

Юридическими символами являются табуляция, возврат каретки, перевод строки и юридические символы Unicode и ISO/IEC 10646.

Данные персонажа

Символ амперсанда (&) и левая угловая скобка (<) не должны появляться в их буквальной форме, за исключением случаев, когда они используются в качестве разделителей разметки или внутри комментария, инструкции обработки или раздела CDATA. Если они нужны где-то еще, их необходимо экранировать, используя либо числовые ссылки на символы, либо строки "&" и "<" соответственно. Правая угловая скобка (>) может быть представлена ​​с помощью строки " > " и для совместимости должна быть экранирована с использованием либо " > ", либо ссылки на символ, когда она появляется в строке " ]]> " в содержимом, когда это Строка не отмечает конец раздела CDATA.

ampersand (&) is escaped to &amp;

double quotes (") are escaped to &quot;

single quotes (') are escaped to &apos; 

less than (<) is escaped to &lt; 

greater than (>) is escaped to &gt;

В C# используйте System.Security.SecurityElement.Escape или System.Net.WebUtility.HtmlEncode, чтобы экранировать эти недопустимые символы.

string xml = "<node>it's my \"node\" & i like it 0x12 x09 x0A  0x09 0x0A <node>";
string encodedXml1 = System.Security.SecurityElement.Escape(xml);
string encodedXml2= System.Net.WebUtility.HtmlEncode(xml);


encodedXml1
"&lt;node&gt;it&apos;s my &quot;node&quot; &amp; i like it 0x12 x09 x0A  0x09 0x0A &lt;node&gt;"

encodedXml2
"&lt;node&gt;it&#39;s my &quot;node&quot; &amp; i like it 0x12 x09 x0A  0x09 0x0A &lt;node&gt;"

В XML-процессоре Woodstox недопустимые символы классифицируются по этому коду

if (c == 0) {
    throw new IOException("Invalid null character in text to output");
}
if (c < ' ' || (c >= 0x7F && c <= 0x9F)) {
    String msg = "Invalid white space character (0x" + Integer.toHexString(c) + ") in text to output";
    if (mXml11) {
        msg += " (can only be output using character entity)";
    }
    throw new IOException(msg);
}
if (c > 0x10FFFF) {
    throw new IOException("Illegal unicode character point (0x" + Integer.toHexString(c) + ") to output; max is 0x10FFFF as per RFC");
}
/*
 * Surrogate pair in non-quotable (not text or attribute value) content, and non-unicode encoding (ISO-8859-x,
 * Ascii)?
 */
if (c >= SURR1_FIRST && c <= SURR2_LAST) {
    throw new IOException("Illegal surrogate pair -- can only be output via character entities, which are not allowed in this content");
}
throw new IOException("Invalid XML character (0x"+Integer.toHexString(c)+") in text to output");

Источник отсюда

Удалить недопустимые символы (ограничено + не рекомендуется) в XML-документе с помощью Java

У меня возникли проблемы с созданием шаблона из спецификации xml 1.1 , поскольку в нем есть символы длиной более 16 бит.

Проблема с Java заключается в том, что символ всегда занимает 16 бит, что означает, что после первых 64 КБ кодовых точек Unicode (т.е. в диапазоне от 0x0000 до 0xFFFF) кодовые точки не являются BMP («редкими») символами Unicode и не могут быть выраженный\uбуквально. К счастью, начиная с Java 7, мы можем использовать\x{foo}гдеfoo— шестнадцатеричное представление кодовой точки.

Наконец, приведенный ниже код удаляет из текста все запрещенные символы и нежелательные символы.

      static Pattern XMLCharInvalidPattern =
      Pattern.compile(
          "[\\x{1}-\\x{8}]|[\\x{B}-\\x{C}]|[\\x{E}-\\x{1F}]|[\\x{7F}-\\x{84}]|[\\x{86}-\\x{9F}]|[\\x{FDD0}-\\x{FDDF}]|[\\x{1FFFE}-\\x{1FFFF}]|[\\x{2FFFE}-\\x{2FFFF}]|[\\x{3FFFE}-\\x{3FFFF}]|[\\x{4FFFE}-\\x{4FFFF}]|[\\x{5FFFE}-\\x{5FFFF}]|[\\x{6FFFE}-\\x{6FFFF}]|[\\x{7FFFE}-\\x{7FFFF}]|[\\x{8FFFE}-\\x{8FFFF}]|[\\x{9FFFE}-\\x{9FFFF}]|[\\x{AFFFE}-\\x{AFFFF}]|[\\x{BFFFE}-\\x{BFFFF}]|[\\x{CFFFE}-\\x{CFFFF}]|[\\x{DFFFE}-\\x{DFFFF}]|[\\x{EFFFE}-\\x{EFFFF}]|[\\x{FFFFE}-\\x{FFFFF}]|[\\x{10FFFE}-\\x{10FFFF}]");

String invalidXmlText = "he\u0001ll\u0003o wo\uFDD0rl\u0084d";

String cleanXmlText = XMLCharInvalidPattern.matcher(invalidXmlText).replaceAll("");

// cleanXmlText = hello world

Кто-нибудь пробовал это System.Security.SecurityElement.Escape(yourstring)? Это заменит недопустимые символы XML в строке их действительным эквивалентом

Для XSL (в действительно ленивые дни) я использую:

capture="&amp;(?!amp;)" capturereplace="&amp;amp;"

переводить все &-signs, которые не следуют за вами; к правильным.

У нас есть случаи, когда входные данные находятся в CDATA, но система, которая использует XML, не принимает это во внимание. Это небрежное решение, остерегайтесь...

Другие вопросы по тегам