Bagaimana Anda menyematkan data biner dalam XML?

107

Saya memiliki dua aplikasi yang ditulis dalam Java yang berkomunikasi satu sama lain menggunakan pesan XML melalui jaringan. Saya menggunakan parser SAX di ujung penerima untuk mendapatkan kembali data dari pesan. Salah satu persyaratannya adalah menyematkan data biner dalam pesan XML, tetapi SAX tidak menyukai ini. Apakah ada yang tahu bagaimana melakukan ini?

PEMBARUAN: Saya mendapatkan ini berfungsi dengan kelas Base64 dari pustaka codec apache commons , jika ada orang lain yang mencoba sesuatu yang serupa.

Bill the Lizard
sumber

Jawaban:

216

Anda dapat menyandikan data biner menggunakan base64 dan memasukkannya ke dalam elemen Base64; artikel di bawah ini adalah artikel yang cukup bagus tentang masalah ini.

Menangani Data Biner dalam Dokumen XML

Greg Hurlman
sumber
209

XML sangat serbaguna ...

<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 itu seperti kekerasan - Jika XML tidak menyelesaikan masalah Anda, berarti Anda tidak cukup menggunakannya.

EDIT:

BTW: Base64 + CDATA mungkin adalah solusi terbaik

(EDIT2:
Siapapun yang meng-upmod saya, tolong juga upmod jawaban yang sebenarnya. Kami tidak ingin ada orang malang yang datang ke sini dan benar-benar menerapkan metode saya karena itu adalah peringkat tertinggi di SO, kan?)

Mo.
sumber
9
Ini tidak lain adalah penggunaan XML yang benar-benar memalukan jika Anda serius. Dan jika tidak, bagaimana pemula yang tidak menulis-tingkat-tinggi-berpikir-tingkat-rendah tahu?
TheFlash
1
Saya pikir itu lucu. Tapi ya, sekali lagi, menggunakan tipe data base64 sebenarnya adalah cara yang tepat. CData terlalu umum.
Omniwombat
4
Saya tidak berpikir itu cukup deskriptif - mungkin seseorang harus menggunakan 'BINARYDIGIT' daripada kontraksi 'BIT'? ;-)
Lee Atkinson
Wow. Ini akan membuat file jarak kilobyte rata-rata 230 kali lebih besar :)
Nyerguds
36
Oh, ya ampun. Ini lelucon. Apa yang saya lakukan?!: Thedailywtf.com/Articles/The-HumanReadable-Encryption-Key.aspx
Mo.
26

Base64 memang jawaban yang benar tetapi CDATA tidak, yang pada dasarnya mengatakan: "ini bisa jadi apa saja", namun itu tidak boleh sembarang, itu harus berupa data biner yang dikodekan Base64. Skema XML mendefinisikan biner Base 64 sebagai tipe data primitif yang dapat Anda gunakan di xsd Anda.

Boris Terzic
sumber
2
Poin tambahan untuk menyebutkan xs:base64Binarytipe data, yang merupakan tipe yang tepat untuk digunakan.
Christopher Schultz
14

Saya mengalami masalah ini minggu lalu. Saya harus membuat serial file PDF dan mengirimkannya, di dalam file XML, ke server.

Jika Anda menggunakan .NET, Anda dapat mengonversi file biner secara langsung ke string base64 dan menyimpannya di dalam elemen XML.

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

Atau, ada metode yang dibangun langsung ke dalam objek XmlWriter. Dalam kasus khusus saya, saya harus menyertakan namespace tipe data Microsoft:

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

String abc terlihat seperti ini:

<?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>
Baxter Tidwell
sumber
jawaban terbaik karena saya dapat menyalin / menempel Convert.ToBase64String darinya
Eldritch Conundrum
5

Coba encoding / decoding Base64 data biner Anda. Lihat juga bagian CDATA

basszero
sumber
4

Mungkin menyandikannya ke dalam set yang diketahui - sesuatu seperti base 64 adalah pilihan yang populer.

mercutio
sumber
4

Semua pengkodean biner-ke-teks akan berhasil. Saya menggunakan sesuatu seperti itu

<data encoding="yEnc>
<![CDATA[ encoded binary data ]]>
</data>
Jarek Przygódzki
sumber
4

Overhead Base64 adalah 33%.

BaseXML untuk overhead XML1.0 hanya 20% . Tapi ini bukan standar dan hanya memiliki implementasi C. Lihat jika Anda khawatir dengan ukuran data. Perhatikan bahwa bagaimanapun browser cenderung menerapkan kompresi sehingga kurang dibutuhkan.

