Как мога да накарам XSLT да връща UTF-8 в Java

Опитвам се да накарам моя XSL скрипт да работи с UTF-8 кодиране. Знаци като åäö и гръцки знаци просто се появяват като боклук. Единственият начин да го накарам да работи е, ако запиша резултата във файл. Ако го запиша в изходен поток, той връща само боклук (System.out работи, но това може да се дължи на това, че е пренасочен към файл).

Резултатът трябва да бъде върнат от сървлет и имайте предвид, че това не е проблем с конфигурацията на сървлета. Мога да върна твърдо кодиран низ с гръцки символи от сервлета и той работи добре, така че това е проблем с трансформацията.

Ето моят текущ (опростен) код.

protected void doGet(final HttpServletRequest request, final HttpServletResponse response) throws ServletException,
IOException {
    try {
        response.setCharacterEncoding("UTF-8");
        response.setContentType("text/html; charset=UTF-8");

        final TransformerFactory factory = this.getFactory();

        final File inFile = new File("infile.xml");
        final File xslFile = new File("template.xsl");
        final File outFile = new File("outfile.html");

        final Templates templates = factory.newTemplates(new StreamSource(xslFile));
        final Transformer transformer = templates.newTransformer();
        transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");

        final InputStream in = new FileInputStream(inFile);
        final StreamSource source = new StreamSource(in);

        final StreamResult result1 = new StreamResult(outFile);
        final StreamResult result2 = new StreamResult(System.out);
        final ByteArrayOutputStream out = new ByteArrayOutputStream();
        final StreamResult result3 = new StreamResult(out);

        //transformer.transform(source, result1);
        //transformer.transform(source, result2);
        transformer.transform(source, result3);

        final Writer writer = response.getWriter();
        writer.write(new String(out.toByteArray()));
        writer.close();
        in.close();

    } catch (final TransformerConfigurationException e) {
        e.printStackTrace();
    } catch (final TransformerException e) {
        e.printStackTrace();
    }
}

Освен това моят XSL скрипт съдържа следното

<xsl:output method="html" omit-xml-declaration="yes" encoding="UTF-8" indent="yes" />

Какъв е правилният начин това да заработи? Използвам Saxon за трансформацията, ако това може да е от полза.


person Johan    schedule 20.11.2012    source източник


Отговори (1)


Това почти сигурно е проблемът:

writer.write(new String(out.toByteArray()));

Внимателно сте кодирали текста си като UTF-8 и след това го конвертирате в низ като използвате кодирането по подразбиране на платформата. Почти никога не трябва да използвате String конструкторите и методите, които използват стандартното кодиране на платформата. Дори ако искате да използвате това кодиране, направете го изрично.

Ако все пак ще пишете на Writer, защо започвате да пишете на ByteArrayOutputStream? Защо не отидете направо на Writer?

Би било по-добре обаче да пишете направо в изходния поток на отговора (response.getOutputStream()) и също така да зададете типа съдържание на отговора, за да посочите, че е UTF-8.

Имайте предвид, че ако наистина искате да получите резултата като String предварително, използвайте StringWriter. Няма смисъл да пишете в ByteArrayOutputStream и след това да конвертирате в низ.

person Jon Skeet    schedule 20.11.2012
comment
Благодаря, насочихте ме в правилната посока. Току-що открих, че ByteArrayOutputStream има метода out.toString("UTF-8"), така че работи след това. Не мога да използвам потока от отговори веднага, тъй като имам и други неща, свързани с резултата, но мисля, че мога да започна това сега. Благодаря! - person Johan; 20.11.2012
comment
Щях да отговоря на този въпрос и тогава виждам @jonSkeet 0_0 - person Rakesh Juyal; 20.11.2012
comment
Ако искате изходът като низ от знаци да бъде обработен от Java приложение, просто накарайте трансформатора да извежда знаци, като предоставите Writer. Искането да запише байтове в byteOutputStream и след това да декодира байтовете като знаци, просто създава сложност и потенциал за грешка. - person Michael Kay; 20.11.2012