คุณฝังข้อมูลไบนารีใน 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'? ;-)
Lee Atkinson

ว้าว. สิ่งนี้จะทำให้ไฟล์ช่วงกิโลไบต์โดยเฉลี่ยใหญ่ขึ้นประมาณ 230 เท่า :)
Nyerguds

36
โอ้เพื่อประโยชน์ของ f *** นี่เป็นเรื่องตลก ฉันทำอะไรลงไป!: thedailywtf.com/Articles/The-HumanReadable-Encryption-Key.aspx
โม

26

Base64 เป็นคำตอบที่ถูกต้อง แต่ CDATA ไม่ใช่นั่นคือโดยพื้นฐานแล้วพูดว่า: "สิ่งนี้อาจเป็นอะไรก็ได้" แต่จะต้องไม่ใช่ข้อมูลไบนารีที่เข้ารหัส Base64 XML Schema กำหนดไบนารีฐาน 64 เป็นประเภทข้อมูลดั้งเดิมซึ่งคุณสามารถใช้ใน xsd ของคุณ


2
จุดพิเศษสำหรับการกล่าวถึงxs:base64Binaryประเภทข้อมูลซึ่งเป็นประเภทที่เหมาะสมที่จะใช้
Christopher Schultz

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>

คำตอบที่ดีที่สุดเพราะฉันสามารถคัดลอก / วาง
Eldritch Conundrum



4

อาจเข้ารหัสเป็นชุดที่รู้จัก - ฐาน 64 เป็นตัวเลือกยอดนิยม



4

ค่าโสหุ้ย Base64 คือ 33%

BaseXMLสำหรับ XML1.0 ค่าใช้จ่ายเพียง 20% แต่ยังไม่ได้มาตรฐานและยังมีการใช้งาน C เท่านั้น ตรวจสอบว่าคุณกังวลกับขนาดข้อมูลหรือไม่ โปรดทราบว่าอย่างไรก็ตามเบราว์เซอร์มีแนวโน้มที่จะใช้การบีบอัดเพื่อให้มีความจำเป็นน้อยลง

ผมพัฒนามันหลังจากการอภิปรายในหัวข้อนี้: การเข้ารหัสข้อมูลไบนารีภายใน XML: ทางเลือกในการ base64


4

ในขณะที่คำตอบอื่น ๆ ส่วนใหญ่ใช้ได้ แต่คุณสามารถลองใช้วิธีการเข้ารหัสแบบอื่นที่ประหยัดพื้นที่มากกว่าเช่น yEnc ( ลิงก์ yEnc วิกิพีเดีย ) ด้วย yEnc ยังช่วยให้สามารถตรวจสอบได้ทันที "นอกกรอบ" อ่านและลิงค์ด้านล่าง แน่นอนเนื่องจาก XML ไม่มีประเภท yEnc แบบเนทีฟสคีมา XML ของคุณควรได้รับการอัปเดตเพื่ออธิบายโหนดที่เข้ารหัสอย่างถูกต้อง

เหตุผล : เนื่องจากกลยุทธ์การเข้ารหัส base64 / 63 uuencode et al. การเข้ารหัสจะเพิ่มปริมาณข้อมูล (ค่าใช้จ่าย) ที่คุณต้องจัดเก็บและถ่ายโอนประมาณ 40% (เทียบกับของ yEnc 1-2%) ขึ้นอยู่กับสิ่งที่คุณกำลังเข้ารหัสค่าใช้จ่าย 40% อาจเป็น / กลายเป็นปัญหา


yEnc - บทคัดย่อ Wikipedia: https://en.wikipedia.org/wiki/YEnc yEnc เป็นรูปแบบการเข้ารหัสไบนารีเป็นข้อความสำหรับการถ่ายโอนไฟล์ไบนารีในข้อความบน Usenet หรือทางอีเมล ... ข้อได้เปรียบเพิ่มเติมของ yEnc เมื่อเทียบกับวิธีการเข้ารหัสก่อนหน้านี้เช่น uuencode และ Base64 คือการรวมการตรวจสอบ CRC เพื่อตรวจสอบว่าไฟล์ที่ถอดรหัสนั้นได้รับการส่งมอบเหมือนเดิม


2
@Jamine คุณมีทางเลือกอื่นไหม?
ล่า

เจมี่นี่อาจเป็นคำตอบที่ดีสำหรับการทำงานอีกเล็กน้อย ฉันลบ -1 ของฉันออกและจะ +1 หากคุณพยายาม ... ตั้งค่าสถานะฉันถ้าคุณติดตาม
Paul Sasik

เจมี่, n / m. ฉันอัปเดตคำตอบของคุณและ +1 หวังว่าจะมีข้อมูลที่คุณต้องการจะสื่อในตอนแรก ลองดูและอาจอัปเดตตามที่เห็นสมควร (ฉันไม่ได้ใช้งาน SO มาระยะหนึ่งแล้วการค้นคว้าและแก้ไขคำตอบเป็นเรื่องสนุกฉัน +1 เนื่องจากระหว่างทางฉันได้เรียนรู้สิ่งใหม่ ๆ สองสามอย่างและนั่นคือทั้งหมดที่เกี่ยวกับ ... ? ไชโย)
Paul Sasik

Escapelessอาจเป็นอีกทางเลือกหนึ่งสำหรับ yEnc เมื่อค่าโสหุ้ยที่คาดเดาได้ / คงที่เป็นสิ่งสำคัญ
Ivan Kosarev

2

คุณยังสามารถUuencodeข้อมูลไบนารีต้นฉบับของคุณได้ รูปแบบนี้เก่ากว่าเล็กน้อย แต่ทำสิ่งเดียวกับการเข้ารหัส base63


* การเข้ารหัส base63
luckydonald

0

หากคุณสามารถควบคุมรูปแบบ XML ได้คุณควรแก้ไขปัญหาจากภายนอก แทนที่จะแนบไบนารี XML คุณควรคิดถึงวิธีการแนบเอกสารที่มีหลายส่วนซึ่งหนึ่งในนั้นมี XML

วิธีแก้ปัญหาแบบเดิมคือไฟล์เก็บถาวร (เช่น tar) แต่ถ้าคุณต้องการเก็บเอกสารที่แนบมาในรูปแบบข้อความหรือหากคุณไม่สามารถเข้าถึงไลบรารีการเก็บไฟล์ได้นอกจากนี้ยังมีรูปแบบมาตรฐานที่ใช้อย่างมากในอีเมลและ HTTP ซึ่งเป็นหลายส่วน / * MIMEด้วยContent-Transfer-เข้ารหัส: ไบนารี

ตัวอย่างเช่นหากเซิร์ฟเวอร์ของคุณสื่อสารผ่าน 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

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.