劉娉婷
(國家圖書館,北京10081)
MARC(Machine-Readable Cataloging)是機器可讀目錄的簡稱,指利用計算機識讀和處理的目錄。它是文獻編目內(nèi)容經(jīng)過計算機處理,以代碼形式記載在一定載體上而形成的一種目錄。MARC數(shù)據(jù)是描述文獻著錄項目的國際標準格式,是實現(xiàn)計算機處理書目信息及資源共享的基礎[1]。MARC數(shù)據(jù)最早產(chǎn)生于美國,作為一種計算機技術發(fā)展早期形成的數(shù)據(jù)格式,這一格式在定義時比較充分地照顧到圖書館書目數(shù)據(jù)在文獻形式描述、內(nèi)容描述、檢索等方面的需要,具有字段數(shù)量多、著錄詳盡、可檢索字段多、定長與不定長字段結合、保留主要款目及傳統(tǒng)編目的特點、擴充修改功能強等特點[2]。在文獻數(shù)字化建設的過程中,MARC數(shù)據(jù)是數(shù)字化項目中的一項重要元數(shù)據(jù),但MARC數(shù)據(jù)中的字段信息無法被直接使用,需要提取字段以及子字段信息,保存在可讀取的數(shù)據(jù)庫中。在對MARC數(shù)據(jù)的數(shù)據(jù)格式進行深入分析后,筆者開發(fā)出可以自由選擇字段的MARC數(shù)據(jù)提取工具,該工具對MARC數(shù)據(jù)提取的字段信息沒有限制,可以進行批量提取,筆者詳細介紹了該工具的實現(xiàn)原理和開發(fā)實踐,希望能為大家提供一定的借鑒。
提取MARC數(shù)據(jù)的前提是理解MARC數(shù)據(jù)的格式結構,下面詳細地說明一下MARC數(shù)據(jù)的格式。
MARC數(shù)據(jù)格式是GB/T 2901(ISO 2709)的一個特定形式,規(guī)定了每一個用于交換的書目記錄必須遵循的標準記錄結構。MARC數(shù)據(jù)由4部分組成:記錄頭標、地址目次區(qū)、數(shù)據(jù)字段區(qū)和記錄結束符。MARC數(shù)據(jù)的記錄結構如下圖1所示:
圖1 MARC數(shù)據(jù)的記錄結構
根據(jù)GB/T 2901(ISO 2709)規(guī)定,記錄頭標位于MARC數(shù)據(jù)的開頭,由24位字符組成,包含了處理MARC數(shù)據(jù)所需的數(shù)據(jù)元素,是必備的并且不能重復。記錄頭標中的數(shù)據(jù)元素是由字符位置標識的,字符位置起始于0,記錄頭標的字符位置為0到23,數(shù)據(jù)元素具體如表1所示。
表1 記錄頭標數(shù)據(jù)元素
地址目次區(qū)位于記錄頭標之后,含有一個或多個目次項,每個目次項描述一個字段,一個目次項包含3部分:字段標識符、字段長度和字段起始字符位置,其中字段標識符由3位數(shù)字表示,字段長度由4位數(shù)字表示,字段起始字符位置由5位數(shù)字表示,即一個目次項有12位,不允許出現(xiàn)其他字符。在地址目次區(qū)之后有一個字段分隔符。地址目次區(qū)的結構如圖2所示。
圖2 地址目次區(qū)的結構
每個目次項中的字段長度是該字段全部字符數(shù)的總和,包括指示符、子字段標識符、行文或代碼數(shù)據(jù)以及字段分隔符;字段起始字符位置是該字段第一個字符在數(shù)據(jù)字段區(qū)中的位置,第一個數(shù)據(jù)字段的第一個字符的位置為0。MARC數(shù)據(jù)中的數(shù)據(jù)字段的位置完全由地址目次區(qū)決定,每個數(shù)據(jù)字段都對應地址目次區(qū)中的一個目次項。
數(shù)據(jù)字段區(qū)位于地址目次區(qū)之后,由若干定長和變長字段組成,每個字段之間用字段分隔符隔開。定長字段的結構圖3所示。
圖3 定長字段結構
變長字段的結構如圖4所示:
圖4 變長字段結構
001和005字段僅由數(shù)據(jù)和字段分隔符組成,其他字段由兩個字段指示符、一個或多個子字段以及字段分隔符組成,每個子字段的開頭是子字段標識符,由1位子字段分隔符和1位子字段代碼組成,子字段代碼一般為英文字母或數(shù)字,子字段標識符之后是代碼數(shù)據(jù)或正文數(shù)據(jù)。MARC數(shù)據(jù)中的字段和子字段原則上是可以重復的。這里要注意的是,字段標識符保存在地址目次區(qū),在數(shù)據(jù)字段區(qū)是不存在的。
MARC數(shù)據(jù)中存在著一些特殊字符,用于分隔和控制MARC數(shù)據(jù)的格式,以便機器正確的識讀和處理MARC數(shù)據(jù),MARC數(shù)據(jù)中的特殊字符主要有下面幾種:
(1)字符集中的IS1,即子字段分隔符,用作子字段標識符的第一位字符,標志著子字段的開始,在雙八位編碼表中用001F表示,在格式文本中用$表示。
(2)字符集中的IS2,用作地址目次區(qū)的結尾和數(shù)據(jù)字段的分隔符,以隔開相鄰的數(shù)據(jù)字段,在雙八位編碼表中用001E表示,在格式文本中用*表示。
(3)字符集中的IS3,即記錄結束符,置于每條記錄的結尾以表示該記錄結束,在雙八位編碼表中用001D表示,在格式文本中用%表示。
圖5是一條MARC數(shù)據(jù),這里將不能顯示的特殊字符用可顯示的字符替代,其中IS1用$表示,IS2用*表示,IS3用%表示。
MARC數(shù)據(jù)作為一項重要的元數(shù)據(jù),在文獻數(shù)字化建設的過程中是必不可少的。從MARC數(shù)據(jù)的格式來看,字段和子字段的信息并不能夠直接使用,當數(shù)據(jù)量比較大時,手工錄入并不現(xiàn)實,需要進行提取保存到可讀取的數(shù)據(jù)庫中。不同載體類型的數(shù)字化項目需要提取的MARC數(shù)據(jù)的字段信息是有差異的,同時要考慮到字段或子字段重復的情況,筆者沒有發(fā)現(xiàn)合適的工具來滿足MARC數(shù)據(jù)的提取需求,一般是自己開發(fā)提取工具,筆者針對中文圖書、民國報紙、民國期刊、音視頻等不同的載體類型開發(fā)了多個工具。這些工具只能提取固定字段的信息,靈活性差,當提取字段有變更時需要更新工具,不具備通用性,于是筆者萌生了開發(fā)一款可以自由選擇字段的MARC數(shù)據(jù)提取工具的想法,并最終完成了該工具的程序?qū)崿F(xiàn)。
以圖5中的MARC數(shù)據(jù)為例,詳細地介紹MARC數(shù)據(jù)提取原理,具體提取流程如下:
(1)讀取MARC數(shù)據(jù),每次讀取一行,假設現(xiàn)在讀取到的是圖5中的MARC數(shù)據(jù)。
圖5 MARC數(shù)據(jù)
(2)計算地址目次區(qū)中目次項的數(shù)量。該MARC數(shù)據(jù)的起始24個字符為記錄頭標,即“00911nam0 2200265 450”,記錄頭標的第12-16位為數(shù)據(jù)基地址,也就是數(shù)據(jù)字段區(qū)的起始位置,這里是“00265”,即在該條MARC數(shù)據(jù)中數(shù)據(jù)字段區(qū)起始于第265個字符。數(shù)據(jù)基地址減去記錄頭標的24個字符和地址目次區(qū)結尾的1個字段分隔符,就得到了地址目次區(qū)的總長度,這里是240。每個目次項的長度為12,用地址目次區(qū)的總長度除以12就得到了地址目次區(qū)中目次項的數(shù)量,這里是20。
(3)獲取地址目次區(qū)中所有目次項的字段標識符,按照順序存儲在數(shù)組中。每個目次項的前三位數(shù)字為字段標識符。圖1中的MARC數(shù)據(jù)的地址目次區(qū)如圖6所示,每一行是一個目次項,有標記的前三位數(shù)字為字段標識符。
圖6 地址目次區(qū)
(4)獲取數(shù)據(jù)字段區(qū)的每一個數(shù)據(jù)字段,按照順序存儲在數(shù)組中。這里要用到字段分隔符IS2,使用字段分隔符IS2將MARC數(shù)據(jù)進行分割,去掉記錄開頭的記錄頭標加地址目次區(qū)和記錄最后的記錄結束符,將得到全部的數(shù)據(jù)字段內(nèi)容。圖5中的MARC數(shù)據(jù)的數(shù)據(jù)字段區(qū)如圖7所示,每一行是一個數(shù)據(jù)字段。目次區(qū)中目次項的順序和數(shù)據(jù)字段區(qū)中字段內(nèi)容的順序是一致的,所以字段標識符數(shù)組和數(shù)據(jù)字段數(shù)組中的內(nèi)容是一一對應的,至此就獲得了MARC數(shù)據(jù)中全部的字段信息。
圖7 數(shù)據(jù)字段區(qū)
(5)按照需求提取字段內(nèi)容。將需要提取的字段標識符和子字段標識符存儲在一個數(shù)組中,依次在第(3)、(4)兩步獲取的數(shù)組中進行查找,即可得到對應的字段內(nèi)容。提取字段內(nèi)容時需要用到子字段分隔符IS1,利用IS1將數(shù)據(jù)字段進行分解,通過子字段標識符定位到對應的子字段內(nèi)容。這里要注意001和005字段是沒有子字段分隔符的。在圖6中,第一行是001字段,第二行是005字段,第三行是010字段,取001和005字段的內(nèi)容,直接讀取圖3中的第一行和第二行的內(nèi)容,取010$a字段,需要將圖7中第三行的內(nèi)容進行分解,以獲取到“978-7-5013-5978-3”。
(6)將字段內(nèi)容存儲在Microsoft Office Excel文件中,每一個子字段的內(nèi)容存儲為一列。選擇Microsoft Office Excel進行存儲是因為其具有靈活性,列數(shù)可以動態(tài)調(diào)整,符合自由選擇字段的需求,也可以方便的轉(zhuǎn)換為Microsoft Office Access等其他數(shù)據(jù)格式。
程序開發(fā)的硬件環(huán)境為普通PC機,操作系統(tǒng)是Windows 7,開發(fā)平臺是Microsoft Visual Studio 2010,目標框架使用的是.NET Framework 2.0,使用的編程語言是C#,PC機上必須安裝Microsoft Office Excel 2007和Microsoft Office Word 2007或更高版本。
自由選擇字段的MARC數(shù)據(jù)提取工具的界面如圖8所示。該工具有兩個主要功能:MARC數(shù)據(jù)提取和說明文檔展示,這里主要介紹MARC數(shù)據(jù)提取的功能。
圖8 程序界面
MARC數(shù)據(jù)提取中主要包括字段間隔字符選擇、字段選擇、MARC數(shù)據(jù)查看和MARC數(shù)據(jù)提取4個功能,下面詳細地介紹一下這些功能:
(1)字段間隔字符選擇,間隔字符分為重復字段間隔字符和重復子字段間隔字符。在MARC數(shù)據(jù)中存在著字段重復和子字段重復的現(xiàn)象,該工具會將重復的字段和子字段全部提取,存儲在一個Excel單元格中,這就需要設置間隔字符將各個字段和子字段間隔開來,以免造成閱讀困難。筆者將重復字段的間隔字符默認設置為“;”,重復子字段的間隔字符默認設置為“,”,用戶也可以根據(jù)需求設置間隔字符,如果沒有設置間隔字符則使用默認的設置。
(2)字段選擇,包括添加字段、刪除字段、清空字段列表、導入字段和導出字段的功能。
點擊“添加”按鈕,彈出添加字段對話框,按提取需求填寫字段名稱和子字段名稱,如圖9所示。這里需要注意三點:①子字段代碼只需要填寫英文字母或數(shù)字,不需要填寫子字段分隔符;②子字段代碼的英文字母大小寫需要與MARC數(shù)據(jù)保持一致;③001和005字段不需要填寫子字段代碼。字段標識符和子字段代碼填寫完成后,點擊“確定”按鈕,字段將顯示在“已選字段”列表中,如圖10所示,用戶需要依次將提取的字段添加。
圖9 添加字段
圖10 已選字段
單擊“已選字段”列表中的某一行,點擊“刪除”按鈕,可以將該字段刪除,也可以雙擊該行進行刪除操作。點擊“清空列表”按鈕,“已選字段”中的內(nèi)容將全部清除。
用戶添加完提取字段之后,為方便以后使用可以將字段列表導出。點擊“導出”按鈕,可以將“已選字段”列表中的內(nèi)容導出為后綴為“.list”的文本文件。在下一次使用時,點擊“導入”按鈕,可以將該文本文件導入,不需要再一一添加字段內(nèi)容。
(3)MARC數(shù)據(jù)查看。首先選擇MARC數(shù)據(jù)文件的編碼方式,根據(jù)文件的實際編碼方式選擇,否則可能會顯示亂碼;然后選擇要查看的MARC數(shù)據(jù)文件,點擊“查看”按鈕,顯示結果如圖11所示,這里將子字段分隔符用藍色方框代替,以方便查看。用戶可以點擊“上一條”“下一條”按鈕來查看上一條和下一條MARC數(shù)據(jù),也可以輸入指定的數(shù)字,點擊“跳轉(zhuǎn)”按鈕跳轉(zhuǎn)到指定的MARC數(shù)據(jù)。
圖11 MARC數(shù)據(jù)查看
(4)MARC數(shù)據(jù)提取。在選擇MARC數(shù)據(jù)文件編碼方式和MARC數(shù)據(jù)文件之后,選擇要保存的Excel文件,點擊“提取”按鈕,會根據(jù)已選字段將MARC數(shù)據(jù)中的相應字段內(nèi)容提取到Excel文件中。以提取001、200$a、200$f、210$a、210$c、210$d這5個字段為例,提取結果如圖12所示。該工具界面簡潔、易于操作,能夠滿足工作中對MARC數(shù)據(jù)提取的各種需求,已經(jīng)被多人使用了多年,為工作提供了便利。
圖12 MARC數(shù)據(jù)提取結果
程序開發(fā)的關鍵點在于Excel文件的操作和MARC數(shù)據(jù)字段內(nèi)容的提取。
(1)Excel文件操作
Excel文件操作包括Excel文件的創(chuàng)建、寫入和保存,筆者使用Office的Excel組件來操作Excel文件,先引入Excel組件,在COM組件庫中找到Microsoft.Office.Interop.Excel,將其添加到引用中。Excel文件操作的關鍵代碼如下所示:
//定義一個COM中空類型的對象
object missing=System.Reflection.Missing.Value;
//創(chuàng)建Excel對象
Microsoft.Office.Interop.Excel.Application app=new Microsoft.Office.Interop.Excel.Application-Class();
app.Application.Workbooks.Add(true);
//添加新工作簿
Microsoft.Office.Interop.Excel.Workbook book=(Microsoft.Office.Interop.Excel.Workbook)app.Active-Workbook;
Microsoft.Office.Interop.Excel.Worksheet sheet=(Microsoft.Office.Interop.Excel.Worksheet)book.ActiveSheet;
//設置單元格格式為文本格式
Microsoft.Office.Interop.Excel.Range myrange=sheet.get_Range(sheet.Cells[1,1],sheet.Cells[cols_line.Count+1,al_field.Count+1]);
myrange.NumberFormatLocal="@";/
/給單元格賦值
sheet.Cells[1,1]="序號";
//保存Excel文件
book.SaveCopyAs(file_xls);
//關閉工作簿
book.Close(false,missing,missing);
//退出Excel
app.Quit();
(2)MARC數(shù)據(jù)字段內(nèi)容提取
首先根據(jù)記錄頭標計算出MARC數(shù)據(jù)中字段的個數(shù),然后按照在MARC數(shù)據(jù)地址目次區(qū)中出現(xiàn)的順序,將所有的字段標識符和數(shù)據(jù)字段內(nèi)容分別存儲,最后與提取字段進行匹配來提取字段內(nèi)容。MARC數(shù)據(jù)字段內(nèi)容提取的關鍵代碼如下所示:
//根據(jù)記錄頭標計算出MARC數(shù)據(jù)中字段的個數(shù)
data_pos=int.Parse(line.Substring(12,5));
address_len=data_pos-24-1;
address_num=address_len/12;
//將字段標識符存儲在al_label中
//使用字段分隔符將MARC數(shù)據(jù)分隔,數(shù)據(jù)字段內(nèi)容存儲在al_content中
//要提取的字段標識符存儲在al_field中
//根據(jù)al_field中的字段標識符依次尋找對應的字段內(nèi)容
//001、005字段和其他字段內(nèi)容需要分別處理
//如果MARC數(shù)據(jù)中有相應字段,提取字段內(nèi)容填入單元格中,如果沒有單元格為空
MARC數(shù)據(jù)在圖書館中應用廣泛,是圖書館描述數(shù)據(jù)、存儲數(shù)據(jù)、處理數(shù)據(jù)的基礎。隨著圖書館事業(yè)的不斷發(fā)展,MARC數(shù)據(jù)始終作為元數(shù)據(jù)的標準之一,具有非常重要的作用。筆者開發(fā)的MARC數(shù)據(jù)提取工具為MARC數(shù)據(jù)的查看和提取提供了便利,在工作中的多次實踐證明了推廣該工具的可行性。目前該工具的功能還比較簡單,未來筆者將增加字段的修改、增加、刪除功能,將該工具的功能做進一步的完善,以便為工作提供更多的便利。