2009-12-21 5 views
1

Я пытаюсь создать XML-документ (rss-канал) и разработал все изломы в нем, за исключением одной проблемы с кодировкой символов. Проблема в том, что я использую кодировку UTF-8, например, <?xml version="1.0" encoding="UTF-8"?>, за исключением того, что сам документ не кодируется в UTF-8.Преобразование XML-документа из Latin1 в UTF8 с использованием Java

Я использую пакет org.apache.ecs.xml для создания всех тегов. Затем я использую doc.output(stream) для записи контента. Этот метод, похоже, не пишет вывод с использованием UTF-8, и я не знаю, как это сделать. До тех пор, пока я этого не сделаю, некоторые символы (британский фунт - это то, что я впервые заметил) не получают должным образом у большинства читателей.

--Updated с более information--

Я закончил с использованием плохое решение (как объяснено в комментариях), чтобы решить эту проблему. Правильный ответ, похоже, не использует библиотеку org.apache.ecs.xml. Спасибо всем за помощь. StackOverflow снова побеждает.

+1

Просьба представить образец кода, который показывает, как вы используете пакет 'org.apache.ecs.xml', и как вы готовите объект' doc'. –

+0

О, мальчик ... откуда этот фунт? GUI-контроль? Командная строка? Встроенный код? –

+0

Ваш вопрос/формат - это круто, не волнуйтесь и приветствуйтесь! –

ответ

1

Вот решение, с которым мой коллега придумал, что я ДУМАЮ, это правильный способ сделать это, но что я знаю. Вместо использования doc.output(stream) мы использовали:

 try { 
      IOUtils.write(doc.toString(), stream, "UTF-8"); 
     } catch (IOException e) { 
      throw new RuntimeException(e); 
     } 

Чтобы быть честным, я не совсем понимаю проблему пока, поэтому у меня возникли проблемы, в первую очередь. Похоже, что решение @ subtenante прошло и преобразовало любой символ, который UTF-8 не мог представить и заменил его на юникодный объект. Это решение, похоже, пишет в поток с использованием кодировки UTF-8, как мне изначально требовалось doc.output. Я не знаю точной разницы, просто я решил свои проблемы. Любые дополнительные комментарии, которые помогут мне понять проблему, будут оценены.

+0

Это решение выглядит действительно нормально, если у вас есть доступ к библиотеке commons-io. Мое решение имеет то преимущество, что независимость вывода не зависит, поскольку содержит только чистый ASCII. Это решение использует UTF-8 и кодирует расширенные символы правильным образом, как определено в вашем атрибуте кодирования. Основное различие в результате заключается в том, что ваш метод ставит расширенные символы в 2 или 3 байта, в то время как для каждого требуется 8 байт. Но XML все равно. :) – glmxndr

0

Я не знаком с этим пакетом, но из источника в Интернете, я подозреваю, что это может быть разорван:

http://kickjava.com/src/org/apache/ecs/xml/XMLDocument.java.htm

