İkili verileri XML'e nasıl yerleştirirsiniz?


107

Ağ üzerinden XML mesajları kullanarak birbirleriyle iletişim kuran Java dilinde yazılmış iki uygulamam var. Verileri mesajlardan geri almak için alıcı uçta bir SAX ayrıştırıcısı kullanıyorum. Gereksinimlerden biri, ikili verileri bir XML mesajına gömmektir, ancak SAX bundan hoşlanmaz. Bunun nasıl yapılacağını bilen var mı?

GÜNCELLEME: Bunu , başka birinin benzer bir şey denemesi durumunda apache commons codec kitaplığından Base64 sınıfı ile çalıştırdım .

Yanıtlar:



209

XML çok yönlü ...

<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 şiddet gibidir - Sorununuzu çözmezse, yeterince kullanmıyorsunuz demektir.

DÜZENLE:

BTW: Base64 + CDATA muhtemelen en iyi çözümdür

(
DÜZENLEME2 : Kim beni modifiye ederse, lütfen gerçek cevabı da modifiye edin. Zavallı ruhun buraya gelmesini ve aslında benim yöntemimi uygulamasını istemiyoruz çünkü SO'da en yüksek sırada yer alıyordu, değil mi?)


9
Ciddiyseniz, bu tamamen utanç verici bir XML kullanımından başka bir şey değildir. Ve eğer değilseniz, yüksek seviye-düşük-seviye yazmayan yeni başlayanlar nasıl bilir?
TheFlash

1
Bence komik Ama evet, bir kez daha, gerçek base64 veri türünü kullanmak gitmenin yoludur. CData çok genel.
Omniwombat

4
Bunun yeterince açıklayıcı olduğunu düşünmüyorum - belki de 'BIT' kısaltması yerine 'BINARYDIGIT' kullanılmalı? ;-)
Lee Atkinson

Vay. Bu, ortalama kilobayt aralığı dosyasını yaklaşık 230 kat daha büyük hale getirecek :)
Nyerguds

36
Oh Allah aşkına. Bu bir şakaydı. ?!: Ben ne yaptım thedailywtf.com/Articles/The-HumanReadable-Encryption-Key.aspx
Mo


14

Bu sorunu daha geçen hafta yaşadım. Bir PDF dosyasını serileştirmem ve bir XML dosyası içinde bir sunucuya göndermem gerekiyordu.

.NET kullanıyorsanız, bir ikili dosyayı doğrudan bir base64 dizesine dönüştürebilir ve bir XML öğesinin içine yapıştırabilirsiniz.

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

Veya, XmlWriter nesnesine yerleşik bir yöntem vardır. Benim durumumda, Microsoft'un veri türü ad alanını dahil etmem gerekiyordu:

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

Abc dizisi şuna benzer bir şeye benziyor:

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

en iyi cevap, çünkü Convert.ToBase64String'i kopyalayıp yapıştırabiliyorum
Eldritch Conundrum


5

İkili verilerinizi Base64 kodlamayı / kod çözmeyi deneyin. Ayrıca CDATA bölümlerine bakın


4

Belki onları bilinen bir sete kodlayın - temel 64 gibi bir şey popüler bir seçimdir.



4

Base64 ek yükü% 33'tür.

XML1.0 ek yükü için BaseXML yalnızca% 20'dir . Ancak bu bir standart değil ve yalnızca bir C uygulaması var. Veri boyutuyla ilgileniyorsanız kontrol edin. Bununla birlikte, tarayıcıların daha az ihtiyaç duyulacak şekilde sıkıştırma uygulama eğiliminde olduğunu unutmayın.

Bu konudaki tartışmadan sonra geliştirdim: XML içinde ikili verileri kodlama : base64'e alternatifler .


4

