国产日韩欧美一区二区三区三州_亚洲少妇熟女av_久久久久亚洲av国产精品_波多野结衣网站一区二区_亚洲欧美色片在线91_国产亚洲精品精品国产优播av_日本一区二区三区波多野结衣 _久久国产av不卡

?

文檔一致性測試系統(tǒng)的研究與設(shè)計(jì)

2022-05-27 08:53師子源王明飛
北京印刷學(xué)院學(xué)報 2022年3期
關(guān)鍵詞:表單文檔解析

師子源, 李 成, 王明飛

(1. 北京印刷學(xué)院,北京 102600; 2. 奧博杰天軟件(北京)有限公司,北京 100022)

個性化的文檔輸出在越來越多的行業(yè)中被應(yīng)用。 比如,以前去銀行或保險公司去辦理業(yè)務(wù)時,所填寫的表格往往是預(yù)印制表單,用戶或工作人員在留空中填寫相關(guān)的內(nèi)容。 而現(xiàn)在,得益于動態(tài)文檔生成系統(tǒng)的發(fā)展,越來越多的傳統(tǒng)印制表單被動態(tài)文檔所代替。 動態(tài)文檔生成系統(tǒng)徹底改變了文檔產(chǎn)生方式,之前靜態(tài)文檔的制作過程就變成了利用文檔模板和用戶數(shù)據(jù)進(jìn)行動態(tài)文檔生成的過程。

動態(tài)文檔生成過程通??梢苑譃橐韵滤牟?。

(1)制作動態(tài)文檔模板。 動態(tài)文檔生成系統(tǒng)會提供廣泛的文檔開發(fā)工具的插件,用戶可以利用這些插件在文檔內(nèi)部插入相應(yīng)的變量或規(guī)則。

(2)內(nèi)容組裝。 根據(jù)特定的用戶數(shù)據(jù),替換文檔模板中的變量;計(jì)算文檔模板定義的規(guī)則,將生成的內(nèi)容添加進(jìn)文檔模板。

(3)文檔排版。 根據(jù)生成的內(nèi)容和文檔模板中的文檔樣式定義進(jìn)行排版,該部分功能稱為排版引擎,而排版引擎確保輸出精確、緊湊的排版結(jié)果。

(4)文檔生成。 文檔排版完成后,系統(tǒng)就會根據(jù)定義好的輸出方式生成對應(yīng)格式的靜態(tài)文檔,目前,使用最多的格式是便攜式文檔格式(Portable Document Format,簡稱PDF)。

從上述動態(tài)文檔的產(chǎn)生過程步驟描述可以知道,動態(tài)文檔從制作到最終發(fā)布是一個非常復(fù)雜的過程。 動態(tài)文檔生成系統(tǒng)本身作為一個復(fù)雜軟件系統(tǒng),會有軟件系統(tǒng)所固有的問題(Software Bugs),并且會不斷進(jìn)行產(chǎn)品功能升級。 解決這些問題或功能升級過程中的一個很小的改動,最終輸出文檔可能會發(fā)生很大變化。

而對于用戶來講,只要文檔模板和用戶數(shù)據(jù)不變,最終生成的靜態(tài)文檔就要始終保持一致。 輸入數(shù)據(jù)一致的情況下,系統(tǒng)迭代更新過程中新版本生成的文檔必須要和舊版本已經(jīng)生成的文檔保持一致。 只有這種一致性能夠得到保證,客戶才會放心地把他們現(xiàn)有系統(tǒng)中的數(shù)據(jù)遷移到新版本系統(tǒng)中。通常,使用動態(tài)文檔生成系統(tǒng)的用戶都會有數(shù)量極其龐大的文檔數(shù)據(jù),靠人工去驗(yàn)證兩個版本系統(tǒng)生成文檔之間的差異已經(jīng)不現(xiàn)實(shí)。

為了解決上面提出的問題,需要設(shè)計(jì)一個能夠自動化批量比較文檔的系統(tǒng)。 該系統(tǒng)能夠自動比較兩份文檔,自動生成比較結(jié)果報表,并且自動發(fā)送通知給相關(guān)人員。 同時,該系統(tǒng)應(yīng)該是一個輕量級的系統(tǒng),提供多種運(yùn)行方式,既可以方便地集成到客戶現(xiàn)有的測試系統(tǒng)中,也可以單獨(dú)運(yùn)行,方便開發(fā)人員在運(yùn)行、提交代碼時檢查會不會產(chǎn)生輸出文檔的變化。

綜上所述,確保在動態(tài)文檔生成系統(tǒng)的不斷迭代過程中整個系統(tǒng)最終生成文檔的一致性是在系統(tǒng)開發(fā)、升級迭代過程中的重要內(nèi)容。

高麗萍[1]等人對Word 中圖文混排的文檔一致性的控制做了研究,解決了圖文混排的一些沖突情況。 馬康[2]在結(jié)構(gòu)化文檔的自動化提取方面做了研究。 牛永潔[3]等人做了基于PDFBox 的信息提取方面的研究與實(shí)現(xiàn)。 朱玲玉[4]在文檔解析與文本內(nèi)容提取及脫敏方面做了較深入研究。 徐俊剛[5]等人用本地文件模擬數(shù)據(jù)庫的方法繞過原系統(tǒng)對數(shù)據(jù)庫的依賴,提出一個自動化測試方案。

本文通過對PDF 文檔的解析,提取文檔中的文本、圖像、圖形及表單并分類,再分別與原文檔中的對應(yīng)內(nèi)容相比較,完成一致性測試。 系統(tǒng)基本框架還包括與外部集成模塊、結(jié)果報表生成模塊和結(jié)果發(fā)送模塊,系統(tǒng)結(jié)構(gòu)圖如圖1 所示。

圖1 文檔一致性測試系統(tǒng)結(jié)構(gòu)圖

1 PDF 文檔解析

PDF 格式是一種獨(dú)立于應(yīng)用程序、硬件、操作系統(tǒng)呈現(xiàn)文檔的文件格式,適用于郵件、歸檔等發(fā)布需求。 每個PDF 文件包含固定布局的平面文檔的完整描述,包括文本、字形、圖形、圖像及其他需要顯示的信息。 在對PDF 文檔比較之前,首先要分析PDF 文檔的基本結(jié)構(gòu)和文檔內(nèi)容的組織方式。

1.1 PDF 文檔結(jié)構(gòu)

一個PDF 文件從大的方面來說可以分4 個部分:文件頭(Header)、文件體(Body)、交叉引用表(XRef Table)、文件尾(Trailer),參考文獻(xiàn)都有很詳細(xì)的論述[3][4][6],其邏輯結(jié)構(gòu)如圖2 所示,從Trailer 開始進(jìn)行解析可以逐步定位到頁面組對象(Pages),進(jìn)而進(jìn)行頁面內(nèi)容提取。

圖2 PDF 文檔的邏輯結(jié)構(gòu)圖

PDF 的頁面基本內(nèi)容包括存儲為字符串的文本內(nèi)容、由圖形和線條組成的矢量圖形、由照片和其他類型的圖片組成的位圖、鏈接(文檔內(nèi)部或網(wǎng)頁)、表單、JavaScript 等。 頁面內(nèi)容結(jié)構(gòu)圖如圖3所示,Resources 指示了PDF 資源對象,包含字體、圖形、圖像、表格等;Fonts 指示字體信息,XObjects包含了圖片、表格等;Contents 指PDF 頁面內(nèi)容對象,包含PDF 頁面內(nèi)的路徑、文字、內(nèi)嵌圖像數(shù)據(jù)等頁面描述信息,PDF 規(guī)范里都有詳細(xì)描述。

圖3 PDF 頁面內(nèi)容結(jié)構(gòu)圖

系統(tǒng)選擇PDF 格式作為比較文檔格式來實(shí)現(xiàn)一致性測試系統(tǒng),其中基準(zhǔn)文件稱為BaselinePDF,對比文件稱為TestPDF。 PDF 文檔比較模塊需要對頁面的所有內(nèi)容作比較,并記錄所有變化。 PDF格式是非結(jié)構(gòu)化的文檔,并且PDF 文檔的頁內(nèi)容是按照定點(diǎn)描述的,任意內(nèi)容可以輸出在任意位置,這就導(dǎo)致程序不能以流的方式對文檔頁內(nèi)容進(jìn)行從上而下的比較。 將文檔內(nèi)容分為文本、圖像、圖形、表單之后進(jìn)行分類比較是易于實(shí)現(xiàn)的,需要比較的分類內(nèi)容如表1 所示。

表1 PDF 頁面比較內(nèi)容

系統(tǒng)以分類比較的方式進(jìn)行一致性測試,其基本流程圖如圖4 所示。 首先對輸入的Baseline 和Test 文件進(jìn)行解析,提取內(nèi)容生成中間數(shù)據(jù);然后將數(shù)據(jù)分為文本、圖形、圖像、PDF 表單四類;依次對四類內(nèi)容進(jìn)行比較,最后生成比較結(jié)果報表。

圖4 文檔一致性測試系統(tǒng)流程圖

1.2 PDF 頁內(nèi)容提取

系統(tǒng)采用了開源PDF 庫Apache PDFBox 作為PDF 文件的基礎(chǔ)解析模塊。 但PDFBox 解析PDF的結(jié)果數(shù)據(jù)并不適用于PDF 的分類比較,需要利用PDFBox 的API 生成本系統(tǒng)所需要的數(shù)據(jù)。

研究PDFBox 中關(guān)于PDF Rendering 部分的接口,可以發(fā)現(xiàn)所有解析PDF 頁的類都繼承于抽象函數(shù)PDFGraphicsStreamEngine,本系統(tǒng)的實(shí)現(xiàn)也應(yīng)遵守PDFBox 的接口規(guī)范和實(shí)現(xiàn)規(guī)則,設(shè)計(jì)一個符合本系統(tǒng)需求的解析類,該類應(yīng)繼承并實(shí)現(xiàn)PDFGraphicsStreamEngine。 該實(shí)現(xiàn)類完成下列功能:

(1)解析PDF 頁中的所有內(nèi)容。

(2)對分析出來的內(nèi)容進(jìn)行歸類,分為文本,圖形圖像,表單等單元。

(3)記錄所有單元出現(xiàn)的位置及區(qū)域信息,方便比較結(jié)果的展示。

(4)記錄所有單元在繪制時的繪制參數(shù), 即當(dāng)前圖形狀態(tài)(Graphics State)。

1.2.1 解析頁面內(nèi)容

設(shè)計(jì)一個繼承PDFBox 定義的抽象類PDFGraphicsStreamEngine 的實(shí)現(xiàn)類PDFContentExtractor,實(shí)現(xiàn)該抽象類中所定義的抽象方法(Abstract Method),完成內(nèi)容解析和分類功能。

(1)解析PDF 頁中的所有內(nèi)容。

以解析一段文本內(nèi)容舉例說明如何實(shí)現(xiàn)抽象類PDFGraphicsStreamEngine。 經(jīng)過對源碼分析,文本中內(nèi)容的開始結(jié)束都有對應(yīng)的抽象接口,在實(shí)現(xiàn)類PageContentExtractor 中需要通過實(shí)現(xiàn)這些抽象方法,對于文本內(nèi)容,其對應(yīng)的抽象方法是abstract void beginText()和abstract void endText()。

beginText()標(biāo)志解析流程開始處理文本內(nèi)容,得到一個新的TextContent,壓入堆棧pageContentStack。 endText()標(biāo)志解析流程結(jié)束一段文本內(nèi)容,將beginText()處生成的TextContent 對象從pageContentStack 中彈出,將TextContent 對象加入頁內(nèi)容列表PageContentList 中。

使用了一個堆棧pageContentStack 來檢查當(dāng)前解析內(nèi)容的開始結(jié)束是否配對。 在beginText 處往堆棧中壓入一個TextContent 對象,那么在endText處從堆棧中彈出的對象類型必須是TextContent,否則說明解析過程的解析內(nèi)容產(chǎn)生了不一致。