содержит такие вещи, как

 for (int i=0; i<prolog.size(); i++) { 
268    ConcreteElement e = (ConcreteElement)prolog.elementAt(i); 
269    e.output(out); 
270    // XXX really this should use line separator! 
271 // XXX should also probably check for pretty print 
272 // XXX also probably have difficulties with encoding 

, который наводит на мысль о проблемах.

Мы используем XOM (http://www.xom.nu) и что конкретно имеет setEncoding() на его Serializer, так что я хотел бы предложить изменения пакетов ...

+0

К сожалению, я действительно видел это, но я надеюсь, что есть какое-то обходное решение. Независимо от того, спасибо за предложение пакета. – UmYeah

0

Вот функция, я написал, чтобы преобразовать все символы не-ASCII в соответствующие им организация. Можете помочь вам дезинфицировать некоторый контент PCDATA перед выходом.

/** 
* Creates xml entities for non ascii characters in the given String. 
*/ 
public static String xmlEntitify(String in){ 

    StringBuffer b = new StringBuffer(); 

    for (int i=0;i<in.length();i++){ 

     Character c = in.charAt(i); 
     if (c<128){ 
      b.append(c); 
     } 
     else if (c=='\ufeff'){ 
      // BOM character, just remove it 
     } 
     else { 
      String cstr = Integer.toHexString(c).toUpperCase(); 
      while(cstr.length()<4){ 
       cstr="0"+cstr; 
      } 
      b.append("&#x"); 
      b.append(cstr); 
      b.append(";"); 
     } 
    } 
    return b.toString(); 
} 

Прочитайте входной поток в String content и записать в выходной поток xmlEntitify(content).

Ваш выход гарантированно содержит только символы ASCII, не более проблем с кодировкой.

UPDATE

Учитывая замечания, я буду еще смелее: если вы не санировать ваши данные, вы звоните на неприятности. Думаю, вы по крайней мере уже заменили символы < и & на вашем PCDATA. Если нет, вы определенно должны. У меня есть еще один вариант описанного выше способа, который, вместо первого if, имеет:

if (c<128 && c!='&' && c!='<' && c!='>' && c!='"'){ 
    b.append(c); 
} 

так, что эти символы также преобразуются в соответствующие сущности Unicode. Это преобразует все мои PCDATA в unicode-дружественные строки только для ASCII. У меня не было проблемы с кодированием, поскольку я использую эту технику. Я никогда не выдавал XML PCDATA, который не прошел через этот метод: это не подметает слона под ковром. Это просто избавление от проблемы, поскольку оно является общим, каким может быть.

+0

Это решает неправильную проблему. Ему нужно, чтобы UTF-8 кодировал выходной поток, который ОЧЕНЬ отличается от подстановки символов символов для данных, отличных от ascii. Эти объекты символов будут по-прежнему указывать на кодовые точки Latin1, а не на кодовые точки UTF-8. –

+0

Как писал Джим (и мой коллега указал мне) это просто прикрывает проблему. Это стало моим временным решением только потому, что мне нужно было быстро исправить, но когда у меня есть время, я вернусь и переписал свой код, потому что это просто неправильно. – UmYeah

+0

Ха-ха, так здорово. Я занижен за единственный ответ, который приносит что-то до сих пор. Я люблю тебя, приятели. @ Jim: Я знаю, что я не ответил на вопрос желаемым образом. Если кто-то придумает лучшее исправление, я буду рад поддержать его и использовать его в своем собственном коде. До сих пор дезинфекция PCDATA всегда была для меня лучшим способом, который работает во всех случаях. @UmYeah: если у вас есть только символы ASCII, вы кодируете текст UTF-8. Вы просто изменили способ передачи расширенных символов. Вы предоставляете клиенту ответственность за их форматирование. – glmxndr

1

Самый простой обходной путь, вероятно, будет меняться ваш код следующим образом:

XMLDocument doc = new XMLDocument(1.0,false,Charset.defaultCharset().toString()); 

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

Я согласен с другими плакатами, что это, пожалуй, наименее из ваших забот. Рассматривая source repository для ECS, он, похоже, не обновлялся в течение четырех лет (репозиторий ECS2 аналогичным образом).

И некоторые саморекламы: если вы хотите создавать XML-документы с использованием простого интерфейса, в библиотеке Practical XML есть строитель. Он использует стандартный механизм сериализации JDK для вывода.

+1

'Charset.defaultCharset()' возвращает стандартную кодировку по умолчанию для платформы, которая может быть не такой, как кодировка XML-файла, и/или вообще не быть деривацией Unicode, например 'CP-1252' (ouch) или 'ISO-8859-x'. Вы не хотите этого. Прежде чем вы должны знать фактическую кодировку XML-файла. – BalusC

+0

Если вы внимательно прочитали вопрос, вы увидите, что OP фактически * производит * и XML-файл, не потребляя его. Если бы вы прочли мой ответ немного более внимательно, вы бы увидели, что мое обоснование использования 'defaultEncoding()' в прологе было то, что оказалось, что его использует сторонняя библиотека (Jakarta ECS). – kdgregory

1

Любой шанс, который вы можете написать в Writer, а не в OutputStream ... таким образом, вы можете указать кодировку.

Смежные вопросы