Java — Отправить строку UTF-8 через веб-службу и XML, которая может содержать недопустимые символы

#c# #java #.net #web-services #utf-8

#c# #java #.net #веб-сервисы #utf-8

Вопрос:

У меня есть веб-служба, написанная на Java. Я хочу отправить несколько строк в виде XML-файла. Но эти строки могут содержать некоторые символы, которые распознаются как недопустимые в XML. В настоящее время я заменяю их все на ?, создаю XML и отправляю его по сети (в приложение Silverlight). Но иногда все, что я получаю, это вопросительные знаки! Итак, я хочу каким-то образом закодировать / декодировать эти строки до и после их отправки, чтобы получить точные строки. Эти строки в кодировке UTF-8. Я использую что-то подобное для создания XML:

 try{
    DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
    DocumentBuilder docBuilder = docFactory.newDocumentBuilder();

    //root elements
    Document doc = docBuilder.newDocument();
    Element rootElement = doc.createElement("SearchResults");
    rootElement.setAttribute("count", Integer.toString(total));
    doc.appendChild(rootElement);

    for(int i = 0; i < results.size(); i  )
    {
        Result res = results.get(i);
        //title
        Element title = doc.createElement("Title");
        title.appendChild(doc.createTextNode(res.title));
        searchRes.appendChild(title);

        //...
    }
    //write the content into xml file
    TransformerFactory transformerFactory = TransformerFactory.newInstance();
    Transformer transformer = transformerFactory.newTransformer();
    DOMSource source = new DOMSource(doc);
    StringWriter sw = new StringWriter();
    StreamResult result =  new StreamResult(sw);
    transformer.transform(source, result);
    String ret = sw.toString();
    return ret;
}
catch(ParserConfigurationException pce){
    pce.printStackTrace();
}catch(TransformerException tfe){
    tfe.printStackTrace();
}
return null;
  

Спасибо.

PS: Некоторые люди сказали, что они не поняли мой вопрос, так что, возможно, я сказал это неправильно, поэтому я пытаюсь прояснить это на примере. Предположим, у меня есть массив элементов.
Каждый элемент содержит 3 строки.
Эти строки являются строками UTF-8 (из многих языков).
Я хочу отправить эти строки клиенту через веб-службу на Java.
Клиентская часть — Silverlight. В приложении Silverlight
я получаю XML, анализирую его и использую LinQ для извлечения из него данных, и я использую эти данные в своем приложении Silverlight.
Когда я пытаюсь экранировать символы, каким-то образом анализатор в Silverlight выдает исключение, в котором говорится, что в исходной строке (XML string) присутствует недопустимый символ. После отладки я обнаружил, что на самом деле существует недопустимый символ, но я не знаю, как создать гарантированно разрешенную XML-строку.

Редактировать: Спасибо всем за вашу поддержку. Я ДЕЙСТВИТЕЛЬНО ценю это.
Я решил свою проблему.
Оказывается, где-то в моем коде я создавал недопустимый символ и добавлял его к своей результирующей строке.
Вопрос все еще остается (как я могу создать легальный XML-файл, даже если я предоставляю ему некоторые недопустимые символы — обратите внимание, что я решил проблему, удалив недопустимый символ перед созданием XML, поэтому я все еще задаюсь вопросом, что, если бы я хотел каким-то образом отправить его?) но поскольку моя проблема решена и здесь есть множество ответов, я думаю, у будущих читателей есть преимущество, чтобы начать путешествие к решению этой проблемы.
У меня не было времени, но я уверен, что это поможет.
Существует множество ответов и подсказок, поэтому я не могу выбрать один из них в качестве своего конкретного ответа.
Но я должен выбрать один из них.
Я искренне благодарю всех за ответы.

Комментарии:

1. В первую очередь просто правильно закодируйте символы. Хорошим подходом является использование amp;#-конструкции.

2. @Thorbjorn (извините, не клавиатура EU) — это экранирование, а не кодирование, и это не поможет с символами типа 0x01, которые не разрешены в XML 1.0.

3. @Alireza — Я заметил, что вы преобразуете выходные данные в строку, а затем, предположительно, записываете ее в поток. Лучший подход (поскольку он позволяет избежать возможных ошибок кодирования) — передать этот поток непосредственно в transformer.

4. @Anon : В моем веб-методе я возвращаю эту строку (ret в приведенном выше коде) в качестве результата. Я не понял, что именно вы сказали, извините: D

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

Ответ №1:

Если вы отправляете безсимвольные данные (например, двоичные данные) в вашем XML, вы можете закодировать их с помощью Base64. Но я не уверен, что правильно понял ваш вопрос.

Возможно, вы просто забыли закодировать свой XML в UTF-8, используя transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8")

Комментарии:

1. 1. Никакая другая форма экранирования XML не позволит вам иметь символы, подобные ‘ 0’, присутствующие в XML.

2. Спасибо. Это не двоичные данные (это несколько строк, вырезанных с веб-страниц), и я не знаю, как кодировать в Base64. Не могли бы вы предоставить мне небольшое руководство или пример?

3. Еще одна вещь, использование transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8"); не помогло.

4. Алиреза, взгляни на [Кодек Apache Commons] ( commons.apache.org/codec ).

5. Вы можете использовать метод кодирования BCodec . Или что-то вроде этого .

Ответ №2:

Не уверен, что понимаю ваш вопрос, но, возможно, вам следует поместить данные в CDATA тег, чтобы они не анализировались анализатором XML. Вот документация из MSDN.

Комментарии:

1. CDATA не допускает «недопустимые» символы. Вот документация из W3C: w3.org/TR/xml/#dt-cdsection

Ответ №3:

Оберните содержимое с помощью <![CDATA[ и ]]> .

Дополнительная информация здесь:http://www.w3schools.com/xml/xml_cdata.asp

Комментарии:

1. CDATA — хороший подход, когда вы не хотите, чтобы XML анализировался (это исходная функция тега). Но поскольку он создает XML с нуля для использования, более рекомендуемым (и таким же простым) способом было бы избежать строк.

2. CDATA не позволит вам использовать «недопустимые» символы (такие как 0x01, SOH). Это существует для того, чтобы вы могли использовать символы, которые обычно требуют экранирования, например < . Но даже тогда это не особенно полезно.

Ответ №4:

По опыту я бы рекомендовал экранировать / неэкранировать XML. Взгляните на StringEscapeUtils из Apache Commons Lang.

Комментарии:

1. Я пробовал это так: desc.appendChild(doc.createTextNode(StringEscapeUtils.escapeXml(res.description))); но в части silverlight, когда я использую это: XDocument xmlStories = XDocument.Parse(xmlContent); Я получаю исключение, в котором говорится, что в XML есть недопустимый символ!

2. Символы, подобные », недопустимы в XML. Нет способа избежать их (за исключением пользовательской кодировки — см. Ответ JB Nizet об использовании Base64).

Ответ №5:

Вам следует попробовать StringEscapeUtils от apache