Неверные символы в XML
Я сейчас работаю с некоторыми XML.
У меня есть узлы, которые содержат строки, как показано ниже:
<node>This is a string</node>
Некоторые строки, которые я передаю узлам, будут содержать символы, такие как &, #, $ и т. Д.
<node>This is a string & so is this</node>
Это недействительно из-за &
Я не могу обернуть эти строки в CDATA, так как они должны быть такими, какие они есть. Я попытался найти в Интернете список символов, которые нельзя поместить в узлы XML без CDATA.
Кто-нибудь может указать мне направление одного или предоставить мне список нелегальных персонажей?
16 ответов
Единственные нелегальные персонажи &
, <
а также >
(так же как "
или же '
в атрибутах).
Они экранированы с использованием сущностей XML, в этом случае вы хотите &
за &
,
Однако на самом деле вы должны использовать инструмент или библиотеку, которая пишет для вас XML и абстрагирует подобные вещи, чтобы вам не пришлось об этом беспокоиться.
Хорошо, давайте разделим вопрос о (1) символах, которые вообще недопустимы в любом документе XML, и (2) символах, которые необходимо экранировать:
Ответ, предоставленный @dolmen Недопустимые символы в XML, все еще действителен, но его необходимо обновить с помощью спецификации XML 1.1.
1. Недопустимые символы
Описанные здесь символы - это все символы, которые разрешено вставлять в документ XML.
1.1. В XML 1.0
- Ссылка: см. Рекомендацию XML 1.0, §2.2 Символы
Глобальный список разрешенных символов:
[2] Char ::= #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF] /* any Unicode character, excluding the surrogate blocks, FFFE, and FFFF. */
В основном, управляющие символы и символы вне диапазонов Unicode не допускаются. Это также означает, что вызов, например, сущности персонажа 
запрещен.
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. Символы, которые необходимо экранировать (чтобы получить правильно оформленный документ):
<
должен быть сброшен с <
сущность, поскольку предполагается, что это начало тега.
&
должен быть сброшен с &
объект, поскольку предполагается, что он является началом ссылки на объект
>
следует избегать с >
юридическое лицо. Это не обязательно - это зависит от контекста - но настоятельно рекомендуется избегать его.
'
следует избегать с '
entity - обязателен в атрибутах, определенных в одинарных кавычках, но настоятельно рекомендуется всегда избегать его.
"
следует избегать с "
сущность - обязательна в атрибутах, определенных в двойных кавычках, но настоятельно рекомендуется всегда избегать ее.
Список допустимых символов приведен в спецификации 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, "");
}
В дополнение к ответу Потаме, если вы хотите сбежать с помощью блока 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 &
double quotes (") are escaped to "
single quotes (') are escaped to '
less than (<) is escaped to <
greater than (>) is escaped to >
В 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
"<node>it's my "node" & i like it 0x12 x09 x0A 0x09 0x0A <node>"
encodedXml2
"<node>it's my "node" & i like it 0x12 x09 x0A 0x09 0x0A <node>"
В 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;)" capturereplace="&amp;"
переводить все &-signs, которые не следуют за вами; к правильным.
У нас есть случаи, когда входные данные находятся в CDATA, но система, которая использует XML, не принимает это во внимание. Это небрежное решение, остерегайтесь...