DotNet 版 (精華區(qū))
發(fā)信人: xuelu (絕情), 信區(qū): DotNet
標(biāo) 題: XML的數(shù)據(jù)編碼方式
發(fā)信站: 碧海青天 (Sun Oct 14 10:05:25 2001), 轉(zhuǎn)信
xml 數(shù)據(jù)的編碼方式
chris lovett
microsoft corporation
2000 年 3 月
目錄
------------------------------------------------------------------------
--------
1、跨平臺數(shù)據(jù)格式
2、xml 和字符編碼
3、字符集和 msxml dom
4、用 msxml 創(chuàng)建新的 xml 文檔
5、結(jié)論
6、有關(guān)詳細(xì)信息
------------------------------------------------------------------------
--------
摘要:本文介紹了字符編碼的工作原理,特別是在 xml 和 msxml dom 中的工作原
理。
近來很多人問我,如何使 xml 文件在不同的平臺間正確地傳遞數(shù)據(jù)。他們創(chuàng)建了
xml 文檔,鍵入了數(shù)據(jù),粘上了幾個標(biāo)記,調(diào)整了標(biāo)記的格式,甚至放入了
<?xml version="1.0"?> 聲明,作為額外增添。然后他們試著裝載它,可得到的卻
是意想不到的出錯消息,microsoft(r) xml parser (msxml) 報(bào)告說數(shù)據(jù)有問題。
對初編 xml 者來說,這真令人沮喪。難道它竟不能正常工作嗎?
當(dāng)然不是。當(dāng)從 msxml 收到意想不到的出錯消息時,很可能是因?yàn)榻邮諗?shù)據(jù)的平
臺將其存儲到了與發(fā)送數(shù)據(jù)不同的平臺上,結(jié)果導(dǎo)致了字符編碼問題。
跨平臺數(shù)據(jù)格式
自從計(jì)算機(jī)軟件和硬件從業(yè)人員設(shè)法將兩臺計(jì)算機(jī)連接到一起以來,他們就一直向
著創(chuàng)建跨平臺技術(shù)并使不同的平臺能夠共享數(shù)據(jù)的領(lǐng)域而努力奮斗。很早以來,由
于不同類型的計(jì)算機(jī)的數(shù)量、連接方式、希望共享的數(shù)據(jù)種類的急劇增加,事態(tài)也
就變得越來越復(fù)雜。
經(jīng)過幾十年關(guān)于跨平臺編程技術(shù)的研究,當(dāng)今(而且可能在未來的很長一段時期內(nèi)
)唯一的真正跨平臺解決方案是通過簡單的標(biāo)準(zhǔn)數(shù)據(jù)格式得到的。web 的成功正是
建立在這種格式上的。在 web 服務(wù)器和 web 瀏覽器之間傳遞的主要內(nèi)容是
http 標(biāo)題和 html 頁,兩者都是標(biāo)準(zhǔn)的文本格式。
在以下幾節(jié)中,我將討論字符編碼和標(biāo)準(zhǔn)字符集、unicode、html content-type
標(biāo)題、html content-type 元標(biāo)記和字符實(shí)體。如果您熟悉上述概念,可跳過這些
內(nèi)容去讀 encoding xml data for the xml document object model (dom)
programmer(針對 xml 文檔對象模型 (dom) 編程人員的編碼 xml 數(shù)據(jù))的提示
和技巧。有關(guān)詳細(xì)信息,請參閱 xml and character encoding(xml 和字符編碼
)。
關(guān)于字符編碼
標(biāo)準(zhǔn)文本格式是建立在標(biāo)準(zhǔn)字符集之上的。要記住,所有的計(jì)算機(jī)均將文本存儲為
數(shù)字。然而,不同的系統(tǒng)也可以用不同的數(shù)字存儲相同的文本。下表顯示了一組字
節(jié)是如何被存儲的,第一個是使用默認(rèn)代碼頁 1252、運(yùn)行 microsoft windows(r)
的典型計(jì)算機(jī),第二個是使用 macintosh roman 代碼頁的典型 apple(r)
macintosh(r) 計(jì)算機(jī)。
byte windows macintosh
140 ? ?
229 ? a
231 ? á
232 è ?
233 é è
比方說,如果您的祖母從 http://www.barnesandnoble.com/(英文)訂購了一本
新書,她不會想到她的 macintosh 計(jì)算機(jī)存儲字符的方式,并不同于運(yùn)行 www.
barnesandnoble.com(英文)的新 windows 2000 web 服務(wù)器。在往 internet 訂
購單的發(fā)貨欄中輸入瑞典家中的地址時,她相信 internet 會正確地傳遞字符 ?(
在其 macintosh 上的字節(jié)值是 140),并沒想到接收和處理她發(fā)送消息的計(jì)算機(jī)
會將字節(jié)值 140 轉(zhuǎn)換為字母 ?。
unicode
unicode consortium(統(tǒng)一碼協(xié)會)確信(用雙字節(jié)而不是單字節(jié)表示每個字符)
定義一個通用的代碼頁是個好主意,該代碼頁適用于全世界所有的語言,從而不同
代碼頁之間的映射問題將不復(fù)存在。
既然如此,如果 unicode 解決了跨平臺的字符編碼問題,那為何它卻未成為唯一
的標(biāo)準(zhǔn)呢?第一個問題是,轉(zhuǎn)換到 unicode 有時意味著使所有的文件大小加倍 —
這樣做在網(wǎng)絡(luò)世界中是不可想象的。因此有人仍樂于使用老的、單字節(jié)的字符集
,如 iso-8859-1 到 iso-8859-15、shift-jis、euc-kr 等等。
第二個問題是,仍存在許多并非基于 unicode 的系統(tǒng),這就意味著在網(wǎng)絡(luò)上,某
些組成 unicode 字符的字節(jié)值可能會給那些更舊的系統(tǒng)造成嚴(yán)重問題。因此定義
了“unicode 轉(zhuǎn)換格式 (utf)”;它們運(yùn)用位轉(zhuǎn)換技術(shù)對 unicode 字符進(jìn)行編碼
,使其成為在老系統(tǒng)上“透明的”(或可安全通過)的字節(jié)值。
此類字符編碼中最普及的是 utf-8。utf-8 采用 unicode 標(biāo)準(zhǔn)的前 127 個字符(
它們恰好是基本的拉丁文字符:a-z、a-z 和 0-9,以及幾個標(biāo)點(diǎn)字符),并直接
將其映射到單字節(jié)值。然后采用位轉(zhuǎn)換技術(shù),用字節(jié)的高位來編碼 unicode 字符
的其余部分。這樣做的結(jié)果是,小瑞典字符 ? (0xe5) 變成了下列雙字節(jié)亂碼:?
¥ (0xc3 0xa5)。所以,除非您能夠在腦海里進(jìn)行位轉(zhuǎn)換,否則,在utf-8 中編碼
的數(shù)據(jù)是無法被人讀懂的。
content-type 標(biāo)題
因?yàn)楦f的單字節(jié)字符集仍被使用,所以只有當(dāng)指定了數(shù)據(jù)所在的實(shí)際字符集之后
,傳輸數(shù)據(jù)的問題才能得以解決。認(rèn)識到這一點(diǎn)后,internet 電子郵件和 http
協(xié)議小組定義了一種標(biāo)準(zhǔn)方法,用以在消息標(biāo)題 content-type 屬性中指定字符集
。該屬性從注冊的字符集名稱列表中指定一個字符集,該字符集名稱是由
internet assigned numbers authority (iana)定義的。典型的 http 標(biāo)題都可能
包含下列文本:
http/1.1 200 ok
content-length: 15327
content-type: text/html; charset:iso-8859-1;
server: microsoft-iis/5.0
content-location: http://www.microsoft.com/default.htm
date: wed, 08 dec 1999 00:55:26 gmt
last-modified: mon, 06 dec 1999 22:56:30 gmt
該標(biāo)題向應(yīng)用程序表明,跟在標(biāo)題后面的內(nèi)容位于 iso-8859-1 字符集中。
content-type 元標(biāo)記
content-type 屬性是可選項(xiàng),在有些應(yīng)用程序中,http 標(biāo)題的信息被去掉了,而
只有 html 本身通過。為了補(bǔ)救這一點(diǎn),html 標(biāo)準(zhǔn)小組定義了一種可選的元標(biāo)記
方法,用于指定 html 文檔本身的字符集,使 html 文檔字符集是自描述的。
<meta http-equiv="content-type" content="text/html;
charset=iso-8859-1">
在這種情況下,字符集 iso-8859-1 說明在此特定的 html 頁中,字節(jié)值 229 表
示 ??,F(xiàn)在該頁對任何系統(tǒng)來說,都是完全清楚的,數(shù)據(jù)不會被曲解。遺憾的是,
由于此元標(biāo)記是可選的,所以它給錯誤留下了空子。
字符實(shí)體
不是所有的系統(tǒng)支持所有的注冊字符集。例如,我并不認(rèn)為很多平臺實(shí)際上可支持
稱為 ebcdic 的 ibm 主機(jī)字符集。windows nt 是支持的,但許多其他系統(tǒng)很可能
不支持 — 這大概就是 http://www.ibm.com(英文)主頁為什么生成 ascii 的原
因。
作為備選方案,html 允許通過指定確切的 unicode 字符值,對該頁中的單個字符
進(jìn)行編碼。然后將這些字符實(shí)體進(jìn)行脫離字符集的分析,即可確切地確定其
unicode 值。它的語法是 ?amp;#229;?or ?amp;#xe5;?。
xml 和字符編碼
xml 從 html 那里借鑒了這些思想,并使之更進(jìn)一步,定義了一個徹底明確的算法
,以確定編碼使用的字符集。在 xml 中,由 xml 聲明中的可選編碼屬性定義字符
編碼。下列算法確定默認(rèn)的編碼:
如果文件以 unicode 字節(jié)次序標(biāo)志 [0xff 0xfe] 或 [0xfe 0xff] 開頭,則認(rèn)為
該文檔是在 utf-16 編碼中。否則,它在 utf-8 中。
以下是所有正確和等效的 xml 文檔:
字符集或編碼 http 標(biāo)題 xml 文檔
iso-8859-1 content-type: text/xml; charset:iso-8859-1; <test>?lt;
/test>
utf-8 content-type: text/xml; <test>?¥</test>
iso-8859-1 content-type: text/xml; <?xml version="1.0"
encoding="iso-8859-1"?>
<test>?lt;/test>
utf-8(用字符實(shí)體) content-type: text/xml; <test>?</test>
utf-16(帶字節(jié)次序標(biāo)志的 unicode) content-type: text/xml; ff fe 3c 00
74 00 65 00 73 00 74 00 3e 00 e5 00 ..<.t.e.s.t.>...
3c 00 2f 00 74 00 65 00 73 00 74 00 3e 00 0d 00 <./.t.e.s.t.>...
0a 00
字符集和 msxml dom
現(xiàn)在,討論過不同的字符編碼方法之后,讓我們來看看如何在 msxml dom 中加載
xml 文檔,以及當(dāng)碰到模糊編碼的字符時,可能收到的出錯消息的類型。加載
xml dom 文檔的兩個主要方法是 loadxml 方法和 load 方法。
loadxml 方法總是采用只在 ucs-2 或 utf-16 中編碼的 unicode bstr。如果將非
有效的 unicode bstr 的內(nèi)容傳遞給 loadxml,則加載會失敗。
load 方法可將以下內(nèi)容當(dāng)作 variant:
value des cription
url 如果 variant 是 bstr,則將其理解為 url。
vt_array | vt_ui1 variant 也可以是包含原始編碼字節(jié)的 safearray。
iunknown 如果 variant 是 iunknown 接口,則 dom 文檔為 istream、
ipersiststream 和 ipersiststreaminit 調(diào)用 queryinterface。
load 方法實(shí)現(xiàn)以下算法,用于確定 xml 的字符編碼或字符集。
如果 content-type http 標(biāo)題定義了字符集,該字符集則替代 xml 文檔本身的所
有內(nèi)容。因?yàn)闆]有 http 標(biāo)題,所以這顯然不適用于 safearray 和 istream 機(jī)制
。
如果有雙字節(jié) unicode 字節(jié)次序標(biāo)志,則它假設(shè)編碼是 utf-16。它既可處理大
endian,也可處理小 endian。
如果有四字節(jié) unicode 字節(jié)次序標(biāo)志 (0xff 0xfe 0xff 0xfe),則它假設(shè)編碼是
utf-32。它既可處理大 endian,也可處理小 endian。
否則,它假設(shè)編碼是 utf-8,除非它用指定其他一些字符集的編碼屬性(如
iso-8859-1、windows-1252、shift-jis 等),找到 xml 聲明。
您將看到兩個從 xml dom 返回的指出編碼問題的出錯消息。第一個通常指出文檔
中的字符與 xml 文檔的編碼不匹配:
在文本內(nèi)容中發(fā)現(xiàn)了一個無效字符。
parseerror 對象可告訴您這個搗亂字符在某一行的確切位置,以便使您解決該問
題。
第二個出錯消息指出您一開始用的是 unicode 字節(jié)次序標(biāo)志(或調(diào)用了
loadxml 方法),然后編碼屬性指定了不是雙字節(jié)編碼的編碼(如 utf-8 或
windows-1250):
不支持從當(dāng)前編碼轉(zhuǎn)換到指定的編碼。
另外,您可能調(diào)用了 load 方法,并在一開始使用了單字節(jié)編碼(沒有字節(jié)次序標(biāo)
志),但是它隨后發(fā)現(xiàn)了指定雙字節(jié)或四字節(jié)編碼(如 utf-16 或 ucs-4)的編碼
屬性。
基本原則是不能利用 xml 聲明的編碼屬性,在多字節(jié)字符集如 utf-8、shift-jis
或 windows-1250,與 unicode 字符編碼如 utf-16、ucs-2 或 ucs-4 之間進(jìn)行
轉(zhuǎn)換,這是因?yàn)槁暶鞅旧肀仨殞γ總€字符都使用與文檔其余部分相同數(shù)量的字節(jié)。
最后,ixmlhttprequest 接口提供如下方法,用以訪問下載的數(shù)據(jù):
methods desc ription
responsexml 表示由 msxml dom 分析器分析的響應(yīng)實(shí)體(用與 load 方法相同的
規(guī)則)。
responsetext 表示作為字串的響應(yīng)實(shí)體。本方法盲目地解碼從 utf-8 收到的消息
實(shí)體。這是一個已知問題,應(yīng)在即將面市的 msxml web release 中得到解決。
responsebody 表示作為無符號字節(jié)數(shù)組的響應(yīng)實(shí)體。
responsestream 表示作為 istream 接口的響應(yīng)實(shí)體。
用 msxml 創(chuàng)建新的 xml 文檔
一旦加載了 xml 文檔,即可用 dom 處理 xml 文檔,而不必考慮任何編碼問題,
因?yàn)槲臋n是作為 unicode 存儲在內(nèi)存中的。所有 xml dom 接口都是基于 com
bstr 的,后者是雙字節(jié)的 unicode 字串。這就是說,您可以從新開始在包含所有
unicode 字符的內(nèi)存中建立 msxml dom 文檔,并且所有組建將會共享該內(nèi)存中的
dom,而不會對 unicode 字符值的意思有任何疑惑。然而,當(dāng)對其進(jìn)行保存時,
msxml 將以默認(rèn)方式按 utf-8 編碼所有數(shù)據(jù)。例如,假設(shè)您進(jìn)行了以下處理:
var xmldoc = new activexobject("microsoft.xmldom")
var e = xmldoc.createelement("test");
e.text = "?;
xmldoc.appendchild(e);
xmldoc.save("foo.xml");
下列 utf-8 編碼文件的結(jié)果是:
<test>?¥</test>
注意 上述例子只有當(dāng)在瀏覽器以外的環(huán)境運(yùn)行時,才有效。由于受到安全限制,
在瀏覽器里調(diào)用 save 方法將不會產(chǎn)生相同的結(jié)果。
盡管這看上去有點(diǎn)怪,但卻是正確的。下列測試裝載了用 utf-8 編碼的文件,并
測試 utf-8 是否被重新解碼為 unicode 字符值 229。它是:
var xmldoc = new activexobject("microsoft.xmldom")
xmldoc.load("foo.xml");
if (xmldoc.documentelement.text.charcodeat(0) == 229)
{
wsc ript.echo("yippee - it worked !!");
}
要想更改 xml dom save 方法使用的編碼,需要用如下位于文檔頂部的編碼屬性創(chuàng)
建 xml 聲明:
var pi = xmldoc.createprocessinginstruction("xml",
" version='1.0' encoding='iso-8859-1'");
xmldoc.appendchild(pi);
調(diào)用 save 方法時,您就會得到以下用 iso-8859-1 編碼的文件:
<?xml version="1.0" encoding="iso-8859-1"?>
<test>?lt;/test>
現(xiàn)在,小心不要被 xml 屬性迷惑。xml 屬性返回 unicode 字串。如果在創(chuàng)建
iso-8859-1 編碼聲明之后,調(diào)用 domdocument 對象上的 xml 屬性,即可取回以
下 unicode 字串:
<?xml version="1.0"?>
<test>?lt;/test>
請注意這里沒有 iso-8859-1 編碼聲明了。這是正常的。這樣做的原因是使您可以
轉(zhuǎn)而用此字串調(diào)用 loadxml,它會起作用。如果它不這么做,loadxml 會失敗并返
回出錯消息:“不支持從當(dāng)前編碼切換到指定的編碼。”
結(jié)論
但愿本文有助于解釋字符編碼的工作原理,特別是在 xml 和 msxml dom 中的工作
原理。一旦您理解了字符集編碼,它是相當(dāng)簡單的,而且 xml 是非常出色的,因
為它在這方面未留有絲毫含糊的余地。盡管 msxml dom 有幾處怪異需要密切留意
,但它仍不失為一個能讓您讀取和寫入任何 xml 編碼的強(qiáng)大工具。
有關(guān)詳細(xì)信息
microsoft msdn online library: xml dom reference(microsoft msdn 聯(lián)機(jī)庫
:xml dom 引用)
character encoding model(字符編碼模型),作者:ken whistler 和 mark
davis
iana character sets(iana 字符集)
http://www.ietf.org(英文)的 internet engineering task force (ietf) 提
供了 rfc 列表
microsoft msdn online library: compatibility issues with mixed
environments(microsoft msdn 聯(lián)機(jī)庫:與混合環(huán)境的兼容性問題)
--
oooo0 絕情空間,
( ) 0oooo
\ ( 源自苦愛. ( )
\_) ) /
——我情依舊. (_/
※ 來源:.碧海青天 bbs.dlut.edu.cn.[FROM: tianwei]
本站僅提供存儲服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請
點(diǎn)擊舉報(bào)。