2008-08-21 12 views
95

Ich habe zwei in Java geschriebene Anwendungen, die miteinander über XML-Nachrichten über das Netzwerk kommunizieren. Ich benutze einen SAX-Parser am empfangenden Ende, um die Daten aus den Nachrichten herauszuholen. Eine der Anforderungen besteht darin, Binärdaten in eine XML-Nachricht einzubetten, aber SAX mag dies nicht. Weiß jemand, wie man das macht?Wie betten Sie Binärdaten in XML ein?

UPDATE: Ich habe dies mit der Base64 Klasse von apache commons codec library arbeiten, falls jemand anderes etwas Ähnliches versucht.

+3

Genie! Genau wonach ich gesucht habe! –

Antwort

192

Sie könnten die Binärdaten mit base64 kodieren und in ein Base64-Element einfügen; Der folgende Artikel ist ziemlich gut zu diesem Thema.

Handling Binary Data in XML Documents

+0

Vorsicht, einige Firewalls (https-Verbindungen) scheinen manchmal zu blockieren, wenn das Zeichen "=" vorhanden ist. (Viele Codierungen von Strings führen zu etwas wie dem "kdiLKjdfdilfse =") – tObi

4

Vielleicht codieren sie in einem bekannten Set - so etwas wie Base 64 ist eine beliebte Wahl.

5

Probieren Sie Base64 Codierung/Decodierung Ihrer Binärdaten aus. Schauen Sie auch in die CDATA-Abschnitte

190

XML ist so vielseitig ...

<DATA> 
    <BINARY> 
    <BIT index="0">0</BIT> 
    <BIT index="1">0</BIT> 
    <BIT index="2">1</BIT> 
    ... 
    <BIT index="n">1</BIT> 
    </BINARY> 
</DATA> 

XML ist wie Gewalt - Wenn es Ihr Problem nicht lösen, bist du nicht genug davon verwenden.

EDIT:

BTW: Base64 + CDATA ist wahrscheinlich die beste Lösung

(EDIT2.
Wer upmods mir bitte upmod auch die richtige Antwort Wir wollen keine arme Seele kommen hier und eigentlich meine Methode implementieren, weil es die am höchsten eingestuften auf SO war, rechts)

+0

Ich wiederholte dieses Zitat einfach meinem Freund, und nachdem er gelacht hatte, sagte er "und es ist schmerzhaft, wenn es auf dich gerichtet ist" :) – kaybenleroll

+5

Das ist nichts weniger als eine absolut schändliche Verwendung von XML, wenn Sie es ernst meinen. Und wenn Sie es nicht sind, wie würden Anfänger, die nicht schreiben - High-Level-Think-Low-Level - wissen? –

+1

Jeremy ...für einen jungen 23-jährigen Jungen bist du furchtbar ernst/wörtlich ... du hast eindeutig nicht lange genug in der Industrie gearbeitet, um zu sehen, warum das eine amüsante Antwort mit einer warnenden Geschichte für die Mutigen zwischen den Zeilen ist. – Kev

22

Base64 ist in der Tat die richtige Antwort, aber CDATA ist nicht, dass im Grunde sagt: „das könnte alles sein“, jedoch muss es nicht sei einfach alles, es muss sein Base64-codierte Binärdaten. XML-Schema definiert Base 64 binary as a primitive datatype, die Sie in Ihrem xsd verwenden können.

+1

Zusätzlicher Punkt für die Erwähnung des Datentyps 'xs: base64Binary', der der richtige zu verwendende Datentyp ist. –

2

Sie können auch Uuencode Sie ursprünglichen Binärdaten. Dieses Format ist etwas älter, aber es macht dasselbe wie die Base63-Codierung.

3

Alle binary-to-text encoding werden den Trick tun. Ich benutze so etwas

<data encoding="yEnc> 
<![CDATA[ encoded binary data ]]> 
</data> 
9

Ich hatte dieses Problem nur letzte Woche. Ich musste eine PDF-Datei serialisieren und sie in einer XML-Datei an einen Server senden.

Wenn Sie .NET verwenden, können Sie eine Binärdatei direkt in eine Base64-Zeichenfolge konvertieren und in ein XML-Element einfügen.

string base64 = Convert.ToBase64String(File.ReadAllBytes(fileName)); 

Oder gibt es ein Verfahren nach rechts in die XmlWriter-Objekt gebaut.In meinem Fall hatte ich Microsofts Datentyp-Namespace enthalten:

