Як ви вбудовуєте двійкові дані в XML?


107

У мене є два програми, написані на Java, які спілкуються між собою за допомогою XML-повідомлень по мережі. Я використовую SAX-аналізатор на кінці прийому, щоб повернути дані з повідомлень. Однією з вимог є вбудовування бінарних даних у повідомлення XML, але SAX цього не любить. Хтось знає, як це зробити?

ОНОВЛЕННЯ: Це я працюю з класом Base64 з бібліотеки кодеків apache commons , на випадок, якщо хтось інший намагається щось подібне.

Відповіді:



209

XML настільки універсальний ...

<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 - це як насильство - якщо це не вирішує вашу проблему, ви недостатньо використовуєте її.

Редагувати:

BTW: Base64 + CDATA - це, мабуть, найкраще рішення

(EDIT2:
Хто мене переосмислив, будь-ласка, також оновив справжню відповідь. Ми не хочемо, щоб якась бідна душа приїжджала сюди і фактично впроваджувала мій метод, тому що це був найвищий рейтинг на SO, правда?)


9
Це не менш ніж ганебне використання XML, якщо ви серйозно. А якщо ви цього не зробите, як би знали початківці, які не пишуть - високий рівень - думають - низький?
TheFlash

1
Я думаю, що це смішно. Але так, ще раз, використовуючи фактичний тип даних base64, це шлях. CData занадто загальний.
Omniwombat

4
Я не думаю, що це досить описово - можливо, слід використовувати "BINARYDIGIT", а не скорочення "BIT"? ;-)
Лі Аткінсон

Ого. Це зробить середній кілобайт-файл приблизно в 230 разів більшим :)
Nyerguds

36
О, заради f *** s. Це був жарт. Що ж мені робити?:! Thedailywtf.com/Articles/The-HumanReadable-Encryption-Key.aspx
Пн

26

Base64 - це справді правильна відповідь, але CDATA - це не так, це в основному говорить: "це може бути все", однак це не повинно бути нічого, це має бути кодовані Base64 двійкові дані. Схема XML визначає двійковий код Base 64 як примітивний тип даних, який ви можете використовувати у своєму xsd.


2
Додаткова точка для згадування xs:base64Binaryтипу даних, який є правильним типом для використання.
Крістофер Шульц

14

У мене була ця проблема лише минулого тижня. Мені довелося серіалізувати PDF-файл і відправити його, всередині XML-файлу, на сервер.

Якщо ви використовуєте .NET, ви можете перетворити двійковий файл безпосередньо в рядок base64 і вставити його всередині елемента XML.

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

Або є метод, вбудований прямо в об’єкт XmlWriter. У моєму конкретному випадку мені довелося включити простір імен типу 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();

Рядок abc виглядає приблизно так:

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

найкраща відповідь, тому що я можу скопіювати / вставити Convert.ToBase64String з нього
Eldritch Conundrum


5

Спробуйте Base64 кодування / декодування своїх бінарних даних. Також розгляньте розділи CDATA


4

Можливо, закодувати їх у відомий набір - щось на зразок бази 64 - це популярний вибір.



4

Накладні витрати Base64 складають 33%.

BaseXML для накладних витрат XML1.0 становить лише 20% . Але це не стандарт і є лише впровадження C. Перевірте це, якщо вас турбує розмір даних. Зауважте, що однак браузери, як правило, реалізують стиснення, щоб воно було менш необхідним.

Я розробив це після обговорення в цій темі: Кодування бінарних даних у XML: альтернативи base64 .


4

Хоча інші відповіді в основному добре, ви можете спробувати інший, більш просторий метод кодування, як yEnc. ( посилання yEnc wikipedia ) За допомогою yEnc також можна отримати можливість перевірки суми прямо "поза коробкою". Прочитайте та посилання нижче. Звичайно, оскільки XML не має вбудованого типу yEnc, ваша XML-схема повинна бути оновлена, щоб правильно описати закодований вузол.

Чому : Через стратегії кодування base64 / 63, uuencode та ін. кодування збільшує обсяг даних (накладні витрати), які потрібно зберігати та передавати приблизно на 40% (порівняно з yEnc на 1-2%). Залежно від того, що ви кодуєте, 40% накладних витрат можуть стати / стати проблемою.


yEnc - реферат Вікіпедії: https://en.wikipedia.org/wiki/YEnc yEnc - це схема кодування двійкового тексту для передачі бінарних файлів у повідомленнях на Usenet або електронною поштою. ... Додатковою перевагою yEnc перед попередніми методами кодування, такими як uuencode та Base64, є включення контрольної суми CRC для перевірки того, що декодований файл був доставлений неушкодженим. Сігналы абмеркавання


2
@Jamine, чи є у вас інша альтернатива?
Полювання

Джеймі, це може бути гідною відповіддю з огляду на трохи більше роботи. Я видалив -1 і поставить +1, якщо докладете зусиль ... Позначте мене, якщо ви продовжуєте діяти.
Пол Сасик

Джеймі, н / м. Я оновив вашу відповідь і поставив +1, сподіваючись, з інформацією, яку ви мали намір передати спочатку. Погляньте і, можливо, зробіть оновлення, як вважаєте за потрібне. (Я деякий час не працював на ПЗ. Було цікаво досліджувати та редагувати відповідь. Я поставив +1, тому що по дорозі я дізнався пару нових речей, і ось у чому справа ...? Ура.)
Пол Сасик

безвідмовні можуть бути альтернативою yEnc, коли передбачувані / фіксовані накладні витрати критичні.
Іван Косарев

2

Ви також можете Uuencode ви оригінальні двійкові дані. Цей формат трохи старший, але він робить те саме, що і кодування base63.


* кодування base63
luckydonald

0

Якщо у вас є контроль над форматом XML, ви повинні перетворити проблему назовні. Замість того, щоб прикріплювати двійковий XML, ви повинні подумати про те, як долучити документ, який має декілька частин, одна з яких містить XML.

Традиційним рішенням цього є архів (наприклад, смола). Але якщо ви хочете зберегти свій додаючий документ у текстовому форматі або якщо у вас немає доступу до бібліотеки архівації файлів, існує також стандартизована схема, яка широко використовується в електронній пошті та HTTP, яка є багатопоточною / * MIME з Передача вмісту-кодування: двійкове .

Наприклад, якщо ваші сервери спілкуються через HTTP, і ви хочете надіслати багаточастинковий документ, основним документом є XML-документ, який посилається на двійкові дані, зв’язок HTTP може виглядати приблизно так:

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

Як у вищенаведеному прикладі, XML посилається на бінарні дані в додатковій множині, використовуючи cidсхему URI, яка є ідентифікатором заголовка Content-Id. Накладні витрати цієї схеми були б лише заголовком MIME. Аналогічна схема також може бути використана для HTTP-відповіді. Звичайно, у протоколі HTTP ви також маєте можливість надсилати багаточастковий документ в окремий запит / відповідь.

Якщо ви хочете уникнути загортання ваших даних у багаточастинні, це використовувати URI даних:

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

Але це має базові64 накладні витрати.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.