Как вы встраиваете двоичные данные в XML?

95

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

UPDATE: я получил эту работу с классом Base64 из apache commons codec library, если кто-то еще пытается что-то подобное.

  • 4
    Genius! Как раз то, что я искал!
Теги:
binary
binary-data

13 ответов

200
Лучший ответ

Вы можете закодировать двоичные данные с помощью base64 и поместить его в элемент Base64; ниже статья является довольно хорошей по этому вопросу.

Обработка двоичных данных в XML-документах

  • 0
    Будьте осторожны, некоторые брандмауэры (https-соединения) иногда блокируются при наличии символа «=». (Многие кодировки строки приводят к чему-то вроде этого "kdiLKjdfdilfse =")
205

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 похож на насилие. Если это не решит вашу проблему, вы не используете его достаточно.

EDIT:

BTW: Base64 + CDATA, вероятно, лучшее решение

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

  • 0
    @ (кто бы ни уменьшил Мо ): Осветлите немного, это было весело (и код, и шутка). +1
  • 0
    Я только что повторил эту цитату своему другу, и после того, как он засмеялся, он сказал: «И больно, если тебя направят» :)
Показать ещё 23 комментария
24

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

  • 2
    Дополнительная точка для упоминания типа данных xs:base64Binary , который является правильным типом для использования.
10

У меня была эта проблема только на прошлой неделе. Мне пришлось сериализовать 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>
6

Я обычно кодирую двоичные данные MIME Base64 или URL-кодирование.

5

Попробуйте Base64 кодировать/декодировать ваши двоичные данные. Также просмотрите разделы CDATA

4

Любое двоично-текстовое кодирование будет делать трюк. Я использую что-то вроде этого

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

Может быть, закодировать их в известном наборе - что-то вроде базы 64 является популярным выбором.

3

Накладные расходы Base64 составляют 33%.

BaseXML для служебных сообщений XML1.0 составляет всего 20%. Но это не стандарт и еще только реализация C. Проверьте это, если вы заинтересованы в размере данных. Обратите внимание, что, однако, браузеры, как правило, реализуют сжатие, поэтому он менее необходим.

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

3

Хотя остальные ответы в основном хороши, вы можете попробовать другой, более экономичный способ кодирования, например, yEnc. (ссылка yEnc на Википедию) С помощью yEnc вы также можете получить контрольную сумму прямо из коробки. Читайте и ссылки ниже. Конечно, поскольку XML не имеет собственного типа yEnc, ваша XML-схема должна быть обновлена для правильного описания закодированного узла.

Почему: из-за стратегий кодирования base64/63, uuencode et al. Кодировки увеличивают объем данных (накладные расходы), которые необходимо хранить и передавать, примерно на 40% (против YEnc на 1-2%). В зависимости от того, что вы кодируете, 40% накладных расходов могут стать/стать проблемой.


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

  • 2
    @ Джеймин, так у тебя есть другая альтернатива?
  • 0
    Джейми, это может быть достойным ответом, если немного больше поработать. Я убрал -1 и +1, если вы приложите усилия ... пометьте меня, если вы последуете.
Показать ещё 1 комментарий
2

Вы также можете Uuencode исходные двоичные данные. Этот формат немного старше, но он делает то же самое, что и base63.

  • 0
    * кодировка base63
0

Если у вас есть контроль над XML-форматом, вы должны решить проблему наизнанку. Вместо прикрепления бинарного XML вы должны подумать о том, как заключить документ с несколькими частями, один из которых содержит XML.

Традиционным решением для этого является архив (например, tar). Но если вы хотите сохранить прилагаемый документ в текстовом формате или если у вас нет доступа к библиотеке архивирования файлов, существует также стандартизованная схема, которая широко используется в электронной почте и HTTP, которая multipart/* MIME с Content-Transfer-Encoding: двоичный.

Например, если ваши серверы обмениваются данными через 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 ссылается на двоичные данные в охватывающем multipart, используя схему URI cid, которая является идентификатором заголовка Content-Id. Накладные расходы этой схемы будут только заголовком MIME. Аналогичную схему можно также использовать для ответа HTTP. Конечно, в протоколе HTTP вы также можете отправить многостраничный документ в отдельный запрос/ответ.

Если вы хотите избежать обертывания ваших данных в multipart, необходимо использовать URI данных:

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

Но у этого есть накладные расходы base64.

-2

Вот хороший пример того, как действовать XEP-0239

PS: не забудьте прочитать Mo ответ.

PS2: прочитайте раздел NOTICE на XEP.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню