第二十八章 定制SAX解析器創(chuàng)建自定義內(nèi)容處理程序
創(chuàng)建自定義內(nèi)容處理程序
如果直接調(diào)用InterSystems IRIS SAX解析器更振,則可以根據(jù)自己的需要?jiǎng)?chuàng)建自定義內(nèi)容處理程序至非。本節(jié)討論以下主題:
- Overview
- 要在內(nèi)容處理程序中自定義的方法的描述
-
%XML.SAX.Parser
類中解析方法的參數(shù)列表摘要 - 示例
創(chuàng)建自定義內(nèi)容處理程序概述
要定制InterSystems IRIS SAX解析器導(dǎo)入和處理XML的方式恤筛,請(qǐng)創(chuàng)建并使用定制的SAX內(nèi)容處理程序。具體地說萌丈,創(chuàng)建%XML.SAX.ContentHandler
的子類。然后踪少,在新類中廊佩,重寫任何默認(rèn)方法以執(zhí)行所需的操作拴还。在解析XML文檔時(shí)使用新的內(nèi)容處理程序作為參數(shù);為此,需要使用%XML.SAX.Parser
類的解析方法根吁。
此操作如下圖所示:
創(chuàng)建和使用自定義導(dǎo)入機(jī)制的過程如下:
- 創(chuàng)建擴(kuò)展
%XML.SAX.ContentHandler
的類员淫。 - 在該類中,包括希望覆蓋的方法击敌,并根據(jù)需要提供新定義介返。
- 在使用
%XML.SAX.Parser
的分析方法之一(即ParseFile()
、ParseStream()
沃斤、ParseString()
或ParseURL()
)編寫讀取XML文檔的類方法映皆。
調(diào)用分析方法時(shí),請(qǐng)將自定義內(nèi)容處理程序指定為參數(shù)轰枝。
SAX內(nèi)容處理程序的可定制方法
%XML.SAX.ContentHandler
類在特定時(shí)間自動(dòng)執(zhí)行某些方法捅彻。通過覆蓋它們,您可以自定義內(nèi)容處理程序的行為鞍陨。
響應(yīng)事件
%XML.SAX.ContentHandle
類分析XML文件步淹,并在它到達(dá)XML文件中的特定點(diǎn)時(shí)生成事件。根據(jù)事件的不同诚撵,會(huì)執(zhí)行不同的方法缭裆。這些方法如下:
-
OnPostParse()
— 在XML解析完成時(shí)觸發(fā)。 -
characters()
— 由字符數(shù)據(jù)觸發(fā)寿烟。 -
comment()
— 注釋觸發(fā) -
endCData()
—由CDATA部分的末尾觸發(fā)澈驼。 -
endDocument()
—由文檔結(jié)尾觸發(fā)。 -
endDTD()
— 由DTD結(jié)束觸發(fā)筛武。 -
endElement()
—由元素的末尾觸發(fā)缝其。 -
endEntity()
— 由一個(gè)實(shí)體的終結(jié)觸發(fā)。 -
endPrefixMapping()
— 由名稱空間前綴映射的結(jié)束觸發(fā)徘六。 -
ignorableWhitespace()
— 由元素內(nèi)容中的可忽略空格觸發(fā)内边。 -
processingInstruction()
— 由XML處理指令觸發(fā)待锈。 -
skippedEntity()
— 被跳過的實(shí)體觸發(fā)。 -
startCData()
—由CDATA部分的開頭觸發(fā)竿音。 -
startDocument()
— 由文檔的開頭觸發(fā)。 -
startDTD()
— 由DTD的開頭觸發(fā)春瞬。 -
startElement()
— 由元素的開始觸發(fā)。 -
startEntity()
— 由一個(gè)實(shí)體的開始觸發(fā)快鱼。 -
startPrefixMapping()
— 由名稱空間前綴映射的開始觸發(fā)颠印。
默認(rèn)情況下纲岭,這些方法是空的线罕,可以在自定義內(nèi)容處理程序中覆蓋它們止潮。
處理錯(cuò)誤
%XML.SAX.ContentHandler
類在遇到某些錯(cuò)誤時(shí)也會(huì)執(zhí)行方法:
-
error()
— 由可恢復(fù)的解析器錯(cuò)誤觸發(fā)。 -
fatalError()
— 由致命的XML解析錯(cuò)誤觸發(fā)钞楼。 -
warning()
— 由解析器警告通知觸發(fā)喇闸。
默認(rèn)情況下,這些方法為空询件,可以在自定義內(nèi)容處理程序中重寫它們燃乍。
計(jì)算事件掩碼
當(dāng)調(diào)用InterSystems IRIS SAX解析器(通過%XML.SAX.Parser
類)時(shí),可以指定一個(gè)掩碼參數(shù)來指示哪些回調(diào)是感興趣的宛琅。如果未指定掩碼參數(shù)刻蟹,解析器將調(diào)用內(nèi)容處理程序的Mask()
方法。此方法返回一個(gè)整數(shù)嘿辟,該整數(shù)指定與內(nèi)容處理程序的重寫方法相對(duì)應(yīng)的復(fù)合掩碼舆瘪。
例如,假設(shè)創(chuàng)建了一個(gè)自定義內(nèi)容處理程序红伦,其中包含startElement()
和endElement()
方法的新版本英古。在本例中,Mask()
方法返回一個(gè)數(shù)值昙读,該數(shù)值等于$$$SAXSTARTELEMENT
和$$$SAXENDELEMENT
,之和召调,這兩個(gè)標(biāo)志對(duì)應(yīng)于這兩個(gè)事件。如果沒有為解析方法指定掩碼參數(shù)蛮浑,則解析器將調(diào)用內(nèi)容處理程序的Mask()
方法唠叛,因此只處理這兩個(gè)事件。
其他有用的方法
%XML.SAX.ContentHandler
類提供在特殊情況下有用的其他方法:
-
LocatePosition()
-通過引用返回兩個(gè)參數(shù)陵吸,這兩個(gè)參數(shù)指示解析的文檔中的當(dāng)前位置玻墅。第一個(gè)表示行號(hào)介牙,第二個(gè)表示行偏移壮虫。 -
PushHandler()
-在堆棧上推送新的內(nèi)容處理程序。SAX的所有后續(xù)回調(diào)都將轉(zhuǎn)到這個(gè)新的內(nèi)容處理程序环础,直到該處理程序完成處理囚似。
如果在解析一種類型的文檔時(shí)遇到想要以不同方式解析的一段XML,則可以使用此方法线得。在本例中饶唤,當(dāng)檢測(cè)到要以不同方式處理的段時(shí),調(diào)用PushHandler()
方法贯钩,該方法將創(chuàng)建一個(gè)新的內(nèi)容處理程序?qū)嵗伎瘛K谢卣{(diào)都會(huì)轉(zhuǎn)到此內(nèi)容處理程序办素,直到調(diào)用PopHandler()
返回上一個(gè)內(nèi)容處理程序祸穷。
-
PopHandler()
-返回堆棧上的上一個(gè)內(nèi)容處理程序。
這些是final
方法需曾,不能重寫祈远。
SAX解析方法的參數(shù)列表
要指定文檔源车份,請(qǐng)使用%XML.SAX.Parser
類的ParseFile()
、ParseStream()
逃顶、ParseString()
或ParseURL()
方法充甚。在任何情況下伴找,源文檔都必須是格式良好的XML文檔;也就是說抖誉,它必須遵守XML語法的基本規(guī)則袒炉。完整的參數(shù)列表按順序如下:
pFilename, pStream, pString, or pURL — 文檔源.
pHandler — 內(nèi)容處理程序我磁,它是
%XML.SAX.ContentHandler
類的實(shí)例夺艰。pResolver — 分析源時(shí)使用的實(shí)體解析器沉衣。
pFlags — 用于控制SAX解析器執(zhí)行的驗(yàn)證和處理的標(biāo)志豌习。
pMask — 用于指定XML源中感興趣的項(xiàng)的掩碼拔疚。通常不需要指定此參數(shù)草雕,因?yàn)閷?duì)于
%XML.SAX.Parser
的解析方法墩虹,默認(rèn)掩碼為0
诫钓。這意味著解析器調(diào)用內(nèi)容處理程序的Mask()
方法篙螟。該方法通過檢測(cè)(在編譯期間)在事件處理程序中自定義的所有事件回調(diào)來計(jì)算掩碼遍略。只處理那些事件回調(diào)。pSchemaSpec — 驗(yàn)證文檔源所依據(jù)的架構(gòu)規(guī)范下愈。此參數(shù)是一個(gè)字符串势似,其中包含以逗號(hào)分隔的命名空間/URL對(duì)列表:
"namespace URL,namespace URL"
這里履因,Namespace
是用于模式的XML名稱空間栅迄,URL
是提供模式文檔位置的URL
皆怕。名稱空間和URL
值之間有一個(gè)空格字符端逼。
pHttpRequest (For the ParseURL() method only) — 這里,
Namespace
是用于模式的XML名稱空間,URL是提供模式文檔位置的URL礁鲁。名稱空間和URL值之間有一個(gè)空格字符。pSSLConfiguration — 客戶端
SSL/TLS
配置的配置名稱冗美。
注意:請(qǐng)注意析二,此參數(shù)列表與%XML.TextReader
類的解析方法略有不同叶摄。有一點(diǎn)不同,%XML.TextReader
不提供指定自定義內(nèi)容處理程序的選項(xiàng)宵喂。
SAX處理程序示例
想要一個(gè)文件中出現(xiàn)的所有XML元素的列表。要做到這一點(diǎn)锅棕,只需記錄每個(gè)開始元素淌山。那么這個(gè)過程是這樣的:
- 創(chuàng)建一個(gè)名為
MyApp.Handler
的類泼疑,它擴(kuò)展%XML.SAX.ContentHandler
:
Class MyApp.Handler Extends %XML.SAX.ContentHandler
{
}
- 使用以下內(nèi)容覆蓋
startElement()
方法:
Class MyApp.MyHandler extends %XML.SAX.ContentHandler
{
// ...
Method startElement(uri as %String, localname as %String,
qname as %String, attrs as %List)
{
//we have found an element
write !,"Element: ",localname
}
}
- 將一個(gè)類方法添加到讀取和分析外部文件的Handler類:
Class MyApp.MyHandler extends %XML.SAX.ContentHandler
{
// ...
ClassMethod ReadFile(file as %String) as %Status
{
//create an instance of this class
set handler=..%New()
//parse the given file using this instance
set status=##class(%XML.SAX.Parser).ParseFile(file,handler)
//quit with status
quit status
}
}
請(qǐng)注意王浴,這是一個(gè)類方法,因?yàn)樗趹?yīng)用程序中被調(diào)用以執(zhí)行其處理秒裕。此方法執(zhí)行以下操作:
- 它創(chuàng)建內(nèi)容處理程序?qū)ο蟮膶?shí)例:
set handler=..%New()
- 它在一個(gè)調(diào)用
%XML.SAX.Parser
的ParseFile()
方法几蜻。這將驗(yàn)證并解析文檔(由fileName
指定)体斩,并調(diào)用內(nèi)容處理程序?qū)ο蟮母鞣N事件處理方法:
set status=##class(%XML.SAX.Parser).ParseFile(file,handler)
每次在解析器解析文檔時(shí)發(fā)生事件(如開始或結(jié)束元素)時(shí)絮吵,解析器都會(huì)調(diào)用內(nèi)容處理程序?qū)ο笾械倪m當(dāng)方法。在本例中暇昂,唯一被覆蓋的方法是startElement()
,它隨后寫出元素名稱从铲。對(duì)于其他事件名段,例如到達(dá)End
元素泣懊,不會(huì)發(fā)生任何事情(默認(rèn)行為)。
當(dāng)
ParseFile()
方法到達(dá)文件末尾時(shí)自娩,它返回忙迁。處理程序?qū)ο蟪鲎饔糜蛩槟耍⒆詣?dòng)從內(nèi)存中刪除。在應(yīng)用程序中的相應(yīng)點(diǎn)恰梢,調(diào)用
ReadFile()
方法嵌言,將文件傳遞給解析:
Do ##class(Samples.MyHandler).ReadFile(filename)
其中及穗,filename是正在讀取的文件的路徑。
例如苛白,如果文件的內(nèi)容如下:
<?xml version="1.0" encoding="UTF-8"?>
<Root>
<Person>
<Name>Edwards,Angela U.</Name>
<DOB>1980-04-19</DOB>
<GroupID>K8134</GroupID>
<HomeAddress>
<City>Vail</City>
<Zip>94059</Zip>
</HomeAddress>
<Doctors>
<Doctor>
<Name>Uberoth,Wilma I.</Name>
</Doctor>
<Doctor>
<Name>Wells,George H.</Name>
</Doctor>
</Doctors>
</Person>
</Root>
則此示例的輸出如下所示:
Element: Root
Element: Person
Element: Name
Element: DOB
Element: GroupID
Element: HomeAddress
Element: City
Element: Zip
Element: Doctors
Element: Doctor
Element: Name
Element: Doctor
Element: Name
使用HTTPS
%XML.SAX.Parser
支持HTTPS
购裙。也就是說躏率,可以使用此類執(zhí)行以下操作:
- (對(duì)于
ParseURL()
)解析HTTPS
位置提供的XML文檔。 - (對(duì)于所有解析方法)解析
HTTPS
位置的實(shí)體私股。
在所有情況下恩掷,如果這些項(xiàng)目中的任何一個(gè)是在HTTPS
位置上提供的黄娘,請(qǐng)執(zhí)行以下操作:
- 使用管理門戶創(chuàng)建包含所需連接詳細(xì)信息的
SSL/TLS
配置逼争。這是一次性的步驟劝赔。 - 調(diào)用
%XML.SAX.Parser
的適用解析方法時(shí)着帽,請(qǐng)指定pSSLConfiguration
參數(shù)。
默認(rèn)情況下赫粥,InterSystems IRIS使用Xerces
圖元解析予借。%XML.SAX.Parser
僅在以下情況下使用其自己的實(shí)體解析:
-
PSSLConfiguration
參數(shù)非空灵迫。 - 已配置代理服務(wù)器。