同樣,對于圖像內(nèi)容實(shí)現(xiàn)beginImage( ) 和endImage()方法,對于表單對象應(yīng)實(shí)現(xiàn)beginAnnot()和endAnnot()方法。

頁內(nèi)容全部解析完成后,所有內(nèi)容對象(Page-Content)都存儲于隊(duì)列pageContentList 中,Page-Conent 的繼承類對應(yīng)了其類型,比如TextContent,ImageContent 等。

(2)記錄所有單元出現(xiàn)的位置及區(qū)域信息。

由于在比較模塊的需求中還需要比較對應(yīng)內(nèi)容的位置及大小,所以解析過程中還需要計(jì)算各個PageContent 的輪廓(Outline)信息。

這里仍然以文本內(nèi)容為例,在PageContentExtractor 中重載(Override) 了方法Protected void drawGlyph2D(),本方法負(fù)責(zé)得到一個字符的字形(Glyph)。

在drawGlyph2D 方法內(nèi),得到Glyph 的同時,記錄Glyph 的BoundingBox 信息,添加到TextContent 對象。 一個TextContent 對象可能包含多個字符,只需連接所有字符的BoundingBox 信息,就可以得到最終這個TextConent 的輪廓大小。

(3)記錄每個內(nèi)容單元在繪制時的繪制參數(shù)。

在每個內(nèi)容單元的繪制過程中,都有對應(yīng)的當(dāng)前繪制狀態(tài),包括字體、顏色、變換矩陣等。 程序在記錄內(nèi)容的同時,在每個PageContent 對象內(nèi)部記錄當(dāng)前的Graphics State。

完成解析工作之后,系統(tǒng)將會得到一個以PDF頁為單元的完整中間數(shù)據(jù)集合。

1.2.2 PDF 頁內(nèi)容分類

中間數(shù)據(jù)集合包含了PDF 文件的所有內(nèi)容,對數(shù)據(jù)集進(jìn)行分類并生成各類數(shù)據(jù)集以便于比較。設(shè)計(jì)比較器的輸入數(shù)據(jù)類PageThread,PageThead分析提取的內(nèi)容隊(duì)列pageContentList,生成用于比較的四個內(nèi)容集合:文本集合(TextThread)、圖像集合(ImageSet)、圖形集合(PathSet)、表單集合(AnnotSet)。

(1)文本

提取PDF 文檔中每一頁所包含的文本內(nèi)容,對頁內(nèi)的所有文本內(nèi)容按照文本位置從上到下,從左到右的方式進(jìn)行排序。 排序完成后,所有文本內(nèi)容形成一個文本串,根據(jù)文本樣式的變化將文本進(jìn)行分段。 針對每一段文本,記錄文本內(nèi)容,樣式表等相關(guān)信息,其中樣式信息包含字體、字號、顏色、顏色空間等,最終生成TextThread。

文本對比在本系統(tǒng)中是以單詞作為基本比較單元。 但PDF 文本內(nèi)容描述中不以單詞作為基本單元,是以單個字符出現(xiàn),只需要字符位置正確,PDF 打開后就可以得到正確的頁面展示。 所以在建立一個TextThread 的時候,還要加入智能分詞的功能。 本系統(tǒng)的基本分詞算法是:按照位置相近的原則將文本分區(qū)域,將頁內(nèi)的所有文本分塊,假定臨近的文本是處于同一段落;然后對每一區(qū)域內(nèi)的文本以空格和標(biāo)點(diǎn)符號分割,形成以詞為基本單元的結(jié)構(gòu)。 這樣處理的好處是復(fù)雜度低,易于實(shí)現(xiàn);不足之處是無法形成更有效的結(jié)構(gòu),比如不能知道文本是否在同一段落,或者不能知道文本是否在表格中。

(2)圖形

提取PDF 文檔中每一頁所包含的圖形內(nèi)容,記錄包括圖形路徑數(shù)據(jù)、畫筆模式、填充模式等,生成PathSet。

(3)圖像

提取PDF 文檔中每一頁所包含的圖像內(nèi)容,記錄圖像的特征參數(shù),包括圖像大小、圖像格式、圖像位數(shù)、顏色空間等信息,生成ImageSet。

(4)PDF 表單

