• 
    

    
    

      99热精品在线国产_美女午夜性视频免费_国产精品国产高清国产av_av欧美777_自拍偷自拍亚洲精品老妇_亚洲熟女精品中文字幕_www日本黄色视频网_国产精品野战在线观看

      ?

      基于QT的XML文件自動(dòng)轉(zhuǎn)換方法

      2021-03-09 01:34:52王宏明林衛(wèi)永王泉榮溫業(yè)中
      鐵路通信信號工程技術(shù) 2021年2期
      關(guān)鍵詞:示例實(shí)例文檔

      王宏明,林衛(wèi)永,王泉榮,溫業(yè)中

      (通號萬全信號設(shè)備有限公司,杭州 310000)

      XML 是一種廣泛使用的具有結(jié)構(gòu)性和自描述性的標(biāo)記語言,在有軌電車領(lǐng)域的工程建模、配置文件、數(shù)據(jù)交換等功能上常被使用。由于軌道交通領(lǐng)域的安全、效率等要求,C/C++語言常當(dāng)做實(shí)現(xiàn)語言。但是由于C++語言缺少java、C#等高級語言的反射特性,將XML 文件讀取到系統(tǒng)內(nèi)部,轉(zhuǎn)換為計(jì)算機(jī)能夠理解的對象時(shí),沒有自動(dòng)轉(zhuǎn)換的方法,實(shí)現(xiàn)比較繁瑣,代碼中充斥著if、else 等判斷,代碼的可維護(hù)性、可擴(kuò)展性都比較差。在將C++對象寫入到XML 文件時(shí),也需要通過定義一大堆的字符串來寫到XML 文件中,代碼的可維護(hù)性,可擴(kuò)展性都不夠好。文獻(xiàn)[1]通過Java 來實(shí)現(xiàn)了XML到編程語言的轉(zhuǎn)換,將XML 元素對應(yīng)到定義好的Java 類中,但是對于如何具體實(shí)現(xiàn)XML 節(jié)點(diǎn)到Java 屬性的載入沒有涉及。文獻(xiàn)[2]對于XML 和數(shù)據(jù)庫的對象模型的轉(zhuǎn)換數(shù)學(xué)算法進(jìn)行了闡述,也沒有對如何實(shí)現(xiàn)該機(jī)制進(jìn)行詳細(xì)的描述。文獻(xiàn)[3]對于如何將一個(gè)定義好的結(jié)構(gòu)體輸出到XML 文件中進(jìn)行研究,但是缺少通用性。

      本文提出一種基于QT 的XML 文件自動(dòng)轉(zhuǎn)換的方法,只需要定義好類的數(shù)據(jù)結(jié)構(gòu),就能夠自動(dòng)的將符合要求的XML 載入進(jìn)來,同時(shí)也能將C++對象按照數(shù)據(jù)結(jié)構(gòu)定義,以XML 格式保存。

      1 XML文檔分析

      以有軌電車的軟件領(lǐng)域經(jīng)常用到的XML 配置文件為例來進(jìn)行說明。

      對于該文檔,可以得到一個(gè)XML 模式定義D,按照文獻(xiàn)[4]的五元組定義進(jìn)行分析,可以得到文檔樹,如圖1 所示。

      圖1 XML文檔樹Fig.1 XML file tree

      對示例文檔對象分析,可知,該文檔需要3 個(gè)C++類進(jìn)行對應(yīng)。使用UML 圖來表示3 個(gè)類及關(guān)系,如圖2 所示。

      圖2 UML類圖Fig.2 UML class diagram

      2 C++及QT結(jié)合的動(dòng)態(tài)生成對象原理

      對于XML 文檔與C++類之間,已經(jīng)得到對應(yīng)的邏輯關(guān)系。但是在C++語言上,還需要解決下面2 個(gè)問題。

      1)動(dòng)態(tài)生成一個(gè)類對象實(shí)例

      C++本身沒有根據(jù)名字生成類對象實(shí)例的功能。想要在讀取XML 的parameters 節(jié)點(diǎn)時(shí)生成QParameters 的實(shí)例,可以用C++的模板功能來模擬實(shí)現(xiàn)動(dòng)態(tài)生成類對象實(shí)例的功能。示例代碼如下:

      通過createInstance()的方式,可以生成QParameters 類的對象實(shí)例。

      為了能夠讓C++程序能夠通過名字查詢到該函數(shù),然后調(diào)用,還需要定義個(gè)函數(shù)指針類型。

      typedef QObject* (*createInstance_func)(QObject* parent );

      然后通過哈希表QHast的形式,就可以通過名字得到對象實(shí)例。

      2)動(dòng)態(tài)設(shè)置類屬性的值

      C++有運(yùn)行時(shí)類型信息RTTI(Run-Time Type Identif ication),但是該信息只能用來鑒別類型,無法操作類的成員變量。

      C++類本身沒有屬性,只有類成員變量及類成員函數(shù),不提供動(dòng)態(tài)設(shè)置成員變量的功能。但是QT 提供了一套元對象系統(tǒng)(Meta-Object System),可以幫助實(shí)現(xiàn)該功能。

      首先要基于QT 的元對象系統(tǒng)來賦予C++類屬性的功能。通過在類中使用以下定義:

      Q_PROPE RT Y(int carl ength READ getCarlength WRITE getCarlength)

      可以賦予C++類屬性。示例中的carLength就是屬性名。

      有了屬性以后,把這個(gè)XML 節(jié)點(diǎn)的值48 賦予屬性carlength,其實(shí)現(xiàn)方式為調(diào)用QObject::setProperty 方法。

      3 算法設(shè)計(jì)

      XML 文檔的解析,主要有兩種方式,一種文檔對象模型DOM(Document Object Model),使用樹形結(jié)構(gòu)來描述XML 文檔,層次結(jié)構(gòu)清晰,較為符合人類的抽象認(rèn)知,在處理過程中會(huì)將整個(gè)文檔的內(nèi)容都載入到內(nèi)存中,內(nèi)存占用率較高。另外一種是流式解析的SAX(simple API for XML),相比于DOM,SAX 的速度更快,效率更高,但它是逐行掃描,邊掃描邊解析,操作復(fù)雜。為便于說明,后面使用DOM 的方式來說明。

      XML 文檔的內(nèi)容如圖1 所示,configuration為根節(jié)點(diǎn),parameters 和database 作為其子節(jié)點(diǎn)。對于每一個(gè)子節(jié)點(diǎn),進(jìn)行如圖3 所示的處理。

      1)根據(jù)傳入的DOM 節(jié)點(diǎn),判斷是否有子節(jié)點(diǎn)。有子節(jié)點(diǎn)則認(rèn)為是復(fù)合屬性,否則為簡單屬性。

      2)如果為簡單屬性,則提取子節(jié)點(diǎn)的內(nèi)容,賦值給對象實(shí)例。然后繼續(xù)處理下一子節(jié)點(diǎn)。

      3)如果是復(fù)合屬性,那么根據(jù)前述的createInstance 方法,按照子節(jié)點(diǎn)名,動(dòng)態(tài)生成一個(gè)對應(yīng)的對象實(shí)例。

      4)對3)生成的對象實(shí)例進(jìn)行內(nèi)容組裝。

      圖3 子節(jié)點(diǎn)處理流程Fig.3 Child node processing flow

      5)判斷當(dāng)前子節(jié)點(diǎn)的屬性名是否記錄在List類型的信息中,如果是List 類型的,則按照List屬性的方法來組裝。

      6)如果不是List 類型的屬性,則將該對象實(shí)例的值賦予父實(shí)例對象。

      通過以上步驟,可以通過遞歸的方式,高效得將XML 文件內(nèi)容轉(zhuǎn)換為C++的對象實(shí)例。

      將C++對象實(shí)例轉(zhuǎn)換XML 形式輸出相對比較簡單,只需要遍歷C++類的所有屬性,然后組成XML 節(jié)點(diǎn)即可,在此不再贅述。

      4 算法實(shí)現(xiàn)

      依據(jù)動(dòng)態(tài)對象生成原理和算法設(shè)計(jì),實(shí)現(xiàn)部分主要分為兩部分:動(dòng)態(tài)對象生成的實(shí)現(xiàn)和對象實(shí)例組裝的實(shí)現(xiàn)。

      動(dòng)態(tài)對象生成模塊使用一個(gè)泛型類DynamicObjectFactory。 該 類 主 要 就 是 構(gòu)建對象生成原理中的哈希表QHash。

      由于QT 中只有QObject 的派生類才能使用屬性,所以要求的XML 相關(guān)的類需要從QObject 派生。通過此方法將類名字和創(chuàng)建對象實(shí)例的方法注冊保存,以便后續(xù)使用。

      對象實(shí)例的組裝模塊,定義了一個(gè)基類XmlBaseData,由基類來實(shí)現(xiàn)XML 轉(zhuǎn)換的工作,那么以后使用時(shí),只需要定義XML 節(jié)點(diǎn)對應(yīng)的數(shù)據(jù)結(jié)構(gòu)的類,即可將XML 轉(zhuǎn)換為C++的對象實(shí)例。

      XmlBaseData 的類結(jié)構(gòu)如圖4 所示。內(nèi)部有兩個(gè)靜態(tài)的成員變量,分別記錄List 類型的屬性和復(fù)合屬性,以便組裝實(shí)例的時(shí)候名字的查找。

      圖4 XMLBaseData的UML類圖Fig.4 UML class diagram of XMLBaseData

      load 函數(shù)用于將XML 的內(nèi)容組裝到C++對象實(shí)例中,write 則將對象實(shí)例以XML 的方式寫出到文件中。

      preload 函數(shù)則是為了一些特殊的節(jié)點(diǎn)或類型預(yù)留,為一個(gè)返回0 的空函數(shù)。在派生類需要對某些節(jié)點(diǎn)進(jìn)行特殊處理預(yù)留。

      registerAllProp 函數(shù)是需要在派生類的構(gòu)造函數(shù)中調(diào)用1 次的函數(shù),即所有該類的實(shí)例只需要進(jìn)行1 次處理的函數(shù)。該函數(shù)的作用是遍歷當(dāng)前類的所有屬性,將所有的復(fù)合屬性保存到complexProps 哈希表中,以便于后續(xù)的處理。

      以本文中的示例XML 文檔為例,需要?jiǎng)?chuàng)建如下的類,類關(guān)系如圖5 所示。

      3 個(gè)XML相關(guān)的類QConfiguration、QParameters、QDatabase 都從XmlBaseData 基類派生,本身不需要特別定義方法,只需定義數(shù)據(jù)的屬性即可。在使用時(shí),只需調(diào)用基類的load 函數(shù)即可將XML 文件內(nèi)容讀入。

      圖5 UML類關(guān)系圖Fig.5 UML class relationship diagram

      示例代碼如圖6 所示。

      圖6 示例代碼Fig.6 Sample code

      運(yùn)行結(jié)果如圖7 所示。

      只需定義好數(shù)據(jù)結(jié)構(gòu)的成員,通過短短3 ~5行代碼就可以完成XML 讀取的工作。

      5 結(jié)語

      提出一種將XML 文檔和C++對象實(shí)例的互相轉(zhuǎn)換方法,并實(shí)現(xiàn)了該方法。該方法能夠讓開發(fā)人員關(guān)注于數(shù)據(jù)和業(yè)務(wù),從繁瑣的字符串比較,一大堆的if-else 組合中解放出來,使用較少的代碼高效地實(shí)現(xiàn)了從XML 文件到C++對象實(shí)例的轉(zhuǎn)換,具有通用性,同時(shí)也為特殊需要提供了接口預(yù)留。該方法使用了基于QT 的實(shí)現(xiàn)方式,由于QT 是跨平臺(tái)的架構(gòu),所以該方法可以在windows 和Linux上跨平臺(tái)使用。

      圖7 示例代碼運(yùn)行結(jié)果Fig.7 Operation result of sample code

      猜你喜歡
      示例實(shí)例文檔
      大還是小
      有人一聲不吭向你扔了個(gè)文檔
      2019年高考上海卷作文示例
      常見單位符號大小寫混淆示例
      山東冶金(2019年5期)2019-11-16 09:09:22
      “全等三角形”錯(cuò)解示例
      基于RI碼計(jì)算的Word復(fù)制文檔鑒別
      Persistence of the reproductive toxicity of chlorpiryphos-ethyl in male Wistar rat
      完形填空Ⅱ
      完形填空Ⅰ
      不讓他人隨意下載Google文檔
      電腦迷(2012年4期)2012-04-29 06:12:13
      定远县| 若尔盖县| 顺义区| 新余市| 元氏县| 抚州市| 西华县| 柘城县| 睢宁县| 屯门区| 来凤县| 措勤县| 金阳县| 赫章县| 高阳县| 阿克| 佛学| 沈阳市| 桐乡市| 葫芦岛市| 德阳市| 河西区| 湘西| 公安县| 泰来县| 镇雄县| 泉州市| 保亭| 瓦房店市| 崇礼县| 阳信县| 阳朔县| 富蕴县| 如东县| 盐城市| 凌海市| 盘锦市| 永修县| 体育| 贡嘎县| 吐鲁番市|