摘要:提出一種Java connector方式制作動態(tài)專題圖,并與ArcIMS制作動態(tài)專題圖的另一種方式即定制開發(fā)ArcXML方式作了對比。前者直接編輯ArcXML文件,操作過程復(fù)雜、不易擴(kuò)展,難以達(dá)到動態(tài)制作的目的;后者實現(xiàn)了ArcXML到Java對象的映射,支持面向?qū)ο蟮姆绞介_發(fā),省去了處理繁瑣的ArcXML過程。重點(diǎn)以實際應(yīng)用中制作專題統(tǒng)計圖、分類圖為例,采用會話對象存儲動態(tài)數(shù)據(jù),結(jié)合Java connector 的面向?qū)ο箝_發(fā)功能,從數(shù)據(jù)角度和顯示角度實現(xiàn)制作動態(tài)專題圖的目的。實踐表明,采用Java connector方式靈活方便、切實可行。
關(guān)鍵詞:ArcIMS;Java連接器;ArcXML;專題圖
中圖分類號:TP311文獻(xiàn)標(biāo)志碼:A
文章編號:1001-3695(2008)05-1485-04
專題地圖制圖作為對空間地理目標(biāo)專題數(shù)據(jù)或?qū)傩詳?shù)據(jù)的最有效的可視化工具, 不僅能將GIS 中的專題信息進(jìn)行渲染和直觀的可視化分析,而且能對地理信息進(jìn)行深加工,發(fā)掘隱藏在數(shù)據(jù)中的模式以及發(fā)展趨勢,為人們獲取某種或某些特定的信息提供一個有效的手段[1]。專題地圖在WebGIS中具有舉足輕重的作用,是專題屬性信息可視化的重要表現(xiàn),也是空間分析結(jié)果常用的表達(dá)形式。
ArcIMS是ESRI公司開發(fā)的一種實現(xiàn)網(wǎng)上制圖和分布式GIS的WebGIS軟件系統(tǒng),它允許用戶在Internet和Intranet環(huán)境下為瀏覽器端的客戶提供GIS應(yīng)用和地圖服務(wù)。有關(guān)ArcIMS如何制作專題圖的文章很少。文獻(xiàn)[2,3]中介紹了一種編輯地圖配置文件的方式,這種方式操作過程較復(fù)雜。它事先設(shè)定專題變量,該變量可能是圖層或第三方數(shù)據(jù)庫表中的某列數(shù)據(jù),或某幾列數(shù)據(jù)的組合(表達(dá)式)。該方式中專題變量的數(shù)量和內(nèi)容是固定的,當(dāng)增加或減少專題變量時必須修改地圖配置文件,相當(dāng)于專題圖已經(jīng)固定并事先生成,只是在需要時通過圖片形式發(fā)布。因此,其動態(tài)的實質(zhì)是僅實時讀取固定表中動態(tài)變化的數(shù)據(jù)。而真正的動態(tài)專題地圖制作要根據(jù)用戶提交的專題信息實時生成并發(fā)布,而不是事先將專題圖生成接著動態(tài)發(fā)布。本文提出一種Java connector方式來制作動態(tài)專題圖,支持面向?qū)ο箝_發(fā),不僅可以動態(tài)設(shè)定專題變量,而且可以靈活定制表現(xiàn)風(fēng)格,從數(shù)據(jù)和表現(xiàn)兩個層面上達(dá)到動態(tài)制作專題圖的目的。
1ArcIMS體系結(jié)構(gòu)
ArcIMS的體系結(jié)構(gòu)如圖1所示,主要由兩大部分組成,即客戶端(瀏覽器)和服務(wù)器端[4]。客戶端瀏覽器主要有HTML Viewer和Java Viewer兩種。服務(wù)器端的最前端是網(wǎng)絡(luò)服務(wù)器,客戶端使用普通的IE瀏覽器與之直接交互;網(wǎng)絡(luò)服務(wù)器通過ArcIMS連接器與應(yīng)用服務(wù)器連接,應(yīng)用服務(wù)器請求的數(shù)據(jù)從空間服務(wù)器中獲得。空間服務(wù)器是整個ArcIMS的核心,它處理請求的地圖數(shù)據(jù)和相關(guān)信息。各組成部分依賴TCP/IP通信協(xié)議,彼此之間的通信通過ArcXML格式傳遞。
ArcXML是XML派生的用在ArcIMS軟件中的標(biāo)記語言,它有自己定義的一組標(biāo)簽。在Internet世界,XML的用途主要有兩個:a)作為元標(biāo)記語言定義各種實例標(biāo)記語言標(biāo)準(zhǔn);b)作為標(biāo)準(zhǔn)交換語言,擔(dān)負(fù)起描述交換數(shù)據(jù)的作用。ArcXML是與空間服務(wù)器通信的標(biāo)準(zhǔn)語言。當(dāng)客戶端向運(yùn)行在ArcIMS空間服務(wù)器上的地圖服務(wù)發(fā)送請求時,請求的信息就是采用ArcXML描述的。空間服務(wù)器根據(jù)請求的內(nèi)容作出相應(yīng)的反應(yīng),并將反應(yīng)信息以ArcXML描述的格式返回給請求端[3]。
2專題地圖制作
專題地圖制作步驟如下:選擇專題地圖類型;選擇地圖的專題變量;自定義專題地圖。所謂自定義是指改變專題地圖的某些設(shè)置,如顏色、大小、符號、圖例設(shè)計等。
2.1ArcIMS支持的專題類型
ArcIMS支持六種專題圖的制作,如表1所示。
2.2ArcIMS制作動態(tài)專題圖的兩種方式
ArcXML語言是ArcIMS的精華。專題圖繪制實現(xiàn)主要通過ArcXML與ArcIMS服務(wù)器之間的請求和通信實現(xiàn),利用XML技術(shù)綁定數(shù)據(jù),采用ArcIMS對XML文件進(jìn)行解析,并將解析出來的結(jié)果通過各種專題圖形式反饋給用戶[5]。
2.2.1編輯地圖配置文件方式
ArcXML作為客戶端與ArcIMS空間服務(wù)器通信的標(biāo)準(zhǔn)語言。ArcXML文件是文本格式,以.axl結(jié)尾,可以通過文本編輯的方式來直接提交制作專題圖的請求。編輯ArcXML的方式通常分為三種:一種通過author工具,作相關(guān)設(shè)置之后自動生成axl文件;一種是通過文本編輯器或XML編輯器(這兩種方式本質(zhì)上屬于服務(wù)器端定制,用戶不可更改);另一種則是通過客戶端腳本,形成相應(yīng)的ArcXML制圖請求,提交給ArcIMS的spatial server,實現(xiàn)由客戶端定制得到專題圖[3]。
編輯地圖服務(wù)配置文件的方式有以下三個缺點(diǎn):
a)采用author管理工具配置地圖服務(wù)時,一些符號元素?zé)o法在author定義, 如GRADIENTFILLSYMBOL和TRUETYPEMARKERSYMBOL元素在author界面上無法定義,只能使用ArcXML定義。另外,盡管在author中可以使用組合專題圖,但要指定不同要素以不同的符號顯示,只能通過定制完成。
b)脫離author環(huán)境,編輯配置文件時必須嚴(yán)格遵守ArcXML語法,配置中的任何錯誤會導(dǎo)致服務(wù)不會被刷新,甚至?xí)?dǎo)致地圖服務(wù)從管理器中刪除。
c)當(dāng)用第三方關(guān)系數(shù)據(jù)表中動態(tài)變化的數(shù)據(jù)制作動態(tài)專題圖時,實質(zhì)上是在數(shù)據(jù)表結(jié)構(gòu)與專題圖要素之間建立了一種綁定關(guān)系。在實際應(yīng)用中當(dāng)需要新增要素時,不僅需要修改數(shù)據(jù)表結(jié)構(gòu),而且還要更新配置文件,不能達(dá)到動態(tài)制作的目的。
綜上所述,采用編輯地圖配置文件的方式操作過程復(fù)雜、難以擴(kuò)展,實質(zhì)上沒有達(dá)到動態(tài)的效果,因此需要提出一種新的開發(fā)方式。
2.2.2Java connector方式
ArcIMS應(yīng)用服務(wù)連接器將Web服務(wù)器與ArcIMS應(yīng)用服務(wù)器連接在一起,包括ColdFusion connector、ActiveX connector、Servlet connector、Java connector四種。Servlet connector通過純粹的ArcXML文件來傳輸請求和響應(yīng);ColdFusion connector在其自身的運(yùn)行環(huán)境中使用自定義tags來產(chǎn)生ArcXML請求和響應(yīng);Java connector與ActiveX connector比較類似,通過一組API(Java connector還有標(biāo)簽庫)來產(chǎn)生ArcXML請求和響應(yīng),它們是面向?qū)ο蟮拈_發(fā)方式,比較符合一般程序員的思維習(xí)慣。
目前ArcIMS的連接器中,Java connetor是功能最完善的。也就是說Java connetor實現(xiàn)了更多的ArcXML到Java對象的映射,使開發(fā)人員能夠直接以面向?qū)ο蟮姆绞絹磉M(jìn)行ArcIMS的開發(fā),而不必花太多時間去處理ArcXML。相應(yīng)地,Java connector提供了六種專題類型到Java對象的映射。Java connector對象模型圖參照圖2。
選用Java connector是所謂的瘦客戶。ArcXML的所有處理,包括請求和回應(yīng),都是在服務(wù)器端完成的。很明顯使用客戶端的速度會快很多,因為地圖的矢量數(shù)據(jù)比較大,所有的請求和回應(yīng)都在客戶端進(jìn)行將影響性能;另外Java connector是目前功能最完善的ArcIMS連接器,而且很多應(yīng)用可能都會與SDE結(jié)合,這樣采用Java平臺的話,也可以方便地結(jié)合ArcSDE的Java API來進(jìn)行一些應(yīng)用功能的開發(fā);再者,在服務(wù)器操作系統(tǒng)平臺,Linux發(fā)展很快,采用Java connector在操作系統(tǒng)的選擇上也有一定的優(yōu)勢。
3應(yīng)用實例
3.1實驗數(shù)據(jù)
3.1.1圖層數(shù)據(jù)(xz.shp)
以北京市大興區(qū)各鄉(xiāng)鎮(zhèn)地理位置中心點(diǎn)數(shù)據(jù)作為圖層數(shù)據(jù)(shape格式)。結(jié)構(gòu)如下:
XZMCXYLDLOBJECTID
…
數(shù)據(jù)結(jié)構(gòu)中含有LDL字段,代表該鄉(xiāng)鎮(zhèn)的勞動力人口總數(shù)。下文將用這個專題變量制作勞動力分類圖。
3.1.2第三方DBF數(shù)據(jù)(crop.dbf)
以北京市大興區(qū)各鄉(xiāng)鎮(zhèn)作物類別統(tǒng)計表為例。結(jié)構(gòu)如下:
XZMCVEGATABLEMELONFLOWER…
3.1.3ArcSDE表空間數(shù)據(jù)(SDE.wall)
以北京市大興區(qū)某年設(shè)施農(nóng)業(yè)墻體類別統(tǒng)計表數(shù)據(jù)為例。結(jié)構(gòu)如下:
XZMCSOIL_WALLNON_WALLBRICK_WALL…
3.2地圖服務(wù)配置
在author中加載圖層數(shù)據(jù),包括行政區(qū)劃圖、鄉(xiāng)鎮(zhèn)中心點(diǎn)圖層等,將這些圖層數(shù)據(jù)導(dǎo)入到ArcSDE數(shù)據(jù)庫中統(tǒng)一管理。當(dāng)然也可以不借助ArcSDE,而在本地存儲。之后在administrator中將author生成的axl文件配置地圖服務(wù),并將virtual ser-ver類型設(shè)置為image server。DBF屬性文件存儲到地圖數(shù)據(jù)的目錄下。3.3利用本層數(shù)據(jù)生成分類專題圖
所謂本層數(shù)據(jù)是指地圖服務(wù)中的具體某一圖層數(shù)據(jù)。該數(shù)據(jù)的來源可以是本地硬盤空間數(shù)據(jù),也可以是連接到Arc-SDE空間數(shù)據(jù)庫中的空間數(shù)據(jù)。利用Java connector可以分別從數(shù)據(jù)角度和顯示角度支持制作專題圖的靈活性。
3.3.1數(shù)據(jù)
FeatureLayer fLayer=(FeatureLayer) objMap.-getLayers().item(iTargetItem);//定義特征層地圖服務(wù)對象objMap的定義及初始化可參見文獻(xiàn)[6];fLayer為特征層對象,它可從地圖服務(wù)對象中取出,在本例中為鄉(xiāng)鎮(zhèn)中心點(diǎn)圖層;iTargetItem為該點(diǎn)圖層在地圖服務(wù)對象中的索引號,可以根據(jù)制圖的需要動態(tài)設(shè)定。ValueMapRenderer vMapRend = new ValueMap-Renderer();
//分類對象定義
vMapRend.setLookupField(\"LDL\");
//動態(tài)設(shè)定專題變量,該專題變量從特征層中直接提取
3.3.2表現(xiàn)風(fēng)格
Range Low=new Range();//Low對象指定LDL大小范圍。
分類的標(biāo)準(zhǔn),包括分為幾類、每一類的取值范圍、每類范圍的著色和圖例標(biāo)簽均可以根據(jù)需要動態(tài)調(diào)整。現(xiàn)假定根據(jù)LDL取值分為四類,即Low:1~100;Medium:100~200;High:200~600;Super:>600。示意代碼如下:
low.setLower(\"1\");/*Low對象下界屬性賦值為1;Medium為100;High為200;Super為600*/
low.setUpper(\"100\");/*Low對象上界屬性賦值為100;Medium為200;High為600;Super為人口最大數(shù)*/
low.setLabel(\"1~100\");/*Low對象圖例標(biāo)簽,Medium、High和Super分別為\"100~200\"、\"200~600\"及\">600\"*/
low.setSymbol(Lowclr);
//Lowclr為指定的顯示顏色,其余三個類似
vMapRend.addObject(Super);
vMapRend.addObject(High);
vMapRend.addObject(Medium);
vMapRend.addObject(Low);//對象添加
fLayer.setRenderer(vMapRend);
objMap.refresh();//對象添加;地圖刷新顯示
效果如圖4所示。
3.4利用第三方DBF屬性表生成統(tǒng)計專題圖
3.4.1數(shù)據(jù)的動態(tài)
Filter filter=new Filter();
filter.setGlobalEnvelope(true);
Filter.setJoinTable(\"crop\");
//crop為DBF表名,可以根據(jù)實際需要動態(tài)選定
Filter.setJoinExpression(\"To=[xz.XZMC],F(xiàn)rom=[crop. XZMC],Type=[exact]\");
fLayer.SetFilterObject(filter);/*圖層數(shù)據(jù)和DBF表建立連接關(guān)系,同樣圖層數(shù)據(jù)xz也可以根據(jù)需要靈活設(shè)定*/
ChartValue vegatableValue=new ChartValue();/*用來創(chuàng)建分類對象,幾個ChartValue對象代表分為幾類。本例中分為三類,還包括me-lonValue對象和FlowerValue對象*/
VegatableValue.setLookUpField(crop.VEGATABLE);
//分類對象賦值,讀取crop表中的vegatable字段
3.4.2表現(xiàn)風(fēng)格的動態(tài)
SimpleLabelRenderer simpleLabel=new simpleLabelRenderer();
//定義渲染對象
ChartSymbol chartsym=new ChartSymbol();
Chartsym.setMode(\"PIE\");/*專題圖模式,可以為PIE代表餅圖,也可以設(shè)定為BAR代表柱狀圖*/
VegatableValue.setColor(VegatableClr);//Vegatable為顯示顏色
//設(shè)定三個專題變量:
chartsym.addChartValue(vegatableValue);
chartsym.addChartValue(melonValue);
chartsym.addChartValue(FlowerValue);
simpleLabel.addObject(chartsym);
fLayer.setRenderer(simpleLabel);objMap.refresh();
//對象添加;地圖刷新顯示
3.5利用ArcSDE表空間中的屬性表生成統(tǒng)計專題圖
該方式與上文介紹的DBF方式類似,但有兩處不同:
a)圖層數(shù)據(jù)xz.shp采用ArcSDE空間數(shù)據(jù)庫管理。
b)連接方式不同:
Filter filter = new Filter();
filter.setGlobalEnvelope(true);
String where=\"SDE.xz.XZMC=SDE.wall.XZMC\";
filter.setWhereExpression(where);
filter.setJoinTable(\"SDE.wall\");
3.6利用臨時存儲數(shù)據(jù)制作專題圖
臨時存儲數(shù)據(jù)制作專題圖在WebGIS應(yīng)用系統(tǒng)中的地位——統(tǒng)計專題圖。
3.6.1會話對象
臨時存儲數(shù)據(jù)不儲存在DBF文件中,也不存儲在屬性數(shù)據(jù)庫表中,多數(shù)情況下指用戶進(jìn)行的數(shù)據(jù)庫查詢。查詢結(jié)果集(recordSet)的產(chǎn)生本身具有靈活性,所以制作出來的專題圖同樣具有靈活性。典型的Web應(yīng)用程序與瀏覽器之間的連接是無狀態(tài)的。因為瀏覽器與Web服務(wù)器之間的連接無法維持不斷,所以數(shù)據(jù)庫查詢對專題圖頁面的通知無法很容易地辦到。不過Web應(yīng)用程序仍然可以保留用戶的會話數(shù)據(jù)(session data),通過會話數(shù)據(jù)來維系表現(xiàn)視圖和業(yè)務(wù)邏輯模型的數(shù)據(jù)通信[7]。
Session對象的一個主要用途就是存儲和檢索屬性值,以在頁面間傳遞針對用戶的信息[8]。它可以存儲包括recordSet在內(nèi)的各種數(shù)據(jù)類型。文獻(xiàn)[9]介紹了一種用二維數(shù)組存儲記錄集的方法,并證明將記錄集數(shù)據(jù)存入數(shù)組會大大提高速度。下文采用這種方法,將結(jié)果集存入二維數(shù)組,然后將二維數(shù)組存儲為session對象以實現(xiàn)數(shù)據(jù)庫查詢和專題制圖頁面的實時數(shù)據(jù)通信。
3.6.2應(yīng)用會話對象制作統(tǒng)計專題圖
設(shè)計了一個Java類ThemeClass(圖5)。該類有一個私有字符串?dāng)?shù)組變量strColor和該變量相對應(yīng)的公有Get/Set方法,還有一個DrawTheme(String strData[][], String strType, Map objMap, String strMappingField, String strLabelField, int iTargetItem, int iLabelItem)靜態(tài)方法。其中:strColor變量用來存儲各專題變量的RGB格式顏色,提供的SetColor方法可以對該變量進(jìn)行修改;StrData為頁面獲取的session會話對象的值,在本例中為array變量的值,Array的取法為:String[][]Array=(String[][])session.getValue(\"SESSION\"),即先獲取session的屬性值,并用類型轉(zhuǎn)換符還原類型,屬性值還原類型使它成為最初設(shè)定類的一個實例[8];strType為專題圖類型,可以動態(tài)取PIE和BAR,分別代表餅狀圖和柱狀圖;objMap為上文提到的地圖服務(wù)對象;strMappingField為映射字段,該字段從圖層文件中選取;strLabelField為地圖標(biāo)志字段,也是從圖層讀取,若該字段在圖層結(jié)構(gòu)中不存在,則不顯示標(biāo)注;iTargetItem為該點(diǎn)圖層在地圖服務(wù)中的索引號;iLabelItem為標(biāo)注層在地圖服務(wù)對象中的索引號。下面用一個實例演示DrawTheme方法的處理過程。
a)使用的數(shù)據(jù)。專題圖層數(shù)據(jù)(地圖索引號iTargetItem)如下:
XZMCXYLDLOBJECTID…
標(biāo)注層數(shù)據(jù)(地圖索引號iLabelItem)。該圖層為可選圖層如下:
XZMCLabelFieldOBJECTID…
會話數(shù)據(jù)(可能是某查詢的結(jié)果集,里面的字段個數(shù)根據(jù)實際需要隨時變化),存儲為一個二維數(shù)組。其中Total字段的值控制專題圖大小如下:
XZMCItemAItemBItemCTotal
b)處理過程,從數(shù)據(jù)和顯示兩個角度進(jìn)行。
(a)數(shù)據(jù)的動態(tài)
int rows=strData.length;//會話數(shù)據(jù)記錄個數(shù)
int columns=strData[0].length-1;
//排除掉最后一個字段的字段總數(shù)
StringBuffer strLabFldBuf=new StringBuffer();/*存儲動態(tài)專題變量,strLabFldBuf值格式:\"ItemA ItemB ItemC\"*/
FeatureLayer fTarget = (FeatureLayer) objMap.getLayers().item(iTargetItem);//動態(tài)設(shè)定專題層
FeatureLayer fLabel = (FeatureLayer) objMap.getLayers().item(iLabelItem);//動態(tài)標(biāo)注層
SimpleLabelRenderer simpleLabel = new SimpleLabelRenderer();
simpleLabel.setField(strLabelField);
//動態(tài)設(shè)定標(biāo)注
ValueMapLabelRenderer valueRenderer = new ValueMapLabelRenderer();
valueRenderer.setLookupField(strMappingField);
//動態(tài)設(shè)置映射字段
valueRenderer.setLabelField(strLabFldBuf.toString().trim());
//設(shè)定專題變量
for (int i=1;i Exact exact = new Exact(); exact.setValue(strData[i][0]); //用XZCM字段建立專題圖層與數(shù)組的映射關(guān)系 (b)顯示風(fēng)格的動態(tài) ChartSymbol chart=new ChartSymbol(); chart.setMode(strType);//動態(tài)設(shè)定專題圖類型 chart.setSize(size);//size大小根據(jù)Total大小設(shè)定 for (int j=1;j ChartValue value=new ChartValue(); value.setValue(Long.parseLong(strData[i][j])); value.setColor(strFinalColor[j-1]);//專題變量賦色 chart.addChartValue(value);} exact.setSymbol(chart); valueRenderer.addObject(exact);} fTarget.setRenderer(valueRenderer); fLabel.setRenderer(simpleLabel); objMap.refresh();//地圖刷新顯示 至于動態(tài)圖例的處理則更容易,即提取專題變量的字段名稱和顏色,用table或者div標(biāo)簽就能夠表達(dá)。具體選擇哪個標(biāo)簽可以參考文獻(xiàn)[10] 。 c)生成結(jié)果。ItemA、ItemB、ItemC在圖例中分別指代土墻、無墻、磚墻。圖6為北京市大興區(qū)某年設(shè)施類別柱狀圖。 4結(jié)束語 定制開發(fā)ArcXML文件制作專題圖具有局限性:ArcXML語法要求嚴(yán)格,難以擴(kuò)展;從本質(zhì)上講專題變量是固定的,未能真正體現(xiàn)出制作過程的動態(tài)性。基于Java connector,采用面向?qū)ο蟮拈_發(fā)方式,實現(xiàn)了Java對象和ArcXML的映射,可方便定制專題變量。而且在該方式下,可用二維數(shù)組存儲臨時數(shù)據(jù)并借助會話對象保存,有效地分離專題表現(xiàn)層和查詢邏輯層,簡化了程序的設(shè)計和構(gòu)建,并更容易維護(hù)和擴(kuò)展。 參考文獻(xiàn): [1]周海燕,華一新.GIS中定量專題制圖模板的研究與實踐[J].測繪通報,2000,10:9-11. [2] 黃丙湖,閭國年,陳踴,等.網(wǎng)絡(luò)環(huán)境下動態(tài)專題圖制作研究[J].南京師范大學(xué)學(xué)報,2005,5(2):87-90. [3]馮克忠,姜遵鋒,薛本新,等.ArcIMS中動態(tài)專題制圖的實現(xiàn)[C]//第六屆ArcGIS暨ERDAS中國用戶大會論文集.北京:地震出版社,2004:896-901. [4]謝建華,陶紅,李培錚.開發(fā)WebGIS的ArcIMS新技術(shù)應(yīng)用分析[J].地球信息科學(xué),2003,3:51-54. [5]黃健熙,吳炳方.基于B/S的水土保持信息查詢系統(tǒng)的設(shè)計和實現(xiàn)[J].計算機(jī)應(yīng)用研究,2006,23(7):138-144. [6]ESRI中國(北京)有限公司.中國用戶通訊第14期[EB/OL].(2003).http://www.esrichina-bj.cn/ library/arcnews14. [7]CAVANESS C.Programming Jakarta struts[M].北京:高等教育出版社,1989. [8]徐國平,劉臣勇,于君.JSP網(wǎng)絡(luò)開發(fā)實務(wù)[M].北京:電子工業(yè)出版社,2001. [9]極速ASP官方論壇.將recordset記錄集提取到一個二維數(shù)組及早地斷開記錄集[EB/OL].(2006-07-26).http://www.leadbbs.com/a/a.asp?B=230ID=2405358p=2q=1r=866987. [10]李超.CSS網(wǎng)站布局實錄[M].北京:科學(xué)出版社,2006. “本文中所涉及到的圖表、注解、公式等內(nèi)容請以PDF格式閱讀原文”