Очень похоже на этот вопрос, за исключением Java.
Каков рекомендуемый способ кодирования строк для вывода XML в Java. Строки могут содержать такие символы, как «&», «<» и т. д.




Очень просто: используйте библиотеку XML. Таким образом, на самом деле это будет верно, вместо того, чтобы требовать подробного знания битов спецификации XML.
XML является является частью стандартной среды Java - смотрите org.w3c.sax и org.w3c.dom. Однако есть и более простые в использовании фреймворки, такие как JDom. Обратите внимание, что может не быть метода «кодирования строк для вывода XML» - я больше рекомендовал, чтобы вся задача XML выполнялась с библиотекой, а не просто выполняла биты одновременно с манипуляциями со строками.
Это не такой уж полезный совет при выводе XHTML - FlyingSaucer требует XML, но я не могу создавать шаблоны через XML-библиотеку :). К счастью, StringTemplate позволяет мне быстро избегать всех объектов String.
@Stephen: Я бы ожидал, что библиотека XHTML будет использовать библиотеку XML, чтобы все было в здравом уме, но предоставляло API, ориентированный на XHTML. Необходимость экранирования вручную (и убедитесь, что вы все поняли правильно, везде) - не лучшая идея, IMO.
Чтобы преобразовать дерево DOM в XML-строку, используйте преобразователь без таблицы стилей.
Я бы не назвал это «очень просто». На некоторых платформах нет библиотеки генерации xml, но вам может потребоваться кодировать некоторый текст в xml. Добавить несколько сотен килобайт библиотеки только из-за этой задачи непросто и нежелательно. Я не приму этот ответ.
@mice: вопрос помечен как Java, а в Java есть лоты библиотек XML. Действительно, есть XML API, встроенные в Java, поэтому не было бы необходимости добавлять что-нибудь еще ... но даже если бы вы это сделали, несколько сотен тысяч килобайт редко являются проблемой за пределами мобильных устройств в наши дни. Даже если бы это была не Java, я бы очень осторожно подходил к разработке на платформе, на которой не было никаких XML API ...
Рассматриваю Android. Он использует Java, и приложения должны быть небольшими. У него есть парсеры xml, но я не знаю об обратном (он называется «сериализатор xml»?).
@mice: DOM API прекрасно способен генерировать XML. Или есть довольно небольшие сторонние библиотеки. (Например, размер jar-файла JDom составляет 114 КБ.) Использование XML API по-прежнему является рекомендуемым способом создания XML.
Как насчет этого: stackoverflow.com/questions/439298/… для простой цели экранирования текста xml (не построения xml).
@mice: Думаю, я довольно четко изложил свою позицию. Если я хочу что-то делать с XML, я использую XML API. Вот в чем они хороши. По моему опыту, довольно редко нужно избегать XML, если вы не строительство XML. Я не буду комментировать пригодность кода, который я бы в принципе не использовал. (Обновлено: На самом деле, я буду в этом случае. Я прокомментирую напрямую.)
Нет проблем с вашим подходом. Однако я использую такой код, который создает xml с помощью String.printf и заполняет некоторый текст в предварительно созданной строке xml. Вы можете использовать xml lib, я не могу в моем конкретном случае.
@mice: Похоже, вы для начала выбрали плохой инструмент. Любая библиотека, которая создает для меня XML и вставляет в него фрагменты текста, должна сама выполнять экранирование. Непросто получить полное представление о ваших конкретных требованиях в комментариях, но я, безусловно, поддерживаю свой ответ.
Просто общее замечание о том, что слово «правильный» подчеркнуто: простое использование любой XML-библиотеки не гарантирует, что это будет правильно ;-). Разработчики библиотеки тоже люди. Конечно, вы будете в безопасности со стандартными вещами или чем-то вроде Apache Commons Lang ... просто всегда удивляйтесь тому, как люди просто слепо доверяют чужому коду ...
@JonSkeet Я конвертирую файл csv в xml, просто используя Java (без Groovy). Какие существуют библиотеки XML для такого преобразования? Спасибо!
@ Ученик: Их много. Возможно, вы захотите начать с jdom.
Мы используем библиотеку woodstox stax, и у нее нет способа написания текста, в котором он будет кодировать специальные символы. У него есть вызов writeCharacters, но он не кодирует> (кодирует <).
@DavidThielen Это не нужно кодировать. Это часто бывает, но спецификация XML IIRC называет это нормальным, чтобы не кодировать.
Будь осторожен! XML и, следовательно, DOM API поддерживает только символы в диапазонах # x9 | #xA | #xD | [# x20- # xD7FF] | [# xE000- # xFFFD] | [# x10000- # x10FFFF]. Если вы хотите использовать символы за пределами этого диапазона, вы должны дополнительно экранировать их с помощью собственной системы экранирования. Вы можете использовать мои методы здесь stackoverflow.com/a/59475093/3882565.
@ stonar96 Да, я предполагал, что правильный XML-документ - это желаемый результат. Если вам нужно выразить то, что нельзя выразить в XML, это большая проблема. Жаль, что XML 1.1 так и не стал популярным, поскольку это решает эту проблему.
Извините, я проголосовал против и ошибся. Теперь не могу вернуть его обратно. Это правильный ответ
@Alexandr: На самом деле не проблема :)
Просто используйте.
<![CDATA[ your text here ]]>
Это позволит использовать любые символы, кроме концовки
]]>
Таким образом, вы можете включать недопустимые символы, такие как & и>. Например.
<element><![CDATA[ characters such as & and > are allowed ]]></element>
Однако атрибуты необходимо экранировать, поскольку для них нельзя использовать блоки CDATA.
В большинстве случаев это не то, что вам следует делать. Слишком много людей злоупотребляют тегами CDATA. Назначение CDATA - сказать процессору, чтобы он не обрабатывал его как XML, а просто передавал его. Если вы пытаетесь создать файл XML, вы должны создавать XML, а не просто передавать байты через какой-то элемент оболочки.
@Mads, использование CDATA приводит к правильному XML-файлу, так что это так же хорошо, как и "правильным способом". Если вам это не нравится, затем проанализируйте его, измените идентичность и распечатайте.
Если вы помещаете текст в элемент CDATA, вам нужно избежать закрывающего маркера CDATA: "]]>" ... кроме того, что вы не можете этого избежать. Поэтому вместо этого вам нужно разбить свой код на части, где вы помещаете половину данных в один элемент CDATA, а другую половину - в секунду: <! [CDATA [Эти данные содержат закрывающий маркер CDATA: "]]]]> <! [CDATA [> "поэтому его пришлось разделить.]]> ... В конце концов, может быть намного проще вместо этого просто экранировать '<', '>' и '&'. Конечно, многие приложения игнорируют потенциальную проблему с закрывающими маркерами CDATA в данных. Думаю, незнание - это блаженство. :)
@StijndeWitt абсолютно прав. CDATA - не панацея от экранирования специальных символов.
Это плохая идея. CDATA не допускает никаких символов вне кодировки XML.
В XML-файле (Java и DOM Parser) "& lt;" присутствует как текстовое значение узла, но когда для этого узла используется node.getContentType, оно преобразуется в "<". Есть ли способ получить "& lt;" сам вместо "<"?
Как уже упоминалось, использование библиотеки XML - самый простой способ. Если вы действительно хотите сбежать, вы можете заглянуть в StringEscapeUtils из библиотеки Apache Commons Lang.
Это может быть подходящим вариантом, если вас не волнует абсолютная правильность, например, если вы собираете прототип.
Метод escapeXml StringEscapeUtils кажется немного дорогостоящим. Есть ли более эффективный метод, который работает с StringBuffer вместо String?
Используйте StringEscapeUtils.escapeXml(str) из commons-lang. Я использую его в приложении App Engine - работает как шарм. Вот Документ Java для этой функции:
Работает ли этот метод как для содержимого, так и для атрибутов XML? Мне кажется, что это не работает с атрибутами. Кажется, это не ускользнет от \t, \n и \r.
@Lii и \t, \n или \r нужно экранировать?
Обратите внимание, что StringEscapeUtils.escapeXml() не экранирует управляющие символы, которые во многих ситуациях недопустимы в XML.
Обратите внимание, что он был перемещен с commons-lang на commons-text
Примечание. Ваш вопрос касается побег, а не кодирование. Для экранирования используется <и т. д., Чтобы синтаксический анализатор мог различать «это команда XML» и «это некоторый текст». Кодировка - это то, что вы указываете в заголовке XML (UTF-8, ISO-8859-1 и т. д.).
Прежде всего, как все говорили, используйте библиотеку XML. XML выглядит простым, но кодирование + экранирование - это темное вуду (которое вы заметите, как только встретите умляуты, японский язык и другие странные вещи, такие как «цифры полной ширины» (& # FF11; is 1)). Обеспечение читабельности XML - задача Сизифа.
Я предлагаю никогда не хитрить в кодировании текста и экранировании в XML. Но не позволяйте этому останавливать вас от попыток; просто помните, когда он вас укусит (и будет).
Тем не менее, если вы используете только UTF-8, чтобы сделать вещи более читабельными, вы можете рассмотреть эту стратегию:
<![CDATA[ ... ]]>Я использую это в редакторе SQL, и это позволяет разработчикам вырезать и вставлять SQL из стороннего инструмента SQL в XML, не беспокоясь об экранировании. Это работает, потому что в нашем случае SQL не может содержать умляутов, так что я в безопасности.
Это хорошо сработало для меня, чтобы предоставить экранированную версию текстовой строки:
public class XMLHelper {
/**
* Returns the string where all non-ascii and <, &, > are encoded as numeric entities. I.e. "<A & B >"
* .... (insert result here). The result is safe to include anywhere in a text field in an XML-string. If there was
* no characters to protect, the original string is returned.
*
* @param originalUnprotectedString
* original string which may contain characters either reserved in XML or with different representation
* in different encodings (like 8859-1 and UFT-8)
* @return
*/
public static String protectSpecialCharacters(String originalUnprotectedString) {
if (originalUnprotectedString == null) {
return null;
}
boolean anyCharactersProtected = false;
StringBuffer stringBuffer = new StringBuffer();
for (int i = 0; i < originalUnprotectedString.length(); i++) {
char ch = originalUnprotectedString.charAt(i);
boolean controlCharacter = ch < 32;
boolean unicodeButNotAscii = ch > 126;
boolean characterWithSpecialMeaningInXML = ch == '<' || ch == '&' || ch == '>';
if (characterWithSpecialMeaningInXML || unicodeButNotAscii || controlCharacter) {
stringBuffer.append("&#" + (int) ch + ";");
anyCharactersProtected = true;
} else {
stringBuffer.append(ch);
}
}
if (anyCharactersProtected == false) {
return originalUnprotectedString;
}
return stringBuffer.toString();
}
}
stringBuffer.append ("& #" + (int) ch + ";"); Это не сработает для многобайтовых символов. Я сейчас сталкиваюсь с этим с символом эмодзи, последовательностью UTF8 F0 9F 98 8D.
В то время как идеализм говорит, что используйте XML-библиотеку, ИМХО, если у вас есть базовое представление об XML, тогда здравый смысл и производительность говорят, что шаблон полностью. Возможно, это и более читабельно. Хотя использование функций экранирования библиотеки, вероятно, является хорошей идеей.
Подумайте об этом: XML было предназначен для написания людьми.
Используйте библиотеки для генерации XML, когда ваш XML как «объект» лучше моделирует вашу проблему. Например, если подключаемые модули участвуют в процессе построения этого XML.
Обновлено: что касается того, как на самом деле избежать XML в шаблонах, использование CDATA или escapeXml(string) из JSTL - два хороших решения, escapeXml(string) можно использовать следующим образом:
<%@taglib prefix = "fn" uri = "http://java.sun.com/jsp/jstl/functions"%>
<item>${fn:escapeXml(value)}</item>
Чтобы избежать символов XML, самый простой способ - использовать проект Apache Commons Lang, JAR, загружаемый с: http://commons.apache.org/lang/
Это класс: org.apache.commons.lang3.StringEscapeUtils;
У него есть метод с именем «escapeXml», который возвращает строку с соответствующим экранированием.
Обновление: escapeXml устарел - используйте escapeXml10. Ссылка commons.apache.org/proper/commons-lang/javadocs/api-3.3/org/…
Поведение StringEscapeUtils.escapeXml () изменилось с Commons Lang 2.5 на 3.0. Теперь он больше не экранирует символы Unicode больше 0x7f.
Это хорошо, старый метод должен был немного стараться избежать сущностей, которые можно было просто вставить в документ utf8.
Новые средства защиты, которые будут включены в Google Guava 11.0, также кажутся многообещающими: http://code.google.com/p/guava-libraries/issues/detail?id=799
Вот XML-эскейпер Guava: code.google.com/p/guava-libraries/source/browse/guava/src/co m /…. В общем, я обнаружил, что Guava лучше спроектирован, чем Apache Commons.
Попробуй это:
String xmlEscapeText(String t) {
StringBuilder sb = new StringBuilder();
for(int i = 0; i < t.length(); i++){
char c = t.charAt(i);
switch(c){
case '<': sb.append("<"); break;
case '>': sb.append(">"); break;
case '\"': sb.append("""); break;
case '&': sb.append("&"); break;
case '\'': sb.append("'"); break;
default:
if (c>0x7e) {
sb.append("&#"+((int)c)+";");
}else
sb.append(c);
}
}
return sb.toString();
}
Я вижу как минимум две ошибки. Один тонкий, другой нет. У меня не было бы такого бага, потому что я бы вообще не стал изобретать велосипед.
А перебирать строки Unicode немного сложнее. Смотрите здесь: stackoverflow.com/q/1527856/402322
Я предполагаю, что несущественная ошибка - это исправленная ошибка - я также получаю предупреждение о добавлении конкатенированных строк в StringBuilder. В чем заключается тонкая ошибка? Мне, честно говоря, нравится подобное автономное решение для моей текущей реализации, встроенное в которое мы не можем импортировать библиотеки apache.
Не уверен, что это тонкий, но лучше рассмотреть случай, когда t==null.
Для сравнения: org.apache.commons.lang3.StringEscapeUtils.escapeXml поддерживает только пять основных XML-сущностей (gt, lt, quot, amp, apos). Обратите внимание, что символы Unicode больше 0x7f больше не экранируются. (источник)
Разве в вашем случае по умолчанию условие if не должно читаться как «if (c <32 || c> 0x7e) {»? В противном случае вы кодируете все символы меньше пробела как сами себя, что является недопустимым содержимым XML, верно?
@ chaotic3quilibrium: ожидаемые символы <32 - это только новые строки или вкладки, и они не экранируются.
@PointerNull Вы в этом уверены ?! Я читал МНОЖЕСТВО других мест, от которых тоже нужно сбежать. У вас есть официальная ссылка, которую вы можете процитировать, в которой прямо говорится, что от них нельзя избегать? Если так, я был бы очень признателен (и, возможно, это стало бы препятствием для огромного количества предложений по кодированию этого пространства).
@PointerNull Хорошо, сейчас это старое, но многие непечатаемые символы Unicode, которые сопоставляются с ASCII для совместимости, будут переданы вместе с этой процедурой. Я думаю о таких вещах, как встроенные нулевые значения 0x00, встроенные «начало текста» 0x02, «конец передачи» 0x04 и так далее. Конечно, этого нельзя ожидать от вашей типичной строки Java, но забавно, как такие вещи проскальзывают.
Это ужасное решение, никто, читающий, им не пользуется. Это преобразует "& amp;" в "& ampamp;" и что "нет. .
@ user1003916: экранирование XML предназначено для преобразования любого & вхождения в & amp; так вот как это должно работать. Если вы исключаете уже экранированную строку, это ваша вина.
Я доволен финальной версией. Java SE компактен, быстр и эффективен. В моей книге всегда лучше делать то, что нужно, чем загружать еще 100 МБ вредоносного ПО.
Все символы ниже 0x20, кроме 0x09, 0x0A и 0x0D, недопустимы в XML. Это применимо независимо от того, сбежали они или нет. Единственный правильный способ справиться с ними - пропустить их или выбросить исключение. В остальном это хорошее решение, подобное тому, которое мы обычно используем.
@ceving Здесь вам не нужно иметь дело с Unicode, поскольку все символы вне BMP можно просто скопировать в том виде, в каком они есть. Единственные пять кодовых точек, нуждающихся в обработке, находятся в BMP.
Для метода, который также поддерживает недопустимые символы XML, такие как '\u0000', см. Мой ответ здесь stackoverflow.com/a/59475093/3882565.
Вопрос был в том, «каков рекомендуемый способ». Написание собственного метода для общей задачи - нет.
StringEscapeUtils.escapeXml() не экранирует управляющие символы (<0x20). XML 1.1 допускает управляющие символы; XML 1.0 этого не делает. Например, XStream.toXML() успешно сериализует управляющие символы объекта Java в XML, который синтаксический анализатор XML 1.0 отклонит.
Чтобы экранировать управляющие символы с помощью Apache commons-lang, используйте
NumericEntityEscaper.below(0x20).translate(StringEscapeUtils.escapeXml(str))
Вот простое решение, и оно отлично подходит для кодирования акцентированных символов!
String in = "Hi Lârry & Môe!";
StringBuilder out = new StringBuilder();
for(int i = 0; i < in.length(); i++) {
char c = in.charAt(i);
if (c < 31 || c > 126 || "<>\"'\\&".indexOf(c) >= 0) {
out.append("&#" + (int) c + ";");
} else {
out.append(c);
}
}
System.out.printf("%s%n", out);
Выходы
Hi Lârry & Môe!
Разве «31» в первой строке «if» не должно быть «32»; т.е. меньше, чем пробел? И если "31" должно остаться, то не следует ли его исправить, чтобы читать "if (c <= 31 || ..." (дополнительный знак равенства после знака меньше)?
Хотя я в принципе согласен с Джоном Скитом, иногда у меня нет возможности использовать внешнюю библиотеку XML. И мне кажется странным, что две функции для экранирования / отмены экранирования простого значения (атрибута или тега, а не полного документа) недоступны в стандартных библиотеках XML, включенных в Java.
В результате и на основе различных ответов, которые я видел здесь и в других местах, вот решение, которое я создал (ничто не работало как простое копирование / вставка):
public final static String ESCAPE_CHARS = "<>&\"\'";
public final static List<String> ESCAPE_STRINGS = Collections.unmodifiableList(Arrays.asList(new String[] {
"<"
, ">"
, "&"
, """
, "'"
}));
private static String UNICODE_NULL = "" + ((char)0x00); //null
private static String UNICODE_LOW = "" + ((char)0x20); //space
private static String UNICODE_HIGH = "" + ((char)0x7f);
//should only be used for the content of an attribute or tag
public static String toEscaped(String content) {
String result = content;
if ((content != null) && (content.length() > 0)) {
boolean modified = false;
StringBuilder stringBuilder = new StringBuilder(content.length());
for (int i = 0, count = content.length(); i < count; ++i) {
String character = content.substring(i, i + 1);
int pos = ESCAPE_CHARS.indexOf(character);
if (pos > -1) {
stringBuilder.append(ESCAPE_STRINGS.get(pos));
modified = true;
}
else {
if ( (character.compareTo(UNICODE_LOW) > -1)
&& (character.compareTo(UNICODE_HIGH) < 1)
) {
stringBuilder.append(character);
}
else {
//Per URL reference below, Unicode null character is always restricted from XML
//URL: https://en.wikipedia.org/wiki/Valid_characters_in_XML
if (character.compareTo(UNICODE_NULL) != 0) {
stringBuilder.append("&#" + ((int)character.charAt(0)) + ";");
}
modified = true;
}
}
}
if (modified) {
result = stringBuilder.toString();
}
}
return result;
}
Вышеупомянутое вмещает несколько разных вещей:
В какой-то момент я напишу инверсию этой функции toUnescaped (). У меня просто нет на это времени сегодня. Когда я это сделаю, я обновлю этот ответ кодом. :)
Выглядит довольно хорошо для меня. Я не хочу добавлять в свой проект еще одну банку только для одного метода. Если вы дадите разрешение, могу я скопировать и вставить ваш код в свой?
@SatishMotwani Конечно, вы можете взять приведенный выше код и делать с ним, как хотите. Насколько я понимаю, любой код, опубликованный на StackOverflow, считается свободным от авторских прав (не рассматривается как произведение в целом). С другой стороны, кому-то было бы чрезвычайно сложно выдвинуть какие-либо претензии по поводу авторских прав и ожидать какого-то результата для себя.
Спасибо, что разрешили :-) Воспользуюсь.
Вы забыли обрабатывать символы NUL. И, может быть, и другие вещи.
@ DavidBalažic Хорошо, объясните, пожалуйста, поподробнее, что я мог пропустить? Пожалуйста, прочтите код более внимательно. Я обработал КАЖДЫЙ ОДИН символ Unicode (из 1111998), включая символ null. Можете ли вы объяснить определение двух значений, UNICODE_LOW и UNICODE_HIGH? Пожалуйста, перечитайте if, в котором используются эти два значения. Обратите внимание, что null (\u0000, который является (int)0) не находится между этими двумя значениями. Прочтите, как он становится правильно "экранированным", как ВСЕ символы Unicode, существующие вне диапазона UNICODE_LOW и UNICODE_HIGH, с помощью техники &#.
@chaotic3quilibrium NULL недопустим в XML (и некоторых других символах). Неважно, как вы это кодируете. Это незаконно. (также: действительно нет необходимости экранировать символы Unicode, они хорошо поддерживаются в XML, за исключением случаев, когда сам документ XML имеет кодировку, отличную от Unicode)
@ DavidBalažic Ах. Tysvm за ваше объяснение. Я нашел справочный документ, который явно определяет, что вы утверждаете о Unicode null. Однако это буквально ЕДИНСТВЕННЫЙ запрещенный символ. Многие категорически не одобряют этого, но NUL является единственным явно безоговорочно ограниченным: en.wikipedia.org/wiki/Valid_characters_in_XML
@ DavidBalažic Я обновил ответ, чтобы теперь включить ограничение, указанное в ссылке, которой я поделился в своем последнем комментарии. Я добавил комментарий и логику, чтобы правильно обработать этот случай. Опять же, tysvm за точный отзыв.
Попробуйте закодировать XML с помощью сериализатора Apache XML
//Serialize DOM
OutputFormat format = new OutputFormat (doc);
// as a String
StringWriter stringOut = new StringWriter ();
XMLSerializer serial = new XMLSerializer (stringOut,
format);
serial.serialize(doc);
// Display the XML
System.out.println(stringOut.toString());
public String escapeXml(String s) {
return s.replaceAll("&", "&").replaceAll(">", ">").replaceAll("<", "<").replaceAll("\"", """).replaceAll("'", "'");
}
Объединение вызовов replaceAll в цепочку очень неэффективно, особенно для больших строк. Каждый вызов приводит к созданию нового объекта String, который будет висеть до тех пор, пока не будет собран мусор. Кроме того, каждый вызов требует повторного прохождения строки. Это можно объединить в один ручной цикл со сравнениями с каждым целевым символом на каждой итерации.
Это должен быть принятый ответ, даже если он неэффективен. Решает проблему в одной строке.
И в нем много ошибок. См. этот комментарий выше
Чтобы исправить эти ошибки, вы можете дополнительно использовать мой метод здесь stackoverflow.com/a/59475093/3882565. Обратите внимание, что это не замена, но может использоваться дополнительно.
Для тех, кто ищет наиболее быстрое решение: используйте методы из apache commons-lang:
StringEscapeUtils.escapeXml10() для xml 1.0StringEscapeUtils.escapeXml11() для xml 1.1StringEscapeUtils.escapeXml() теперь устарел, но обычно использовался в прошломНе забудьте включить зависимость:
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.5</version> <!--check current version! -->
</dependency>
Этому вопросу восемь лет, и он все еще не является полностью правильным! Нет, вам не нужно импортировать весь сторонний API для выполнения этой простой задачи. Плохой совет.
Следующий метод:
Я попытался оптимизировать для наиболее распространенного случая, но при этом убедился, что вы можете пропустить через него / dev / random и получить действительную строку в XML.
public static String encodeXML(CharSequence s) {
StringBuilder sb = new StringBuilder();
int len = s.length();
for (int i=0;i<len;i++) {
int c = s.charAt(i);
if (c >= 0xd800 && c <= 0xdbff && i + 1 < len) {
c = ((c-0xd7c0)<<10) | (s.charAt(++i)&0x3ff); // UTF16 decode
}
if (c < 0x80) { // ASCII range: test most common case first
if (c < 0x20 && (c != '\t' && c != '\r' && c != '\n')) {
// Illegal XML character, even encoded. Skip or substitute
sb.append("�"); // Unicode replacement character
} else {
switch(c) {
case '&': sb.append("&"); break;
case '>': sb.append(">"); break;
case '<': sb.append("<"); break;
// Uncomment next two if encoding for an XML attribute
// case '\'' sb.append("'"); break;
// case '\"' sb.append("""); break;
// Uncomment next three if you prefer, but not required
// case '\n' sb.append(" "); break;
// case '\r' sb.append(" "); break;
// case '\t' sb.append("	"); break;
default: sb.append((char)c);
}
}
} else if ((c >= 0xd800 && c <= 0xdfff) || c == 0xfffe || c == 0xffff) {
// Illegal XML character, even encoded. Skip or substitute
sb.append("�"); // Unicode replacement character
} else {
sb.append("&#x");
sb.append(Integer.toHexString(c));
sb.append(';');
}
}
return sb.toString();
}
Обновлено: для тех, кто продолжает настаивать на глупости написания собственного кода для этого, когда есть совершенно хорошие Java API для работы с XML, вам может быть интересно узнать, что StAX API включен в Oracle Java 8 (я не тестировал другие ) не может правильно кодировать содержимое CDATA: он не экранирует]]> последовательности содержимого. Сторонняя библиотека, даже если она является частью ядра Java, не всегда лучший вариант.
+1 за автономный код. Просто сравнивая ваш код с реализация гуавы, мне интересно, а что насчет '\ t', '\ n', '\ r'? См. Также примечания на документы гуавы
Нет необходимости экранировать \ n, \ r и \ t, они действительны, хотя они делают форматирование немного некрасивым. Я изменил код, чтобы показать, как их убрать, если вы этого хотите.
В CDATA есть способ нет "избежать]]>".
Затем он должен отклонить содержимое, вызвав исключение IllegalArgumentException. Ни при каких обстоятельствах он не должен заявлять об успешном выполнении, но при этом выводить недопустимый XML.
Вместо замены недопустимых символов в XML 1.0 символом подстановки Unicode вы можете использовать здесь мои методы stackoverflow.com/a/59475093/3882565.
Вы можете использовать Библиотека Enterprise Security API (ESAPI), который предоставляет такие методы, как encodeForXML и encodeForXMLAttribute. Взгляните на документацию интерфейса Кодировщик; он также содержит примеры того, как создать экземпляр DefaultEncoder.
Просто замените
& with &
И для других персонажей:
> with >
< with <
\" with "
' with '
Если вы ищете библиотеку для работы, попробуйте:
Гуава 26,0 задокументировано здесь
return XmlEscapers.xmlContentEscaper().escape(text);
Note: There is also an
xmlAttributeEscaper()
Текст 1.4 Apache Commons задокументированный здесь
StringEscapeUtils.escapeXml11(text)
Note: There is also an
escapeXml10()method
Вот что я нашел после повсеместных поисков решения:
Получите библиотеку Jsoup:
<!-- https://mvnrepository.com/artifact/org.jsoup/jsoup -->
<dependency>
<groupId>org.jsoup</groupId>
<artifactId>jsoup</artifactId>
<version>1.12.1</version>
</dependency>
Потом:
import org.jsoup.Jsoup
import org.jsoup.nodes.Document
import org.jsoup.nodes.Entities
import org.jsoup.parser.Parser
String xml = '''<?xml version = "1.0"?>
<SOAP-ENV:Envelope
xmlns:SOAP-ENV = "http://www.w3.org/2001/12/soap-envelope"
SOAP-ENV:encodingStyle = "http://www.w3.org/2001/12/soap-encoding">
<SOAP-ENV:Body xmlns:m = "http://www.example.org/quotations">
<m:GetQuotation>
<m:QuotationsName> MiscroSoft@G>>gle.com </m:QuotationsName>
</m:GetQuotation>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>'''
Document doc = Jsoup.parse(new ByteArrayInputStream(xml.getBytes("UTF-8")), "UTF-8", "", Parser.xmlParser())
doc.outputSettings().charset("UTF-8")
doc.outputSettings().escapeMode(Entities.EscapeMode.base)
println doc.toString()
Надеюсь, это кому-то поможет
I have created my wrapper here, hope it will helps a lot, Click here You can modify depends on your requirements
Вы можете порекомендовать такую библиотеку? (Я нахожу удивительным, что это не стандартная часть Java версии 5 ... такая обычная задача).