StringBuilder sb = new StringBuilder(); 
System.Xml.XmlWriter xw = XmlWriter.Create(sb); 
xw.WriteStartElement("doc"); 
xw.WriteStartElement("serialized_binary"); 
xw.WriteAttributeString("types", "dt", "urn:schemas-microsoft-com:datatypes", "bin.base64"); 
byte[] b = File.ReadAllBytes(fileName); 
xw.WriteBase64(b, 0, b.Length); 
xw.WriteEndElement(); 
xw.WriteEndElement(); 
string abc = sb.ToString(); 

Der String abc sieht etwas, das wie folgt aussieht:

<?xml version="1.0" encoding="utf-16"?> 
<doc> 
    <serialized_binary types:dt="bin.base64" xmlns:types="urn:schemas-microsoft-com:datatypes"> 
     JVBERi0xLjMKJaqrrK0KNCAwIG9iago8PCAvVHlwZSAvSW5mbw...(plus lots more) 
    </serialized_binary> 
</doc> 
0

Hier ist ein gutes Beispiel dafür, wie XEP-0239

fortzufahren PS: Vergiss nicht Mo's answer zu lesen.

PS2: Lesen Sie den Abschnitt HINWEIS auf dem XEP.

2

Verwenden Sie keine base64-Codierung, da die Datenmenge, die gespeichert werden muss, um mindestens 40% erhöht wird. Verwenden Sie stattdessen andere Codierungsmethoden wie yEnc.

+1

@Jamine also hast du noch eine alternative? – Hunt

3

Base64 Overhead ist 33%.

BaseXML für XML1.0 Overhead ist nur 20%. Aber es ist kein Standard und nur eine C-Implementierung. Überprüfen Sie es, wenn Sie sich mit der Datengröße befassen. Beachten Sie jedoch, dass Browser dazu neigen, die Komprimierung so zu implementieren, dass sie weniger benötigt wird.

Ich entwickelte es nach der Diskussion in diesem Thread: Encoding binary data within XML : alternatives to base64.

0

Wenn Sie Kontrolle über das XML-Format haben, sollten Sie das Problem umkehren. Anstatt das binäre XML anzuhängen, sollten Sie darüber nachdenken, wie Sie ein Dokument einschließen, das aus mehreren Teilen besteht, von denen einer XML enthält.

Die traditionelle Lösung ist ein Archiv (z. B. Teer). Wenn Sie jedoch Ihr umschließendes Dokument in einem textbasierten Format aufbewahren möchten oder wenn Sie keinen Zugriff auf eine Dateiarchivierungsbibliothek haben, gibt es auch ein standardisiertes Schema, das in E-Mails und HTTP multipart/* MIME mit Content-Transfer-Encoding: binary stark verwendet wird.

Zum Beispiel, wenn Ihr Server über HTTP zu kommunizieren und Sie möchten ein mehrteiliger Dokument senden, das primäre ist ein XML-Dokument, das in eine binäre Daten bezieht, kann die HTTP-Kommunikation wie folgt aussehen:

POST/HTTP/1.1 
Content-Type: multipart/related; boundary="qd43hdi34udh34id344" 
... other headers elided ... 

--qd43hdi34udh34id344 
Content-Type: application/xml 

<myxml> 
    <data href="cid:data.bin"/> 
</myxml> 
--qd43hdi34udh34id344 
Content-Id: <data.bin> 
Content-type: application/octet-stream 
Content-Transfer-Encoding: binary 

... binary data ... 
--qd43hdi34udh34id344-- 

Wie im obigen Beispiel beziehen sich die XML-Daten auf die Binärdaten im einschließenden Multipart, indem ein cid URI-Schema verwendet wird, das eine Kennung für den Content-Id-Header darstellt. Der Overhead dieses Schemas wäre nur der MIME-Header. Ein ähnliches Schema kann auch für die HTTP-Antwort verwendet werden. Natürlich haben Sie im HTTP-Protokoll auch die Möglichkeit, ein mehrteiliges Dokument in separate Anfrage/Antwort zu senden.

Wenn Sie Ihre Daten in einem mehrteiligen vermeiden wollen Verpackung ist Daten URI zu verwenden:

<myxml> 
    <data href="data:application/something;charset=utf-8;base64,dGVzdGRhdGE="/> 
</myxml> 

Aber die base64-Overhead hat.