:基于 SAX 事件回調解析 XML(@nativescript/core/xml))
【免費下載鏈接】NativeScript? Write Native with TypeScript ? Best of all worlds (TypeScript, Swift, Objective C, Kotlin, Java, Dart). Use what you love ?? Angular, React, Solid, Svelte, Vue with: iOS (UIKit, SwiftUI), Android (View, Jetpack Compose), Flutter and you name it compatible.項目地址https://gitcode.com/gh_mirrors/na/NativeScript點擊查看免費下載本文圍繞 NativeScript 核心包中的nativescript/core/xml模塊展開系統(tǒng)講解如何使用其XmlParser一個基于 easysax 實現(xiàn)的非驗證型 SAX 解析器以事件驅動方式解析 XML 字符串。你將掌握模塊引入方式、ParserEventType五種事件類型、ParserEvent事件對象的完整字段、錯誤回調、實體引用自動解碼、命名空間處理以及底層解析原理與自動化測試的驗證方式。文中所有代碼與結論均來自當前倉庫的官方 How-To 文檔、源碼實現(xiàn)與測試用例可直接復制使用。從文檔到源碼Xml 模塊的定位apps/automated/src/xml-parser-tests/xml-parser.md是 NativeScript 官方文檔體系中關于 Xml 模塊的 How-To 入口文檔元數(shù)據(jù)中標注title: xml、description: Examples for using xml其正文由兩個代碼片段構成xml-module-snippet引入模塊與xml-parser-snippet解析 XML兩個片段的實際代碼分別定義在 xml-parser-tests.ts 和 xml-parser-tests.ts 中——NativeScript 的文檔采用片段即測試機制文檔引用的示例代碼本身就是可執(zhí)行的自動化測試從而保證文檔示例永遠與實現(xiàn)一致。模塊的真實實現(xiàn)位于 packages/core/xml/index.ts而 packages/core/xml/Readme.md 給出了準確定位Contains the XmlParser class, which is a SAX parser using the easysax implementation.也就是說XmlParser是一個使用 easysax 實現(xiàn)的 SAX 解析器與一次性構建整棵對象樹的 DOM 解析不同SAX 解析在掃描 XML 文本的過程中邊讀取邊觸發(fā)事件內存占用低、速度快非常適合解析結果需要即時消費的場景如 NativeScript 的 UI 模板解析。引入 Xml 模塊官方 How-To 片段xml-module-snippet展示了最基礎的引入方式CommonJSvar xmlModule require(nativescript/core/xml);在 TypeScript 項目中更推薦使用 ES 模塊導入與自動化測試 xml-parser-tests.ts 一致import * as xmlModule from nativescript/core/xml;引入后即可使用三個核心構件XmlParser—— SAX 解析器類ParserEventType—— 事件類型常量類ParserEvent—— 事件對象類。解析 XML事件驅動回調官方片段xml-parser-snippet即測試函數(shù)test_XmlParser_DummyDocumentationTest中的完整示例給出了解析 XML 的標準姿勢構造XmlParser時傳入事件回調onEventCallback與錯誤回調onErrorCallback然后調用parse(xmlString)開始解析var onEventCallback function (event: xmlModule.ParserEvent) { switch (event.eventType) { case xmlModule.ParserEventType.StartElement: var message event.eventType event.elementName; if (event.attributes) { message , Attributes:; for (var attributeName in event.attributes) { if (event.attributes.hasOwnProperty(attributeName)) { message attributeName event.attributes[attributeName] ; } } } //console.log(message); break; case xmlModule.ParserEventType.EndElement: //console.log(event.eventType event.elementName); break; case xmlModule.ParserEventType.Text: var significantText event.data.trim(); if (significantText ! ) { //console.log(event.eventType \ significantText \); } break; } }; var onErrorCallback function (error: Error) { console.log(Error: error.message); }; var xmlParser new xmlModule.XmlParser(onEventCallback, onErrorCallback); xmlParser.parse(DocumentFirst attr1attribute1 attr2attribute2I am first/FirstSecondI am second/Second/Document);官方注釋明確給出了這段代碼的預期控制臺輸出可以作為自測基準StartElement Document StartElement First, Attributes: attr1 attribute1 attr2 attribute2 Text I am first EndElement First StartElement Second Text I am second EndElement Second EndElement Document注意示例中的處理技巧Text事件先用trim()過濾掉文檔格式化產(chǎn)生的空白字符換行、縮進只對有效文本做處理StartElement事件中先判斷event.attributes是否存在再遍歷屬性這是因為無屬性的元素不會上報屬性見下文測試驗證。ParserEventType五種事件類型ParserEventType定義在 index.ts是一個靜態(tài)常量類事件類型為字符串字面量常量值觸發(fā)時機ParserEventType.StartElementStartElement遇到元素開始標簽ParserEventType.EndElementEndElement遇到元素結束標簽ParserEventType.TextText元素內的文本內容ParserEventType.CDATACDATA遇到![CDATA[...]]塊ParserEventType.CommentComment遇到!-- ... --注釋從集成測試資源 xml.xml 與預期輸出 xml.expected 可以看到CDATA 與 Comment 都會獨立產(chǎn)生事件CDATA 內的 JavaScript 代碼片段、多行注釋均以data形式原樣交付且事件序列嚴格按文檔順序排列。ParserEvent事件對象詳解每次事件觸發(fā)時回調收到的ParserEvent對象定義在 index.ts包含以下字段屬性類型說明eventTypestring事件類型取值為ParserEventType五個成員之一positionPosition事件在 XML 字符串中的位置{ line, column }均從 1 開始計數(shù)prefixstring開啟命名空間處理后元素的前綴如a1:Element中的a1僅 StartElement / EndElement 有效namespacestring開啟命名空間處理后解析出的命名空間 URI僅 StartElement / EndElement 有效elementNamestring元素名開啟命名空間處理時為去除前綴后的本地名僅 StartElement / EndElement 有效attributesObjectStartElement 事件的屬性字典無屬性時該值為undefineddatastringText / CDATA / Comment 事件攜帶的文本數(shù)據(jù)toString()string返回該事件的 JSON 字符串表示含全部字段其中position的精確行號與列號定位能力使開發(fā)者可以在出錯或調試時快速回溯到 XML 原文的對應位置toString()則為日志與斷言提供了結構化輸出集成測試正是依賴它逐字符比對事件序列。XmlParser的構造簽名見 index.ts為constructor(onEvent: (event: ParserEvent) void, onError?: (error: Error, position: Position) void, processNamespaces?: boolean)三個參數(shù)的含義onEvent必填每個解析事件都會調用onError可選解析出錯時調用回調同時收到Error對象與出錯位置positionprocessNamespaces可選是否啟用命名空間處理默認不啟用。錯誤處理畸形 XML 會觸發(fā) onError當 XML 結構非法時例如開始標簽與結束標簽不匹配解析器不會拋出未捕獲異常而是調用onErrorCallback。實現(xiàn)位于 index.tsif (onError) { this._parser.on(error, function (msg, pos) { onError(new Error(msg), pos()); }); }對應測試test_XmlParser_OnErrorIsCalledWhenAnErrorOccursxml-parser-tests.ts用element/otherElement這種標簽錯配的輸入驗證了錯誤回調必然被調用。同時注意如果構造時未傳入onError則錯誤回調不會被注冊——因此生產(chǎn)代碼建議始終提供錯誤回調。實體引用自動解碼XmlParser會對文本內容與屬性值中的實體引用自動解碼無需開發(fā)者手動處理。核心正則定義在 index.tsconst _entitySearchRegEx /#(\d);|#x([0123456789abcdef]);|(\w);/gi;它覆蓋三類實體十進制數(shù)值實體#38;形式十六進制數(shù)值實體#x26;形式命名實體lt;、gt;、quot;、amp;、apos;等由一個覆蓋數(shù)百個命名實體的大映射表_generateAmpMap含 Latin-1、希臘字母、標點、貨幣符號等解析未知命名實體按原樣保留。測試用例給出了完整的驗證矩陣文本內容解碼xml-parser-tests.tselementlt;gt;quot;amp;apos;/element解析出文本屬性值解碼xml-parser-tests.tsLabel textlt;gt;quot;amp;apos;/中屬性text的值為Unicode 實體xml-parser-tests.ts#x1f923;#x2713;被正確解碼為 emoji 與 ?文本與屬性值均適用。從源碼看屬性值在startNode事件中逐屬性調用_dereferenceEntities解碼index.ts文本內容則先解碼實體再交給回調index.ts。命名空間處理當構造時傳入第三個參數(shù)trueprocessNamespaces時解析器會維護一個命名空間棧對元素的前綴進行解析并在事件中暴露prefix與namespace字段。相關實現(xiàn)包括_getNamespacesStackEntryindex.ts收集元素的xmlns/xmlns:xx屬性構建當前作用域的命名空間映射_resolveNamespaceindex.ts將prefix:name形式的元素名拆分為前綴與本地名并從命名空間棧頂向下查找最近聲明的前綴綁定棧的壓入與彈出StartElement 時壓入、EndElement 時彈出index.tsparse開始時棧被重置index.ts。測試資源 xml-with-namespaces.xml 演示了完整的命名空間語義Element xmlnshttp://a-default xmlns:a1http://a1 xmlns:a2http://a2 xmlns:duplicatehttp://a-duplicate expected-namespacehttp://a-default Element expected-namespacehttp://a-default/ a1:Element expected-namespacehttp://a1/ a2:Element expected-namespacehttp://a2/ Element xmlnshttp://b-default xmlns:b1http://b1 xmlns:b2http://b2 xmlns:duplicatehttp://b-duplicate expected-namespacehttp://b-default ...對應測試test_XmlParser_NamespacesTestxml-parser-tests.ts對每個 StartElement 斷言event.namespace等于其expected-namespace屬性。該用例至少驗證了三個關鍵行為默認命名空間無前綴元素解析為最近聲明的默認命名空間http://a-default/http://b-default前綴綁定a1:Element解析為http://a1b1:Element解析為http://b1前綴遮蔽shadowing內層元素重新聲明duplicate前綴后其解析結果從外層的http://a-duplicate變?yōu)閮葘拥膆ttp://b-duplicate——這正是命名空間棧從頂向下查找設計的意義。底層原理EasySAX 非驗證型 SAX 解析器XmlParser內部將工作委托給EasySAXParser實例化于 index.ts類型聲明見 easysax.d.ts源碼注釋明確標注其來源與版本A simple non-validating SAX parser based on easysax version 0.1.14該第三方庫以純 JavaScript 實現(xiàn)easysax.js其自帶說明 README.md 揭示了設計取向這是一個只解析需要的、盡可能快的 SAX 風格解析器非流式、要求整個 XML 一次性載入內存不適合處理巨型文件并內置了命名空間處理機制——這與XmlParser的 API 設計完全吻合parse(xmlString)接收完整字符串事件回調同步觸發(fā)。XmlParser在EasySAXParser之上做了四層封裝將 easysax 的startNode/textNode/endNode/cdata/comment/error原生事件轉換為統(tǒng)一的ParserEvent對象含position定位修復底層細節(jié)easysax 在元素無屬性時會返回字面量trueXmlParser將其歸一化為undefined見 index.ts統(tǒng)一完成實體引用的解碼文本與屬性值在需要時疊加命名空間棧解析。此外XmlParser還暴露了一個angularSyntax布爾屬性getter/setter 透傳到底層解析器見 index.ts用于控制對 Angular 風格模板語法的解析行為這說明該解析器在 NativeScript 生態(tài)中同時承擔著框架模板解析的底層職責。測試驗證與實戰(zhàn)集成單元級行為驗證apps/automated/src/xml-parser-tests/xml-parser-tests.ts 通過TKUnit斷言框架覆蓋了本文前述的所有行為可歸納為一張驗證清單測試函數(shù)驗證點test_XmlParser_IsDefined/test_ParserEventType_IsDefinedXmlParser與ParserEventType均可用test_XmlParser_ElementsWithoutAttributesDoNotReportThem無屬性元素的attributes為undefinedtest_XmlParser_EntityReferencesAreDecoded文本內命名實體解碼test_XmlParser_EntityReferencesInAttributeValuesAreDecoded屬性值內命名實體解碼test_XmlParser_UnicodeEntitiesAreDecoded文本內十六進制 Unicode 實體解碼test_XmlParser_UnicodeEntitiesInAttributeValuesAreDecoded屬性值內十六進制 Unicode 實體解碼test_XmlParser_OnErrorIsCalledWhenAnErrorOccurs標簽錯配觸發(fā)錯誤回調test_XmlParser_IntegrationTest用 xml.xml 解析并與 xml.expected 逐字符比對跳過空白 Texttest_XmlParser_NamespacesTest命名空間解析與前綴遮蔽test_MultiParserTemplate以 XML 字符串驅動 UI 構建其中集成測試xml-parser-tests.ts最有參考價值它從應用資源中讀取真實 XML 文件、用XmlParser解析、將每個非空白事件序列化為字符串再與官方預期的 JSON 事件流逐字符比對——這份 xml.expected 本身就是一個極佳的事件流教學樣例展示了屬性、嵌套元素、混合內容Pre-Text Inline.../Inline Post-text.、實體、CDATA、注釋在事件序列中的真實形態(tài)。與 UI 構建器的集成test_MultiParserTemplatexml-parser-tests.ts展示了 XML 解析在 NativeScript 中最典型的業(yè)務場景——UI 模板解析它加載 itemTemplates.xml一個包含TabView、ListView.itemTemplates與template keyfoo的完整頁面片段交給nativescript/core/ui/builder的Builder.parse直接生成視圖對象并斷言items長度為 1。這印證了掌握XmlParser的事件模型也就理解了 NativeScript 聲明式 UI 模板解析機制的底層基礎。小結nativescript/core/xml的XmlParser為 NativeScript 應用提供了輕量、同步、事件驅動的 XML 解析能力事件類型只有五種StartElement/EndElement/Text/CDATA/Comment事件對象ParserEvent攜帶類型、位置、元素名、屬性、文本等結構化信息文本與屬性中的實體引用含 Unicode 實體自動解碼錯誤通過可選回調上報通過processNamespaces參數(shù)可啟用完整的命名空間解析含默認命名空間與前綴遮蔽底層基于非流式、非驗證型的 easysax 解析器要求 XML 整體載入內存適合 UI 模板、配置文件等中小規(guī)模文檔的即時解析。如需繼續(xù)深入可直接研讀實現(xiàn)源碼 packages/core/xml/index.ts、底層庫 packages/core/js-libs/easysax/easysax.js以及測試與文檔三件套 xml-parser-tests.ts、xml-parser.md 和 xml-with-namespaces.xml。贊分享【免費下載鏈接】NativeScript? Write Native with TypeScript ? Best of all worlds (TypeScript, Swift, Objective C, Kotlin, Java, Dart). Use what you love ?? Angular, React, Solid, Svelte, Vue with: iOS (UIKit, SwiftUI), Android (View, Jetpack Compose), Flutter and you name it compatible.項目地址https://gitcode.com/gh_mirrors/na/NativeScript點擊查看免費下載相關推薦Kubernetes Contributor Summit 內容策劃完全指南Events Content 子團隊角色體系與實戰(zhàn)手冊解析Kubernetes Contributor Summit 內容策劃完全指南Events Content 子團隊角色體系與實戰(zhàn)手冊解析 導讀 本指南以 KubFeign SAX Decoder 實戰(zhàn)指南用 SAX 流式解析 XML 響應Feign SAX Decoder 實戰(zhàn)指南用 SAX 流式解析 XML 響應 導讀 feign sax 是 Feign 生態(tài)中專門用于 XML 響應解碼的模后端API設計TBOOX/TBOX XML讀取器SAX風格的流式XML解析TBOOX/TBOX XML讀取器SAX風格的流式XML解析 引言告別內存瓶頸擁抱流式XML解析 在傳統(tǒng)XML處理中DOMDocument Objec后端上一篇Gradle Doctor終極指南快速解決Android構建中的Jetifier警告與多模塊項目優(yōu)化下一篇大麥網(wǎng)搶票腳本到底怎么買到票創(chuàng)作聲明:本文部分內容由AI輔助生成(AIGC),僅供參考