使用XSLT转换XML并保留Unicode字符
我的XSLT转换已成功几个月,直到我遇到带有Unicode字符的XML文件(很可能是表情符号)。 我需要保留Unicode,但XSLT将其转换为HTML实体。 我认为将编码设置为UTF-8可以解决我的问题,但我仍然遇到问题。
任何帮助赞赏。 码:
private byte[] transform(InputStream stream) throws Exception{ System.setProperty("javax.xml.transform.TransformerFactory", "org.apache.xalan.processor.TransformerFactoryImpl"); Transformer xmlTransformer; xmlTransformer = (TransformerImpl) TransformerFactory.newInstance().newTransformer(new StreamSource(createXsltStylesheet())); xmlTransformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8"); XMLStreamReader reader = XMLInputFactory.newInstance().createXMLStreamReader(stream,"UTF-8"); Source staxSource = new StAXSource(reader, true); ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); Writer writer = new OutputStreamWriter(outputStream, "UTF-8"); xmlTransformer.transform(staxSource, new StreamResult(writer)); return outputStream.toByteArray(); }
如果我加
xmlTransformer.setOutputProperty(OutputKeys.METHOD, "text");
保留Unicode但不保留XML。
这条线是可疑的:
stream = IOUtils.toInputStream(outputStream.toString(),"UTF-8");
您正在使用平台的默认编码将ByteArrayOutputStream
转换为String,该编码可能不是UTF-8。 将其更改为
stream = IOUtils.toInputStream(outputStream.toString("UTF-8"),"UTF-8");
或者,为了获得更好的性能,只需将字节数组包装在ByteArrayInputStream
:
return new ByteArrayInputStream(outputStream.toByteArray());
尝试使用Apache Serializer将XML转换为String。
//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());
我刚刚遇到了同样的问题,经过长时间的研究,这就是我的结论。
即使输出模式是XML, Java XSLT处理器也会将多字节UTF-8字符转换为HTML实体…如果多字节字符出现在未包含在CDATA中的text()节点中。 如果字符包装在CDATA中(用于输出),则将保留多字节字符。
我的问题:
我有一个看起来像这样的xml文件,带有表情符号。
RANDOMID FOOONE FOOTWO Did some things. Had some Fun. 👍
我从一个看起来像这样的XSL样式表开始:
使用java Transformer执行此操作始终如一地生成 我的表情符号应该在哪里。 解析生成的Document的后续尝试失败,并显示以下exception消息:
org.xml.sax.SAXParseException; lineNumber: y; columnNumber: x; Character reference "" is an invalid XML character.
废话!
在命令行上使用xsltproc
进行测试是没用的,因为xsltproc
在涉及多字节字符时不是傻瓜。 我得到了我预期的输出。
一个办法
通过在xsl:output
标记中指定QName,让XSLT将事件包装在CDATA中, cdata-section-elements
属性将保留字节并与xsltproc 和java Transformer一起使用 。
这里的魔力是来自
标记的输出cdata-secion-elements
属性。 https://www.w3.org/TR/xslt#output
我将我的XSL模板更新为:
现在我的xsltproc
和java Transformer的输出都是这样的,并且使用java DocumentBuilders快乐地解析。
RANDOMID FOO FOOTOO