PDF 表單在PDF 文件結(jié)構(gòu)里面是獨(dú)立于頁面描述的,除了分析提取表單本身屬性信息,包括表單類型、表單名稱、表單提示等,還需要分析提取表單內(nèi)容(Appearence)部分。 根據(jù)PDF 格式對表單的定義,表單內(nèi)容可以包括任意文本、圖形圖像,因此表單內(nèi)容部分包含以上三個部分的集合。 同時提取表單屬性及表單內(nèi)容生成AnnotSet。

2 PDF 內(nèi)容比較

2.1 文本內(nèi)容比較

對TextThread 進(jìn)行字符串比較(TextDiff)采用的是經(jīng)典Diff 算法最長公共子序列算法LCS(Longest Common Subsequence)。 LCS 最長公共子序列算法的基本原理是:用一個矩陣來記錄兩個字符串中所有位置的兩個字符之間的匹配情況,若是匹配則為1,否則為0。 然后求出對角線最長的1 的序列,其對應(yīng)的位置就是最長匹配子串的位置。

LCS 算法的開源實(shí)現(xiàn)有很多,系統(tǒng)選用了Google 的google-diff-match-patch 實(shí)現(xiàn),該算法用Java 實(shí)現(xiàn),性能優(yōu)秀,非常適合用于本系統(tǒng)需要的文本對比功能。

TextDiff 結(jié)束后,如果TextDiff 的結(jié)果為相同,則取當(dāng)前相同子字符串的位置,生成一個字符塊(TextLob)。 如果TextDiff 的結(jié)果為不相同,同樣生成一個TextLob,此處不相同的字符塊包含下列三種情況:

#INSERT:TestPDF 中的文本在BaselinePDF 中未找到。

#DELETE:BaselinePDF 中的文本在TestPDF中未找到。

#DIFFRENCE:TestPDF 中的文本在BaselinePDF 對應(yīng)位置的文本不相同。

經(jīng)過對TextDiff 的比較,頁內(nèi)的文本被劃分成為了一系列字符塊的集合。 對于內(nèi)容相同的TextLob,比較他們的樣式,發(fā)現(xiàn)不同則記錄為一條不同內(nèi)容(DiffContent);對于內(nèi)容不相同的TextLob,直接記錄一條DiffContent。

2.2 圖像比較

要實(shí)現(xiàn)對PDF 頁內(nèi)的圖像進(jìn)行比較,首先取圖像屬性信息進(jìn)行比較,對包括圖像大小、圖像字節(jié)數(shù)、圖像格式、像素位數(shù)、色彩空間等參數(shù)直接進(jìn)行比較,如果發(fā)現(xiàn)任何一項(xiàng)不同,則直接記錄一條

DiffContent。

如果以上所有比較都相同,則需要進(jìn)一步對比圖像的實(shí)際內(nèi)容。 首先,利用圖像數(shù)據(jù)生成對應(yīng)的Java2D BufferedImage 對象,然后對兩個BufferedImage 對象中的像素進(jìn)行逐一比對,發(fā)現(xiàn)不相同的像素則記錄一條DiffContent。

2.3 圖形比較

將PDF Graphics Path 轉(zhuǎn)換成Java2D General Path,然后利用Java2D Graphcis API 進(jìn)行比較。 對于比較結(jié)果不相同的圖形,記錄一條DiffContent,同時記錄當(dāng)前的Graphics State。

圖形比較部分只實(shí)現(xiàn)了直線(Line)的精確比較。 對于曲線圖形,采用將曲線轉(zhuǎn)成圖像的方式進(jìn)行圖像像素對比,如果圖像對比結(jié)果不相同,則曲線不相同。 這種方法好處是容易實(shí)現(xiàn);不足之處是無法指出曲線到底哪部分不一致。

2.4 PDF 表單比較

PDF 表單可以分為自身屬性部分和表單展現(xiàn)內(nèi)容部分,要實(shí)現(xiàn)對PDF 表單的比較,同樣需要進(jìn)行這兩部分的比較。

對于表單自身屬性部分,可以直接比較每一個屬性值,發(fā)現(xiàn)不同,則直接記錄一條DiffContent。

