Лучший способ кодировать текстовые данные для XML в Java? - PullRequest
85 голосов
/ 13 января 2009

Очень похоже на этот вопрос , кроме Java.

Каков рекомендуемый способ кодирования строк для вывода XML в Java. Строки могут содержать такие символы, как «&», «<» и т. Д. </p>

Ответы [ 20 ]

5 голосов
/ 20 декабря 2013

Хотя я в принципе согласен с Джоном Скитом, иногда у меня нет возможности использовать внешнюю библиотеку XML. И я нахожу странным, что две функции для выхода / отмены простого значения (атрибут или тег, не полный документ) недоступны в стандартных библиотеках XML, включенных в Java.

В результате, основываясь на различных ответах, которые я видел, опубликованных здесь и в других местах, вот решение, которое я в итоге создал (ничто не работало как простое копирование / вставка):

  public final static String ESCAPE_CHARS = "<>&\"\'";
  public final static List<String> ESCAPE_STRINGS = Collections.unmodifiableList(Arrays.asList(new String[] {
      "&lt;"
    , "&gt;"
    , "&amp;"
    , "&quot;"
    , "&apos;"
  }));

  private static String UNICODE_LOW =  "" + ((char)0x20); //space
  private static String UNICODE_HIGH = "" + ((char)0x7f);

  //should only use 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 {
            stringBuilder.append("&#" + ((int)character.charAt(0)) + ";");
            modified = true;
          }
        }
      }
      if (modified) {
        result = stringBuilder.toString();
      }
    }

    return result;
  }

Вышеуказанное включает в себя несколько разных вещей:

  1. избегает использования логики, основанной на символах, до тех пор, пока это абсолютно не требуется - улучшает совместимость с юникодом
  2. пытается быть максимально эффективным, учитывая вероятность того, что второе условие «если» является наиболее часто используемым путем
  3. - чистая функция; т.е. поточно-ориентированный
  4. хорошо оптимизируется с помощью сборщика мусора, возвращая только содержимое StringBuilder, если что-то действительно изменилось - в противном случае возвращается исходная строка

В какой-то момент я напишу обращение этой функции к Unescaped (). У меня просто нет времени, чтобы сделать это сегодня. Когда я это сделаю, я приду обновлять этот ответ с кодом. :)

5 голосов
/ 13 января 2009

Примечание. Ваш вопрос касается экранирования , а не кодировки . Escape использует <и т. Д., Чтобы синтаксический анализатор мог различить «это команда XML» и «это некоторый текст». Кодировка - это то, что вы указываете в заголовке XML (UTF-8, ISO-8859-1 и т. Д.). </p>

Прежде всего, как и все остальные, используйте библиотеку XML. XML выглядит просто, но кодирование + экранирование - это темное вуду (что вы заметите, как только встретите умлауты, японский и другие странные вещи, такие как " цифры полной ширины " (& # FF11; равен 1) ). Обеспечение читабельности XML-файла - задача Сизифа.

Я предлагаю никогда не пытаться быть умным в отношении кодировки текста и экранирования в XML. Но не позволяйте этому помешать вам; просто запомни, когда он тебя кусает (и будет).

Тем не менее, если вы используете только UTF-8, чтобы сделать вещи более читабельными, вы можете рассмотреть эту стратегию:

  • Если текст содержит «<», «>» или «&», оберните его в <![CDATA[ ... ]]>
  • Если текст не содержит этих трех символов, не деформируйте его.

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

4 голосов
/ 27 марта 2017

Для тех, кто ищет самое быстрое решение для записи: используйте методы из apache commons-lang :

Не забудьте включить зависимость:

<dependency>
  <groupId>org.apache.commons</groupId>
  <artifactId>commons-lang3</artifactId>
  <version>3.5</version> <!--check current version! -->
</dependency>
3 голосов
/ 01 сентября 2011

Чтобы избежать символов XML, проще всего использовать проект Apache Commons Lang, JAR можно загрузить из: http://commons.apache.org/lang/

Класс такой: org.apache.commons.lang3.StringEscapeUtils;

У него есть метод с именем escapeXml, который возвращает соответственно экранированную строку.

1 голос
/ 17 сентября 2018

Если вы ищете библиотеку для выполнения работы, попробуйте:

  1. Гуава 26,0 задокументировано здесь

    return XmlEscapers.xmlContentEscaper().escape(text);

    Примечание: есть также xmlAttributeEscaper()

  2. Apache Commons Text 1.4 задокументировано здесь

    StringEscapeUtils.escapeXml11(text)

    Примечание: существует также метод escapeXml10()

1 голос
/ 26 октября 2012

Вот простое решение, и оно отлично подходит для кодирования ударных символов!

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&#226;rry &#38; M&#244;e!
0 голосов
/ 17 августа 2018

Просто замените

 & with &amp;

А для других персонажей:

> with &gt;
< with &lt;
\" with &quot;
' with &apos;
0 голосов
/ 07 марта 2018

Вы можете использовать библиотеку Enterprise Security API (ESAPI) , которая предоставляет такие методы, как encodeForXML и encodeForXMLAttribute. Взгляните на документацию интерфейса Encoder ; он также содержит примеры того, как создать экземпляр DefaultEncoder .

0 голосов
/ 09 апреля 2014

Попробуйте закодировать 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());
0 голосов
/ 13 января 2009

Используйте JAXP и забудьте об обработке текста, это будет сделано автоматически.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...