Что такое недопустимые символы в XML

229

Я работаю с некоторым XML, который содержит строки вроде:

<node>This is a string</node>

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

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

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

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

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

RailsSon
источник
4
Любая уважительная причина не использовать CDATA?
Петер Перхач
1
Да, я передаю строку в CMS с именем Fatwire, и узел с данными не может быть в CDATA, я не уверен, почему так работает Fatwire :(
RailsSon
@Peter: Как я могу использовать CDATA в моем случае? stackoverflow.com/questions/6906705/…
Радек

Ответы:

147

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

Они сбежали с помощью XML - сущности , в этом случае вы хотите &amp;для &.

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

Welbog
источник
82
Некоторые элементы управления символов также не допускаются. Смотрите мой ответ ниже.
дольмен
43
На самом деле это не совсем так. Ряд символов более низкого ascii также недопустим. Если вы попытаетесь записать 0x03 в документ Xml, вы получите ошибку, как правило, и если вам удастся правильно скрыть ее в документе XML, большинство зрителей будут жаловаться на недопустимый символ. Крайний случай, но это случается.
Рик Страл
16
Этот ответ абсолютно неверен. Вот мое исключение XML с недопустимым символом 0x12 «System.Xml.XmlException:», шестнадцатеричное значение 0x12, недопустимый символ »
Джордж
8
Это также неправильно в другом направлении; Наряду с пропуском каждого недопустимого символа, символы, которые он утверждает, являются незаконными, являются совершенно законными, хотя и имеют особое значение в контексте.
Джон Ханна
6
В XML 1.0 есть много недопустимых символов. Фактически даже использование символьной сущности для большинства управляющих символов приведет к ошибке при разборе.
Тейн
218

Хорошо, давайте разделим вопрос о персонажах, которые:

  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;лица - обязательный в атрибутах , определенных в одинарные кавычки , но настоятельно рекомендуется всегда избежать.

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

potame
источник
171

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

Char       ::=      #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF]  /* any Unicode character, excluding the surrogate blocks, FFFE, and FFFF. */
дольмен
источник
7
Вы должны заметить, что хотя они и являются законными символами, & < > " 'в определенных контекстах их следует экранировать.
Д.Шоули
7
«Законно» в данном контексте означает, что их окончательно декодированные значения являются законными, а не то, что они являются законными в потоке. Как указано выше, некоторые допустимые значения должны быть экранированы в потоке.
SilverbackNet
У меня есть проблема, где 0x1c является недопустимым символом ... Ищет возможность в Java, как избежать этого ....
basZero
Хороший обзор, какие символы действительны, а какие нет, можно найти здесь validchar.com/d/xml10/xml10_namestart
Dr. Max Völkel
8
@xamde Этот список хорош, но он показывает только символы, которые можно использовать для запуска элемента XML. Проблема в том, какие символы допустимы в XML-файле в целом. Есть определенные символы, которые нигде не разрешены.
Джон Сенчина
59

Это код 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, ""); 
}
mathifonseca
источник
6
Для Java шаблон регулярных выражений будет таким же. И тогда вы можете использовать метод replaceAll в классе String, который ожидает шаблон регулярного выражения в качестве параметра. Проверьте это: docs.oracle.com/javase/6/docs/api/java/lang/…
mathifonseca
2
В моей строке есть такие недопустимые символы: SUSITARIMO D & # x5; L DARBO SUTARTIES Этот код не удаляет & # x5; Таким образом, XML-документ не может инициализироваться.
Дайнюс Крейвис,
Я считаю, что вы не можете просто поместить этот шаблон в конструктор регулярных выражений .NET. Я не думаю, что он распознает \u10000и \u10FFFFкак отдельные символы, так как они требуют двух charэкземпляров utf-16 каждый, и, согласно документам, может быть не более 4 цифр. [\u10000-\u10FFFF]скорее всего , анализируются как [ \u1000, 0-\u10FF, F, F] , который является странным , но законно.
GSerg
17

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

& < > " '

См. « Какие специальные символы в XML? » Для получения дополнительной информации.

CGP
источник
Неправильно. Это не все недействительно. Только & и <всегда недопустимы в тексте.
rghome
7

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

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

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

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

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

bvdb
источник
3
Есть ли в блоке CDATA или нет, некоторые символы запрещены в XML.
дольмен
4
точно, разве это не то, что я написал? цитата: "все символы в следующем диапазоне ". Под этим я подразумеваю только персонажей в этом конкретном диапазоне. Другие персонажи не допускаются. - полностью согласен ; но я не понимаю, отрицательный голос. - никаких обид.
17
6

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

WebUtility.HtmlEncode(stringWithStrangeChars)
tiands
источник
Неправильные персонажи
дольмен
1
Он написал Xml не HTML.
Эмануэле
6

Другой способ удаления неправильных символов 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

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

Алекс Важев
источник
2

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

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

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

Персонажи

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

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

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

rghome
источник
1
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;"
живи любя
источник
1

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

Нулевой указатель
источник
1

В 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");

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

Жером Сен-Ив
источник
-1

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

klaydze
источник
-5

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

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

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

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

Самсон Виклунд
источник
8
Если это небрежно, действительно ли необходимо опубликовать это здесь?
дольмен