對于表單內(nèi)容部分,可能包括任意文本、圖形、圖像,所以表單比較器內(nèi)部就需要包含上述的文本、圖形、圖像比較器,比較后得到所有不相同的記錄。 如果記錄條數(shù)不為零,則記錄一條DiffContent,該DiffContent 可能包含表單內(nèi)容比較結(jié)果中的多個DiffContent。

根據(jù)內(nèi)容單元比較功能需求,設(shè)計(jì)一個頁比較的功能類PageContentComparator,該類內(nèi)部需要包含上述的四個內(nèi)容比較器。 內(nèi)容比較器可以抽象一個父類ContentCompartor,在該父類中定義一個抽象方法compare 方法,上述四個比較器都應(yīng)該是ContentComparator 的子類。 在每個子類中實(shí)現(xiàn)compare 方法,在該方法中完成比較功能。

3 測試及結(jié)論

針對本系統(tǒng)的特性,尤其針對PDF 文檔比較部分的特點(diǎn),選取有代表性的PDF 文件作為輸入文件Baseline。 利用PDF 生成庫通過編程方式對該文件做改變,生成測試文件Test,包括損壞文件、相同文件、刪除一段文字、增加一段文字、改變字體、顏色、大小、插入頁、插入空白頁、增加圖像、刪除圖像、改變圖形等。 以此測試用例的設(shè)計(jì)思路,建立了完善的測試用例集合。 經(jīng)過測試,系統(tǒng)生成文件可以明確指出文檔的區(qū)別和位置。

通常一個標(biāo)準(zhǔn)的動態(tài)內(nèi)容文檔生成系統(tǒng)每天都會生成大量的文檔,這就對本系統(tǒng)的性能提出了很高的要求。 因此,在進(jìn)行系統(tǒng)功能測試的同時,還對本系統(tǒng)進(jìn)行了相關(guān)的性能測試。 分別以多頁P(yáng)DF 文件、多個多頁P(yáng)DF 文件、文字密集型多個多頁P(yáng)DF 文件作為測試文件,測試系統(tǒng)比較一份PDF 文件所需時間,得出了比較理想的測試結(jié)果,平均處理一個PDF 標(biāo)準(zhǔn)頁的時間大約在100ms 以內(nèi);最極端的內(nèi)容密集型PDF 頁的平均處理時間大約在300ms 以內(nèi)。 完全能夠達(dá)到一個標(biāo)準(zhǔn)動態(tài)內(nèi)容文檔生成系統(tǒng)的測試要求。

雖然測試系統(tǒng)得到了有效的驗(yàn)證,但是在測試方法上還有很多需要改進(jìn)的地方。 如文本提取中分詞算法可以先采用OCR 預(yù)處理來判斷內(nèi)容結(jié)構(gòu);文本對比是基于英文字符實(shí)現(xiàn)的,如果是中文字符需要進(jìn)一步研究;圖形比較中對直線以外的圖形處理方式需要做進(jìn)一步研究。

猜你喜歡
表單文檔解析
淺談Matlab與Word文檔的應(yīng)用接口
移動App表單組件體驗(yàn)設(shè)計(jì)
有人一聲不吭向你扔了個文檔
輕松編輯PDF文檔
淺談網(wǎng)頁制作中表單的教學(xué)
睡夢解析儀
復(fù)合場中類拋體運(yùn)動解析
Word文檔 高效分合有高招
“Fe2+與Fe3+”相關(guān)解析
使用智能表單提高工作效率
西峡县| 儋州市| 凤庆县| 北海市| 南丹县| 开阳县| 卓尼县| 肇源县| 长治县| 长治市| 罗定市| 石柱| 宁远县| 连南| 垣曲县| 朝阳市| 麦盖提县| 凤台县| 交口县| 玉龙| 通州区| 文化| 壶关县| 平安县| 花莲县| 开平市| 嘉定区| 普格县| 青冈县| 迭部县| 南乐县| 千阳县| 广饶县| 张掖市| 济宁市| 甘泉县| 泰兴市| 马山县| 泸溪县| 栾川县| 青田县|