Diğer cevaplar çoğunlukla iyi olsa da, yEnc gibi başka, daha az yer kaplayan bir kodlama yöntemini deneyebilirsiniz. ( yEnc wikipedia bağlantısı ) yEnc ile ayrıca "kutudan çıkar çıkmaz" sağlama toplamı yeteneği elde edin. Aşağıdaki okuyun ve bağlantıları. Elbette, XML'in yerel bir yEnc türü olmadığı için, XML şemanız kodlanmış düğümü düzgün bir şekilde tanımlayacak şekilde güncellenmelidir.

Nedeni : base64 / 63 kodlama stratejileri nedeniyle, uuencode et al. kodlamalar, depolamanız ve aktarmanız gereken veri miktarını (ek yük) yaklaşık% 40 oranında artırır (yEnc'in% 1-2'sine kıyasla). Neyi kodladığınıza bağlı olarak,% 40 ek yük bir sorun olabilir / olabilir.


yEnc - Wikipedia özeti: https://en.wikipedia.org/wiki/YEnc yEnc, ikili dosyaları Usenet'teki mesajlarda veya e-posta yoluyla aktarmak için ikili-metin kodlama şemasıdır. ... uuencode ve Base64 gibi önceki kodlama yöntemlerine göre yEnc'in ek bir avantajı, kodu çözülen dosyanın sağlam teslim edildiğini doğrulamak için bir CRC sağlama toplamının dahil edilmesidir.


2
@Jamine, başka bir alternatifiniz var mı?
Hunt

Jamie, biraz daha çalışılırsa bu iyi bir cevap olabilir. -1'imi kaldırdım ve biraz çaba gösterirseniz + 1'leyeceğim ... takip ederseniz beni işaretleyin.
Paul Sasik

Jamie, n / m. Cevabınızı güncelledim ve umarım ilk başta iletmek istediğiniz bilgilerle + 1'ledim. Bir göz atın ve belki de uygun gördüğünüz şekilde güncellemeler yapın. (Bir süredir SO'da aktif değildim. Bir cevabı araştırmak ve düzenlemek eğlenceliydi. + 1'ledim çünkü bu arada birkaç yeni şey öğrendim ve her şey bununla ilgili ... Şerefe.)
Paul Sasik

öngörülebilir / sabit ek yük kritik olduğunda, kaçışsız yEnc'e bir alternatif olabilir.
Ivan Kosarev


0

XML formatı üzerinde kontrolünüz varsa, sorunu tersine çevirmelisiniz. İkili XML eklemek yerine, biri XML içeren birden çok parçaya sahip bir belgeyi nasıl kapatacağınızı düşünmelisiniz.

Bunun geleneksel çözümü bir arşivdir (örn. Tar). Ancak, çevreleyen belgenizi metin tabanlı bir biçimde tutmak istiyorsanız veya bir dosya arşivleme kitaplığına erişiminiz yoksa, e-posta ve HTTP'de yoğun olarak kullanılan ve çok parçalı / * MIME olan standartlaştırılmış bir şema da vardır. Content-Transfer-Encoding: ikili .

Örneğin, sunucularınız HTTP üzerinden iletişim kuruyorsa ve çok parçalı bir belge göndermek istiyorsanız, birincil belge ikili veriye atıfta bulunan XML belgesidir, HTTP iletişimi aşağıdaki gibi görünebilir:

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

Yukarıdaki örnekte olduğu gibi, XML cid, Content-Id başlığının bir tanımlayıcısı olan bir URI şeması kullanarak çevreleyen çok parçadaki ikili verilere atıfta bulunur . Bu şemanın ek yükü sadece MIME başlığı olacaktır. Benzer bir şema, HTTP yanıtı için de kullanılabilir. Elbette HTTP protokolünde, çok parçalı bir belgeyi ayrı istek / yanıta gönderme seçeneğiniz de vardır.

Verilerinizi çok parçalı olarak sarmamaktan kaçınmak istiyorsanız, veri URI'si kullanmaktır:

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

Ancak bunun base64 ek yükü var.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.