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

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

ОБНОВЛЕНИЕ: Я получил эту работу с классом Base64 из библиотеки кодеков Apache Commons , на случай, если кто-то еще попробует что-то подобное.

21.08.2008 13:35:46
12 ОТВЕТОВ
РЕШЕНИЕ

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

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

210
11.09.2008 14:08:11

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

4
21.08.2008 13:37:19

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

5
21.08.2008 13:37:52

Я обычно кодирую двоичные данные с помощью MIME Base64 или URL-кодирования .

6
21.08.2008 13:38:36

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

РЕДАКТИРОВАТЬ:

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

(РЕДАКТИРОВАТЬ 2:
Кто бы ни изменял мне, пожалуйста, также измените реальный ответ. Мы не хотим, чтобы какая-то бедная душа пришла сюда и фактически внедрила мой метод, потому что это был самый высокий рейтинг на SO, верно?)

204
21.08.2008 14:18:17
Это не более чем позорное использование XML, если вы серьезно. А если нет, то как об этом узнают начинающие, которые не пишут «высокий уровень - думаю - низкий уровень»?
Robinicks 2.02.2009 10:59:05
Я думаю, что это смешно. Но да, еще раз, использование фактического типа данных base64 - это путь. CData слишком общий.
Omniwombat 21.07.2009 18:48:17
Я не думаю, что это достаточно наглядно - возможно, следует использовать «BINARYDIGIT», а не «BIT»? ;-)
Lee Atkinson 8.04.2011 09:48:07
Вау. Это увеличит средний размер файла в килобайтах примерно в 230 раз :)
Nyerguds 8.08.2011 12:03:58
Ох ради б *** Это была шутка Что же мне делать?:! Thedailywtf.com/Articles/The-HumanReadable-Encryption-Key.aspx
Mo. 18.09.2011 18:11:36

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

26
21.08.2008 17:44:17
Дополнительный пункт для упоминания xs:base64Binaryтипа данных, который является правильным типом для использования.
Christopher Schultz 8.12.2017 21:21:14

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

2
31.08.2008 16:52:05
* кодировка base63
luckydonald 22.07.2018 11:15:06

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

<data encoding="yEnc>
<![CDATA[ encoded binary data ]]>
</data>
4
1.07.2010 08:31:40

У меня была эта проблема только на прошлой неделе. Мне пришлось сериализовать 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>
13
3.08.2010 21:35:11
лучший ответ, потому что я могу скопировать / вставить Convert.ToBase64String из него
Eldritch Conundrum 8.08.2019 10:02:54

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

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


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

4
13.01.2019 01:38:58
@ Джеймин, так у тебя есть другая альтернатива?
Hunt 20.03.2014 16:40:00
Джейми, это может быть достойным ответом, если немного больше поработать. Я убрал -1 и +1, если вы приложите усилия ... пометьте меня, если вы последуете.
Paul Sasik 13.01.2019 01:13:36
Джейми, н / м. Я обновил ваш ответ и добавил +1, надеюсь, с информацией, которую вы хотели передать изначально. Посмотрите и, возможно, делайте обновления по своему усмотрению. (Я не был активным в SO в течение некоторого времени. Было весело исследовать и редактировать ответ. Я +1 добавил, потому что по ходу дела я узнал пару новых вещей, и вот в чем все дело ...? Приветствия.)
Paul Sasik 13.01.2019 01:43:21
escapeless может быть альтернативой yEnc, когда предсказуемые / фиксированные издержки являются критическими.
Ivan Kosarev 3.06.2019 18:08:43

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

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

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

4
23.05.2017 12:34:59

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

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

Если вы хотите избежать переноса данных в несколько частей, используйте URI данных:

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

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

0
10.12.2014 08:42:35