Saya mengembangkannya setelah diskusi di utas ini: Mengkodekan data biner dalam XML: alternatif untuk base64 .

KrisWebDev
sumber
4

Meskipun sebagian besar jawaban lainnya baik-baik saja, Anda dapat mencoba metode pengkodean lain yang lebih hemat ruang seperti yEnc. ( yEnc wikipedia link ) Dengan yEnc juga dapatkan kemampuan checksum langsung "di luar kotak". Baca dan tautkan di bawah. Tentu saja, karena XML tidak memiliki tipe yEnc asli, skema XML Anda harus diperbarui untuk mendeskripsikan node yang dikodekan dengan tepat.

Mengapa : Karena strategi pengkodean base64 / 63, uuencode et al. pengkodean meningkatkan jumlah data (overhead) yang perlu Anda simpan dan transfer sekitar 40% (vs. 1-2% yEnc). Bergantung pada apa yang Anda encoding, overhead 40% bisa / menjadi masalah.


yEnc - Abstrak Wikipedia: https://en.wikipedia.org/wiki/YEnc yEnc adalah skema pengkodean biner-ke-teks untuk mentransfer file biner dalam pesan di Usenet atau melalui email. ... Keuntungan tambahan yEnc dibandingkan metode pengkodean sebelumnya, seperti uuencode dan Base64, adalah penyertaan checksum CRC untuk memverifikasi bahwa file yang didekode telah dikirim secara utuh. </s> </s> </s> </s> </s> </s> </s> </s> </s> </s> </s> </s> </s> </s> </s> </s> </s> </s> </s> </s> </s> </s> </s> </s> </s> </s> orang </s>

Jamie
sumber
2
@ Jamine jadi apakah Anda punya alternatif lain?
Berburu
Jamie, ini mungkin jawaban yang layak mengingat sedikit lebih banyak pekerjaan. Saya menghapus -1 saya dan akan memberi +1 jika Anda berusaha ... tandai saya jika Anda menindaklanjuti.
Paul Sasik
Jamie, t / m. Saya memperbarui jawaban Anda, dan memberi +1, semoga dengan info yang awalnya ingin Anda sampaikan. Mengintip dan mungkin membuat pembaruan sesuai keinginan Anda. (Saya belum aktif di SO selama beberapa waktu. Sangat menyenangkan untuk meneliti dan mengedit jawaban. Saya memberi +1 karena selama ini saya belajar beberapa hal baru dan itu semua tentang ...? Bersulang.)
Paul Sasik
escapeless dapat menjadi alternatif untuk yEnc ketika overhead yang dapat diprediksi / diperbaiki sangat penting.
Ivan Kosarev
2

Anda juga dapat meng-Uuencode data biner asli Anda. Format ini sedikit lebih tua tetapi melakukan hal yang sama seperti pengkodean base63.

Andrei Savu
sumber
* pengkodean base63
luckydonald
0

Jika Anda memiliki kendali atas format XML, Anda harus membalikkan masalahnya. Daripada melampirkan XML biner, Anda harus memikirkan tentang cara melampirkan dokumen yang memiliki banyak bagian, salah satunya berisi XML.

Solusi tradisional untuk ini adalah arsip (mis. Tar). Tetapi jika Anda ingin menyimpan dokumen terlampir Anda dalam format berbasis teks atau jika Anda tidak memiliki akses ke perpustakaan pengarsipan file, ada juga skema standar yang banyak digunakan dalam email dan HTTP yang multipart / * MIME dengan Content-Transfer-Encoding: biner .

Misalnya jika server Anda berkomunikasi melalui HTTP dan Anda ingin mengirim dokumen multibagian, yang primer adalah dokumen XML yang merujuk ke data biner, komunikasi HTTP mungkin terlihat seperti ini:

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--

Seperti dalam contoh di atas, XML merujuk ke data biner dalam multi bagian yang melingkupi dengan menggunakan cidskema URI yang merupakan pengenal untuk header Content-Id. Overhead skema ini hanya akan menjadi header MIME. Skema serupa juga dapat digunakan untuk respons HTTP. Tentu saja dalam protokol HTTP, Anda juga memiliki opsi untuk mengirim dokumen multi bagian ke dalam permintaan / tanggapan terpisah.

Jika Anda ingin menghindari penggabungan data Anda dalam multi bagian adalah dengan menggunakan URI data:

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

Tapi ini memiliki overhead base64.

Lie Ryan
sumber