【发布时间】:2017-01-13 13:53:57
【问题描述】:
我们有一个使用 XML 与服务器通信的移动客户端。当我们需要发送一些更新的 UTF-8 笑脸时,我遇到了一个问题,这些笑脸在新手机上很容易访问。例如:????????????????????????.
现在,我的 Android 应用程序在编码和发送它方面没有问题,但在服务器端,事情往往更容易爆炸。
如果我们尝试使用上面的任何表情发送消息,我们会得到一个巨大的堆栈跟踪,以及相关部分:
javax.xml.transform.TransformerException: org.xml.sax.SAXException: Invalid UTF-16 surrogate detected: d83d d83d ?
java.io.IOException: Invalid UTF-16 surrogate detected: d83d d83d ?
at com.sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl.transform(Unknown Source)
at com.sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl.transform(Unknown Source)
如果我们尝试解析它:
2017-01-13 14:00:22,717 - com.zylinc.core.gatekeeper.stripes.DoBean - WARN - Could not handle request
org.xml.sax.SAXParseException; lineNumber: 3; columnNumber: 93; Character reference "&#
at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(Unknown Source)
at com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl$JAXPSAXParser.parse(Unknown Source)
at com.zylinc.core.gatekeeper.stripes.DoBean.parseRequest(DoBean.java:127)
at com.zylinc.core.gatekeeper.stripes.DoBean.execute(DoBean.java:56)
at com.zylinc.core.gatekeeper.Dispatcher.onRequest(Dispatcher.java:107)
at com.zylinc.core.gatekeeper.io.UntrustedSocketListener.handleRequest(UntrustedSocketListener.java:16)
at com.zylinc.core.gatekeeper.io.SocketListener$MessageHandler.run(SocketListener.java:228)
at java.lang.Thread.run(Unknown Source)
在这种情况下,XML 是:
<?xml version="1.0" encoding="UTF-8"?><action>
<set>
<absence requestid="0" from="2017 01 13 13 00 11" to="2017 01 13 22 59 11" subject="��" user_id="CN=???????? ????????????,OU=TestUsers,OU=ZyUsers,DC=Zylinc,DC=com"/>
</set>
</action>
现在,这在输出 JSON 时似乎工作得很好,但是让客户端使用 JSON 并不是我们可以在一夜之间完成的事情。我猜它会中断,因为与 java 版本相比,使用的字符太新了,但最好确保新的笑脸永远不会中断消息传递。
解析 XML 的代码非常简单:
SAXParser parser = SAXParserFactory.newInstance().newSAXParser();
XMLReader xmlReader = parser.getXMLReader();
xmlReader.setContentHandler(handler);
StringReader reader = new StringReader(xml);
xmlReader.parse(new InputSource(reader));
编辑:
创建 XML 是这样完成的:
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
mDoc = builder.newDocument();
mRoot = mDoc.createElement("action");
mDoc.appendChild(mRoot);
TransformerFactory transFactory = TransformerFactory.newInstance();
Transformer trans = transFactory.newTransformer();
trans.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "no");
trans.setOutputProperty(OutputKeys.INDENT, "yes");
trans.setOutputProperty(OutputKeys.VERSION, "1.1");
StringWriter sw = new StringWriter();
StreamResult result = new StreamResult(sw);
DOMSource source = new DOMSource(mDoc);
trans.transform(source, result);
return sw.toString();
添加文本的地方很简单:
xml.setAttribute(SUBJECT, obj.getSubject());
我是否必须指定一些编码或其他?
【问题讨论】:
-
您可能别无选择,只能对包含表情符号的元素进行 base64 编码。甚至 ASCII 控制码作为 XML 文本也是非法的,例如