Comment intégrer des données binaires dans XML?
j'ai deux applications écrites en Java qui communiquent entre elles en utilisant des messages XML sur le réseau. J'utilise un analyseur SAX à la réception pour récupérer les données des messages. Une des exigences est d'intégrer des données binaires dans un message XML, mais SAX n'aime pas cela. Personne ne sait comment faire cela?
mise à jour: j'ai obtenu ce travail avec la classe Base64 de la bibliothèque apache commons codec , au cas où quelqu'un d'autre essaie quelque chose de similaire.
13 réponses
vous pouvez encoder les données binaires en utilisant base64 et les mettre dans un élément Base64; l'article ci-dessous est assez bon sur le sujet.
XML est tellement polyvalent...
<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 est comme la violence - si elle ne résout pas votre problème, vous n'en utilisez pas assez.
EDIT:
BTW: Base64 + CDATA is probably the best solution""
(Edit 2:
Qui que ce soit qui me dérange, s'il vous plaît aussi la vraie réponse. Nous ne voulons pas qu'une pauvre âme vienne ici et mette en œuvre ma méthode parce que c'était la plus haute. classé sur donc, non?)
Base64 est en effet la bonne réponse mais CDATA ne l'est pas, c'est essentiellement dire: "cela pourrait être n'importe quoi", mais il doit pas être juste n'importe quoi, il doit être données binaires codées Base64. Le schéma XML définit binaire de base 64 comme un type de données primitif que vous pouvez utiliser dans votre xsd.
j'ai eu ce problème la semaine dernière. J'ai dû sérialiser un fichier PDF et l'Envoyer, à l'intérieur d'un fichier XML, à un serveur.
si vous utilisez .NET, vous pouvez convertir un fichier binaire directement en chaîne base64 et le coller dans un élément XML.
string base64 = Convert.ToBase64String(File.ReadAllBytes(fileName));
ou, il y a une méthode intégrée directement dans L'objet XmlWriter. Dans mon cas particulier, j'ai dû inclure l'espace de nommage datatype de 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();
la corde abc ressemble à quelque chose qui ressemble à ceci:
<?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>
j'encode habituellement les données binaires avec MIME Base64 ou URL encoding .
essayez Base64 encodage / décodage de vos données binaires. Regardez aussi dans les sections CDATA
peut - être les encoder dans un set connu-quelque chose comme la base 64 est un choix populaire.
Tout binaire-codage de texte fera l'affaire. J'utilise quelque chose comme ça
<data encoding="yEnc>
<![CDATA[ encoded binary data ]]>
</data>
Base64 frais généraux est de 33%.
BaseXML pour XML1.0 "151950920-dessus de la tête n'est que de 20% . Mais ce n'est pas une norme et n'a qu'un C de mise en œuvre. Vérifiez si vous êtes concerné par la taille des données. Notez cependant que les navigateurs ont tendance à implémenter la compression afin qu'elle soit moins nécessaire.
Je l'ai développé après la discussion dans ce thread: encodage des données binaires dans XML: alternatives à base64 .
vous pouvez aussi Uuencode Vous données binaires originales. Ce format est un peu plus ancien mais il fait la même chose que l'encodage base63.
N'utilisez pas l'encodage base64 car il augmente la quantité de données que vous devez stocker d'au moins 40%. Utilisez plutôt d'autres méthodes d'encodage comme yEnc.
voici un bon exemple de la façon de procéder XEP-0239
PS: n'oubliez pas de lire Mo " réponse .
PS2: lire la section avis sur le XEP.
si vous avez le contrôle sur le format XML, vous devriez retourner le problème à l'envers. Plutôt que d'attacher le binaire XML, vous devriez penser à la façon d'enfermer un document qui a plusieurs parties, dont l'une contient XML.
la solution traditionnelle est une archive (par exemple tar). Mais si vous voulez garder votre document d'enveloppe dans un format texte ou si vous n'avez pas accès à une bibliothèque d'archivage de fichiers, il y a aussi un schéma standardisé qui est utilisé fortement dans le courrier électronique et HTTP qui est multipart / * MIME avec contenu-transfert-encodage: binaire .
par exemple, si vos serveurs communiquent par HTTP et que vous souhaitez envoyer un document en plusieurs parties, la principale étant un document XML qui se réfère à des données binaires, la communication HTTP pourrait ressembler à quelque chose comme ceci:
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--
comme dans l'exemple ci - dessus, le XML se réfère aux données binaires inclure multipart en utilisant un schéma URI cid
qui est un identifiant à L'en-tête Content-Id. Les frais généraux de ce schéma ne seraient que l'en-tête MIME. Un schéma similaire peut également être utilisé pour la réponse HTTP. Bien sûr, dans le protocole HTTP, vous avez aussi la possibilité d'envoyer un document en plusieurs parties dans une requête/réponse séparée.
si vous voulez éviter d'emballer vos données dans un multipart est D'utiliser L'URI de données:
<myxml>
<data href="data:application/something;charset=utf-8;base64,dGVzdGRhdGE="/>
</myxml>
mais cela a le base64 frais généraux.