Jak osadzać dane binarne w XML?

Mam dwie aplikacje napisane w Javie, które komunikują się ze sobą za pomocą wiadomości XML przez sieć. Używam parsera saksofonu na końcu odbiorczym, aby odzyskać dane z wiadomości. Jednym z wymagań jest osadzenie danych binarnych w wiadomości XML, ale SAX tego nie lubi. Czy ktoś wie jak to zrobić?

UPDATE: mam to działa z Base64 klasy z Apache commons codec library , w przypadku, gdy ktoś jeszcze próbuje coś podobne.

Author: Peter17, 2008-08-21

13 answers

Możesz zakodować dane binarne za pomocą base64 i umieścić je w elemencie Base64; poniższy artykuł jest całkiem dobry na ten temat.

Obsługa danych binarnych w dokumentach XML

 196
Author: Greg Hurlman,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-11 14:08:11

XML jest tak wszechstronny...

<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 jest jak przemoc-jeśli nie rozwiąże Twojego problemu, nie używasz go wystarczająco dużo.

EDIT:

BTW: Base64 + CDATA to chyba najlepsze rozwiązanie

(EDIT2:
Ktokolwiek mnie podnieca, proszę również podniesie prawdziwą odpowiedź. Nie chcemy, żeby jakaś biedna dusza tu przychodziła i wdrażała moją metodę, bo była najwyżej oceniana w SO, prawda?)

 192
Author: Mo.,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-08-21 14:18:17

Base64 rzeczywiście jest właściwą odpowiedzią, ale CDATA nie jest, to w zasadzie mówi: "To może być cokolwiek", jednak to musi nie być po prostu cokolwiek, to musi być Base64 zakodowane dane binarne. XML Schema definiuje base 64 binary jako prymitywny typ danych , którego możesz użyć w swoim xsd.

 22
Author: Boris Terzic,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-08-21 17:44:17

W zeszłym tygodniu miałem taki problem. Musiałem serializować plik PDF i wysłać go, w pliku XML, na serwer.

Jeśli używasz. NET, możesz przekonwertować plik binarny bezpośrednio na ciąg base64 i umieścić go w elemencie XML.

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

Lub jest metoda wbudowana bezpośrednio w obiekt XmlWriter. W moim konkretnym przypadku musiałem uwzględnić Przestrzeń nazw typu danych Microsoftu:

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

Ciąg abc wygląda tak:

<?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>
 9
Author: Baxter Tidwell,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-08-03 21:35:11

Zazwyczaj koduję dane binarne za pomocą MIME Base64 lub kodowanie URL.

 6
Author: Anders Sandvig,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-08-21 13:38:36

Spróbuj kodować/dekodować dane binarne Base64. Zajrzyj także do sekcji CDATA

 5
Author: basszero,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-08-21 13:37:52

Może zakodować je w znany zestaw - coś w rodzaju bazy 64 jest popularnym wyborem.

 4
Author: mercutio,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-08-21 13:37:19

Każde Kodowanie binarne na tekst wystarczy. Używam czegoś takiego

<data encoding="yEnc>
<![CDATA[ encoded binary data ]]>
</data>
 4
Author: Jarek Przygódzki,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-07-01 08:31:40

Base64 overhead wynosi 33%.

BaseXML dla xml1.0 overhead wynosi tylko 20% . Ale to nie jest standard i ma tylko implementację C jeszcze. Sprawdź to, jeśli chodzi o rozmiar danych. Zauważ, że jednak przeglądarki mają tendencję do implementacji kompresji, dzięki czemu jest mniej potrzebna.

Rozwinąłem go po dyskusji w tym wątku: Kodowanie danych binarnych w XML: alternatywy dla base64 .

 3
Author: KrisWebDev,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:34:59

Można również Uuencode można oryginalne dane binarne. Ten format jest nieco starszy, ale robi to samo, co kodowanie base63.

 2
Author: Andrei Savu,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-08-31 16:52:05

Nie używaj kodowania base64, ponieważ zwiększa to ilość danych, które musisz przechowywać o co najmniej 40%. Raczej używać innych metod kodowania, takich jak yEnc.

 2
Author: Jamie,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-02-17 10:01:12

Oto dobry przykład jak postępować XEP-0239

PS: nie zapomnij przeczytać odpowiedzi Mo.

PS2: przeczytaj sekcję ogłoszeń na XEP.

 0
Author: mschonaker,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:33:25

Jeśli masz kontrolę nad formatem XML, powinieneś wywrócić problem na drugą stronę. Zamiast dołączać binarny XML powinieneś pomyśleć o tym, jak załączyć dokument, który zawiera wiele części, z których jedna zawiera XML.

Tradycyjnym rozwiązaniem jest archiwum (np. tar). Ale jeśli chcesz zachować dokument w formacie tekstowym lub nie masz dostępu do biblioteki archiwizacji plików, istnieje również ustandaryzowany schemat, który jest często używany w wiadomościach e-mail i HTTP, który jest multipart/* MIME z Content-Transfer-Encoding: binary .

Na przykład, jeśli twoje serwery komunikują się przez HTTP i chcesz wysłać dokument wieloczęściowy, podstawowym jest dokument XML, który odnosi się do danych binarnych, komunikacja HTTP może wyglądać mniej więcej tak:

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

Jak w powyższym przykładzie, XML odnosi się do danych binarnych w załączającym multiparcie za pomocą schematu URI cid, który jest identyfikatorem nagłówka Content-Id. Na narzut tego schematu byłby tylko nagłówkiem MIME. Podobny schemat może być również użyty do odpowiedzi HTTP. Oczywiście w protokole HTTP istnieje również możliwość wysłania dokumentu wieloczęściowego do osobnego żądania/odpowiedzi.

Jeśli chcesz uniknąć zawijania danych w wieloczęściowy jest użycie data URI:

<myxml>
    <data href="data:application/something;charset=utf-8;base64,dGVzdGRhdGE="/>
</myxml>
Ale to ma nad głową base64.
 0
Author: Lie Ryan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-12-10 08:42:35