バイナリデータをXMLに埋め込むにはどうすればよいですか?


107

ネットワーク経由でXMLメッセージを使用して互いに通信するJavaで記述された2つのアプリケーションがあります。受信側でSAXパーサーを使用して、メッセージからデータを取得しています。要件の1つは、XMLデータにバイナリデータを埋め込むことですが、SAXはこれを好みません。誰でもこれを行う方法を知っていますか?

更新:他の誰かが同様のことを試みている場合に備えて、私はこれをapache commonsコーデックライブラリBase64クラスで動作させました。

回答:



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は暴力のようなものです。問題が解決しない場合、XMLは十分に活用されていません。

編集:

ところで、Base64 + CDATAはおそらく最良のソリューションです


EDIT2 :私をアップグレードする人は誰でも、本当の答えもアップグレードしてください。SOで最高ランクだったので、貧しい人がここに来て実際に私のメソッドを実装することは望まないでしょう。)


9
あなたが本気であるならば、これはXMLの全く不名誉な使用に他なりません。そして、そうでない場合、初心者は、高レベル、低レベル、低レベルを書かないことをどのように知っていますか?
TheFlash 2009

1
面白いと思います。しかし、はい、繰り返しますが、実際のbase64データ型を使用する方法です。CDataが一般的すぎる。
Omniwombat 2009

4
私はそれが十分に説明的であるとは思わない-おそらく人は収縮「ビット」よりもむしろ「バイナリーデジット」を使うべきか?;-)
Lee Atkinson、

ワオ。これにより、平均キロバイト範囲のファイルが約230倍大きくなります:)
Nyerguds

36
ああf *** sのために。これは冗談でした。私は何をしました
Mo.

26

Base64では確かに正しい答えですが、CDATAではない、それは基本的に言っている:「これは何でもかまいません」、しかしそれがなければならないだけで何もすることが、それは、Base64でエンコードされたバイナリデータをする必要があります。XMLスキーマは、Base 64バイナリを、 xsdで使用できるプリミティブデータ型として定義します。


2
xs:base64Binary使用するのに適切なデータ型であるデータ型について言及するための追加のポイント。
クリストファーシュルツ2017

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

多分それらを既知のセットにエンコードします-base 64のようなものが一般的な選択です。



4

Base64のオーバーヘッドは33%です。

BaseXML for XML1.0のオーバーヘッドはわずか20%です。しかし、これは標準ではなく、まだC実装しかありません。データサイズが気になる場合はチェックしてください。ただし、ブラウザは圧縮を実装する傾向があるため、圧縮は必要ありません。

このスレッドでの議論の後、私はそれを開発しました:XML内のバイナリデータのエンコード:base64の代替


4

他の答えはほとんど問題ありませんが、yEncのような、よりスペース効率の良い別のエンコード方法を試すことができます。(yEncウィキペディアリンク)yEncを使用すると、「そのまま」チェックサム機能を利用できます。以下を読んでリンクしてください。もちろん、XMLにはネイティブのyEncタイプがないため、エンコードされたノードを適切に記述するようにXMLスキーマを更新する必要があります。

理由:base64 / 63、uuencodeなどのエンコーディング戦略により。エンコーディングにより、格納および転送する必要があるデータ(オーバーヘッド)の量が約40%(vs. yEncの1〜2%)増加します。エンコードする内容によっては、40%のオーバーヘッドが問題になる可能性があります。


yEnc-ウィキペディアの要約: https : //en.wikipedia.org/wiki/YEnc yEncは、Usenet上のメッセージまたは電子メールを介してメッセージ内のバイナリファイルを転送するためのバイナリからテキストへのエンコードスキームです。... uuencodeやBase64などの以前のエンコーディング方式に対するyEncの追加の利点は、デコードされたファイルがそのまま配信されたことを確認するためのCRCチェックサムが含まれていることです。


2
@Jamineそれで、他に何か他の方法はありますか?
ハント

ジェイミー、もう少し仕事を考えれば、これはまともな答えかもしれません。私は私の-1を削除し、あなたがそれをいくつかの努力をするなら+1します...フォローアップするなら私にフラグを立ててください。
Paul Sasik

ジェイミー、n / m。私はあなたの答えを更新し、+ 1しました。うまくいけば、元々伝えたいと思っていた情報でうまくいきました。のぞいてみて、必要に応じて更新してください。(私はしばらくSOで活動していません。回答を調べて編集するのは楽しかったです。途中でいくつかの新しいことを学んだので+1しました。それがすべてのことなのです...?乾杯。)
Paul Sasik

予測可能/固定オーバーヘッドが重要な場合、escapelessyEncの代わりになる場合があります。
Ivan Kosarev


0

XML形式を制御できる場合は、問題を裏返しにする必要があります。バイナリXMLを添付するのではなく、XMLを含む複数の部分を持つドキュメントを囲む方法について考える必要があります。

これに対する従来の解決策はアーカイブ(たとえばtar)です。ただし、囲んでいるドキュメントをテキストベースの形式で保持する場合、またはファイルアーカイブライブラリにアクセスできない場合は、電子メールとHTTPで頻繁に使用される標準化されたスキームがあり、multipart / * MIMEを使用してContent-Transfer-Encoding:binary

たとえば、サーバーが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、Content-Idヘッダーの識別子であるURIスキームを使用して、囲んでいるマルチパートのバイナリデータを参照します。このスキームのオーバーヘッドは、単にMIMEヘッダーになります。同様のスキームは、HTTP応答にも使用できます。もちろん、HTTPプロトコルでは、マルチパートドキュメントを個別のリクエスト/レスポンスに送信することもできます。

データをマルチパートでラップしないようにするには、データURIを使用します。

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

ただし、これにはbase64オーバーヘッドがあります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.