第二十八章 定制SAX解析器創(chuàng)建自定義內(nèi)容處理程序

第二十八章 定制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類的解析方法根吁。

此操作如下圖所示:

image.png

創(chuàng)建和使用自定義導(dǎo)入機(jī)制的過程如下:

  1. 創(chuàng)建擴(kuò)展%XML.SAX.ContentHandler的類员淫。
  2. 在該類中,包括希望覆蓋的方法击敌,并根據(jù)需要提供新定義介返。
  3. 在使用%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ù)列表按順序如下:

  1. pFilename, pStream, pString, or pURL — 文檔源.

  2. pHandler — 內(nèi)容處理程序我磁,它是%XML.SAX.ContentHandler類的實(shí)例夺艰。

  3. pResolver — 分析源時(shí)使用的實(shí)體解析器沉衣。

  4. pFlags — 用于控制SAX解析器執(zhí)行的驗(yàn)證和處理的標(biāo)志豌习。

  5. 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)。

  6. pSchemaSpec — 驗(yàn)證文檔源所依據(jù)的架構(gòu)規(guī)范下愈。此參數(shù)是一個(gè)字符串势似,其中包含以逗號(hào)分隔的命名空間/URL對(duì)列表:

"namespace URL,namespace URL"

這里履因,Namespace是用于模式的XML名稱空間栅迄,URL是提供模式文檔位置的URL皆怕。名稱空間和URL值之間有一個(gè)空格字符端逼。

  1. pHttpRequest (For the ParseURL() method only) — 這里,Namespace是用于模式的XML名稱空間,URL是提供模式文檔位置的URL礁鲁。名稱空間和URL值之間有一個(gè)空格字符。

  2. 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è)過程是這樣的:

  1. 創(chuàng)建一個(gè)名為MyApp.Handler的類泼疑,它擴(kuò)展%XML.SAX.ContentHandler
Class MyApp.Handler Extends %XML.SAX.ContentHandler
{
}
  1. 使用以下內(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
}

}
  1. 將一個(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í)行以下操作:

  1. 它創(chuàng)建內(nèi)容處理程序?qū)ο蟮膶?shí)例:
    set handler=..%New()
  1. 它在一個(gè)調(diào)用%XML.SAX.ParserParseFile()方法几蜻。這將驗(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)行為)。

  1. 當(dāng)ParseFile()方法到達(dá)文件末尾時(shí)自娩,它返回忙迁。處理程序?qū)ο蟪鲎饔糜蛩槟耍⒆詣?dòng)從內(nèi)存中刪除。

  2. 在應(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í)行以下操作:

  1. 使用管理門戶創(chuàng)建包含所需連接詳細(xì)信息的SSL/TLS配置逼争。這是一次性的步驟劝赔。
  2. 調(diào)用%XML.SAX.Parser的適用解析方法時(shí)着帽,請(qǐng)指定pSSLConfiguration參數(shù)。

默認(rèn)情況下赫粥,InterSystems IRIS使用Xerces圖元解析予借。%XML.SAX.Parser僅在以下情況下使用其自己的實(shí)體解析:

  • PSSLConfiguration參數(shù)非空灵迫。
  • 已配置代理服務(wù)器。
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末挣跋,一起剝皮案震驚了整個(gè)濱河市浆劲,隨后出現(xiàn)的幾起案子哀澈,更是在濱河造成了極大的恐慌,老刑警劉巖膨报,帶你破解...
    沈念sama閱讀 218,122評(píng)論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件现柠,死亡現(xiàn)場(chǎng)離奇詭異够吩,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)强法,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,070評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門饮怯,熙熙樓的掌柜王于貴愁眉苦臉地迎上來蓖墅,“玉大人临扮,你說我怎么就攤上這事∧茨遥” “怎么了靶橱?”我有些...
    開封第一講書人閱讀 164,491評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵关霸,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我膘掰,道長(zhǎng)识埋,這世上最難降的妖魔是什么零渐? 我笑而不...
    開封第一講書人閱讀 58,636評(píng)論 1 293
  • 正文 為了忘掉前任诵盼,我火速辦了婚禮,結(jié)果婚禮上洁墙,老公的妹妹穿的比我還像新娘热监。我一直安慰自己,他們只是感情好羹呵,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,676評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著盈简,像睡著了一般太示。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上臼勉,一...
    開封第一講書人閱讀 51,541評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音膏蚓,去河邊找鬼驮瞧。 笑死,一個(gè)胖子當(dāng)著我的面吹牛采郎,可吹牛的內(nèi)容都是我干的狂魔。 我是一名探鬼主播,決...
    沈念sama閱讀 40,292評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼理茎,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了朗鸠?” 一聲冷哼從身側(cè)響起烛占,我...
    開封第一講書人閱讀 39,211評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤忆家,失蹤者是張志新(化名)和其女友劉穎芽卿,沒想到半個(gè)月后胳搞,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體肌毅,經(jīng)...
    沈念sama閱讀 45,655評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡呜舒,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,846評(píng)論 3 336
  • 正文 我和宋清朗相戀三年袭蝗,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了呻袭。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片左电。...
    茶點(diǎn)故事閱讀 39,965評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖闰蚕,靈堂內(nèi)的尸體忽然破棺而出没陡,到底是詐尸還是另有隱情索赏,我是刑警寧澤潜腻,帶...
    沈念sama閱讀 35,684評(píng)論 5 347
  • 正文 年R本政府宣布,位于F島的核電站精钮,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏忽你。R本人自食惡果不足惜檀夹,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,295評(píng)論 3 329
  • 文/蒙蒙 一娜亿、第九天 我趴在偏房一處隱蔽的房頂上張望买决。 院中可真熱鬧沛婴,春花似錦、人聲如沸督赤。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,894評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽躲舌。三九已至丑婿,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間没卸,已是汗流浹背羹奉。 一陣腳步聲響...
    開封第一講書人閱讀 33,012評(píng)論 1 269
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留约计,地道東北人诀拭。 一個(gè)月前我還...
    沈念sama閱讀 48,126評(píng)論 3 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像煤蚌,于是被迫代替她去往敵國(guó)和親筒占。 傳聞我的和親對(duì)象是個(gè)殘疾皇子插勤,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,914評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容