2017-01-13 1 views
0

Wir haben einen mobilen Client, der mit dem Server unter Verwendung von XML kommuniziert. Ich bin auf ein Problem gestoßen, als wir einige der neueren UTF-8-Smileys senden mussten, die auf neuen Handys sehr leicht zugänglich gemacht wurden. Zum Beispiel: .XML-Unterstützung für neue UTF-8 wie Smileys

Jetzt hat meine Android-Anwendung kein Problem mit der Codierung und dem Senden dieser, aber auf der Serverseite neigen Dinge dazu, ein bisschen mehr explodieren.

Wenn wir versuchen, eine Nachricht zu senden einen des smileys unter Verwendung der oben wir einen riesigen Stack-Trace, mit dem entsprechenden Teil erhalten:

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) 

Und wenn wir versuchen, es zu analysieren:

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) 

In diesem Fall wird die XML ist:

<?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="&#55357;&#56846;" user_id="CN=???????? ????????????,OU=TestUsers,OU=ZyUsers,DC=Zylinc,DC=com"/> 
</set> 
</action> 

Nun scheint dies gut zu funktionieren, wenn JSON ausgibt, aber die Bewegung der Kunden JSON zu verwenden, können wir nicht über Nacht tun. Ich schätze, es bricht, weil die verwendeten Zeichen im Vergleich zur Java-Version zu neu sind, aber es wäre schön, sicherzustellen, dass neuere Smileys das Messaging nie unterbrechen werden.

Der Code die XML für die Analyse ist ziemlich geradlinig:

SAXParser parser = SAXParserFactory.newInstance().newSAXParser(); 
XMLReader xmlReader = parser.getXMLReader(); 
xmlReader.setContentHandler(handler); 
StringReader reader = new StringReader(xml); 
xmlReader.parse(new InputSource(reader)); 

Edit:

das Erstellen von XML wie dies geschehen ist:

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(); 

Wo Hinzufügen der Text ist einfach:

xml.setAttribute(SUBJECT, obj.getSubject()); 

Muss ich eine Codierung oder eine andere angeben?

+0

Sie können keine andere Wahl haben, als base64 die Elemente zu codieren, die Emojis enthalten. Auch ASCII-Steuercodes illegal als XML-Text, wie  Stavr00

Antwort

3

Sie codieren diese falsch.

Wenn Sie die XML-Zeichenreferenznotation &#NNNNN; verwenden, muss N ein Unicode-Codepoint sein, kein Unicode-Codepunkt, der in ein Ersatzpaar aufgeteilt ist. Zum Beispiel &#x1f60e;. In Ihrem Beispiel haben Sie &#55357;&#56846;, was nicht legal ist, weil 55357 und 56846 keine Codepunkte sind, sondern die beiden Hälften eines Ersatzpaares.

In dem Fall, in dem Sie die Zeichen direkt darstellen, bin ich nicht sicher, was genau Sie tun, aber die Fehlermeldung "Invalid UTF-16 Surrogat erkannt: D83D D83D" macht es sehr deutlich, dass Sie sind es falsch machen.

Der Titel Ihrer Frage ("UTF-8 like smileys") deutet darauf hin, dass Sie zwischen Unicode und UTF-8 verwirrt sind. Unicode mappt Smileys zu ganzzahligen Codepunkten, z. der erste ist hex 1f60e oder dezimal 128526. UTF-8 ist ein möglicher Weg, Unicode als einen Strom von Bytes oder Oktetten zu codieren, und er kann jeden Unicode-Codepunkt als eine Folge von ein bis vier Bytes codieren.

UTF-16 ist eine weitere Kodierung, die die meisten Unicode-Codepunkte als 16 Bit darstellt, aber die oberhalb von xffff mit einem Paar von 16-Bit-Werten, die als Ersatzpaar bezeichnet werden. Ersatzpaare werden in UTF-8 nicht verwendet. Es ist ziemlich falsch zu versuchen, einen Unicode-Codepunkt in UTF-16 als Ersatzpaar zu codieren und dann jede Hälfte dieses Ersatzpaars unabhängig in UTF-8 zu codieren. Aber ich vermute irgendwie, dass du das machst.

+0

ich hinzugefügt habe, wie ich die XML im Boden schaffen, ich habe nichts klar sehen. –

+0

Sie erstellen das XML als String in einem StringWriter, einer Folge von Java-Zeichen (effektiv UTF-16). Aber das XML, das Sie uns gezeigt haben, behauptet, dass es in UTF-8 ist. Irgendwann müssen die UTF-16-Zeichen in UTF-8-Oktette umgewandelt worden sein, und dies ist wahrscheinlich das Problem. –