利用Shell解析處理XML的方法匯總
前言
前幾天在干活的時候遇到一個需要解析處理xml文件的一個需求,當(dāng)時考慮到邏輯比較復(fù)雜,因此用java慢慢搞了搞。不過這個需求經(jīng)常會變,每次變化之后都要重新找到j(luò)ar包的代碼,改了之后還要替換原來的jar包,一來不方便修改,二來不方便統(tǒng)一保存代碼,三來也不方便查看jar包的功能。
其實(shí)對于這種比較靈活的功能,最方便高效的做法是采用一些腳本語言,比如python,ruby等等,開發(fā)效率高,而且也能處理一些復(fù)雜邏輯。但是由于種種原因,工作中有的機(jī)器沒有安裝這些語言的解釋器。因此不得已,研究了一波用shell腳本解析xml的方法。
說到底,shell還是不太適合處理復(fù)雜的邏輯,但是對于一些簡單的查找替換等需求,用shell來搞還是挺方便的。
我這里主要采用了下面三個工具:
- xmllint
- xpath
- xml2
下面就分別總結(jié)下這三個工具的用法,方便以后查閱。
xmllint
簡述
xmllint其實(shí)是由一個叫l(wèi)ibxml2的c語言庫函數(shù)實(shí)現(xiàn)的一個小工具,因此效率比較高,對不同系統(tǒng)的支持度也很好,功能也比較全。他一般屬于libxml2-utils這個軟件包,因此類似與sudo apt install libxml2-utils
的命令就可以安裝。
功能
xmllint至少支持下面幾個常用功能:
- 支持xpath查詢語句
- 支持類shell的交互式查詢
- 支持xml格式驗(yàn)證
- 支持dtd,xsd對xml的校驗(yàn)
- 支持編碼轉(zhuǎn)換
- 支持xml格式化
- 支持去空格壓縮
- 支持時間效率統(tǒng)計
其實(shí)我們比較常用的功能主要也就是三個–xpath查詢、去空格和格式化、校驗(yàn)。
比如當(dāng)前有sample.xml:
<books> <book id="1"> <name>book1</name> <price>100</price> </book> <book id="2"> <name>book2</name> <price>200</price> </book> <book id="3"><name>book3</name><price>300</price> </book> </books>
執(zhí)行xpath查詢:
myths@business:~$ xmllint --xpath "http://book[@id=2]/name/text()" sample.xml book2
去空格:
myths@business:~$ xmllint --noblanks sample.xml <?xml version="1.0"?> <books><book id="1"><name>book1</name><price>100</price><license/></book><book id="2"><name>book2</name><price>200</price></book><book id="3"><name>book3</name><price>300</price></book></books>
格式化:
myths@business:~$ xmllint --format sample.xml <?xml version="1.0"?> <books> <book id="1"> <name>book1</name> <price>100</price> <license/> </book> <book id="2"> <name>book2</name> <price>200</price> </book> <book id="3"> <name>book3</name> <price>300</price> </book> </books>
xsd校驗(yàn):
myths@business:~$ cat sample.xsd <?xml version="1.0" encoding="utf-8"?> <xs:schema id="books" xmlns="" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> <xs:element name="books" msdata:IsDataSet="true" msdata:Locale="en-US"> <xs:complexType> <xs:choice minOccurs="0" maxOccurs="unbounded"> <xs:element name="book"> <xs:complexType> <xs:sequence> <xs:element name="name" type="xs:string" minOccurs="0" msdata:Ordinal="0" /> <xs:element name="price" type="xs:string" minOccurs="0" msdata:Ordinal="1" /> </xs:sequence> <xs:attribute name="id" type="xs:string" /> </xs:complexType> </xs:element> </xs:choice> </xs:complexType> </xs:element> </xs:schema> myths@business:~$ xmllint --noout --schema sample.xsd sample.xml sample.xml validates
注意:校驗(yàn)結(jié)果信息是輸出到stderr中的,工具默認(rèn)會把原文件回顯到stdout里,可以加–noout參數(shù)關(guān)閉stdout回顯。
流傳遞:
xmllint默認(rèn)是傳遞文件名,如果我們希望用通過管道傳遞文件流的方式傳遞數(shù)據(jù),我們可以這樣弄:
myths@business:~$ cat sample.xml |xmllint --format - <?xml version="1.0"?> <?xml version="1.0"?> <books> <book id="1"> <name>book1</name> <price>100</price> <license/> </book> <book id="2"> <name>book2</name> <price>200</price> </book> <book id="3"> <name>book3</name> <price>300</price> </book> </books>
xpath
簡述
xpath工具其實(shí)是封裝了的perl腳本,本身也只有兩百來行,功能比較專一,就是提供xpath的查詢功能。他一般屬于libxml-xpath-perl這個軟件包,因此類似于sudo apt install libxml-xpath-perl
的命令就可以安裝。像suse之類的系統(tǒng)還會直接自帶。
功能
不同系統(tǒng)中安裝的版本可能不同,不過基本功能是類似的:
myths@business:~$ xpath -e '//book/name/text()' sample.xml Found 3 nodes in sample.xml: -- NODE -- book1 -- NODE -- book2 -- NODE -- book3
默認(rèn)會將查詢呢結(jié)果輸出到stdout中,將說明信息輸出到stderr中。如果為了方便收集結(jié)果,可以將stderr重定向到/dev/null,或者加上-q參數(shù):
myths@business:~$ xpath -e '//book/name/text()' sample.xml 2>/dev/null book1 book2 book3 myths@business:~$ xpath -q -e '//book/name/text()' sample.xml book1 book2 book3
xpath相比xmllint的xpath功能有一點(diǎn)點(diǎn)區(qū)別很重要,如果xpath匹配了多個結(jié)果,那么xpath就會分行輸出,而xmllint則會揉到一行:
myths@business:~$ xmllint --xpath "http://book/name/text()" sample.xml book1book2book3
xml2
簡述
xml2這個工具感覺知道的人并不多,不過其實(shí)他在某些場景里跟其他命令配合能起到奇效。這個工具的開發(fā)人員的博客似乎已經(jīng)掛掉了,不過目測應(yīng)該用C以及l(fā)ibxml2庫寫的一個小工具。一般是在xml2軟件包中,因此類似sudo apt install xml2的命令就可以安裝。
功能
這個工具包含六個命令:xml2,2xml,html2,2html,csv2,2csv,功能也非常unix,就是分別將xml,html,csv格式與一種他稱之為“flat format”的格式進(jìn)行轉(zhuǎn)換。舉個例子:
myths@business:~$ cat sample.xml |xml2 /books/book/@id=1 /books/book/name=book1 /books/book/price=100 /books/book /books/book/@id=2 /books/book/name=book2 /books/book/price=200 /books/book /books/book/@id=3 /books/book/name=book3 /books/book/price=300 myths@business:~$ cat sample.xml |xml2|2xml <books><book id="1"><name>book1</name><price>100</price></book><book id="2"><name>book2</name><price>200</price></book><book id="3"><name>book3</name><price>300</price></book></books>
這種自定義的格式非常簡單而巧妙,有的表示新建節(jié)點(diǎn)(/books/book),有的表示給節(jié)點(diǎn)賦值(/books/book/name=book1),有的表示給節(jié)點(diǎn)的屬性賦值(/books/book/@id=1)。寫法跟xpath很像但又不完全一樣。而且相互對應(yīng)的兩個命令放在一起能做到冪等。
那么這種轉(zhuǎn)化命令有什么用呢?其實(shí)我們經(jīng)常會遇到一些創(chuàng)建xml文件的需求,但是直接按照xml格式動態(tài)生成就非常麻煩,這時候用flat format做個中轉(zhuǎn)就非常方便了:
#!/usr/bin/env bash tempFile=$(mktemp tmp.XXXX) function addBook(){ id=$1 name=$2 price=$3 echo "/books/book">>$tempFile echo "/books/book/@id=$id">>$tempFile echo "/books/book/name=$name">>$tempFile echo "/books/book/price=$price">>$tempFile } function main(){ addBook 1 book1 100 addBook 2 book2 200 addBook 3 book3 300 cat $tempFile|2xml|xmllint --format --output new_sample.xml - rm $tempFile } main "$@"
上面這段代碼就生成了與sample.xml一模一樣的new_sample.xml.
總結(jié)
以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,如果有疑問大家可以留言交流,謝謝大家對腳本之家的支持。
相關(guān)文章
Linux中的host命令應(yīng)用實(shí)例詳解
這篇文章主要介紹了Linux中的host命令應(yīng)用舉例的相關(guān)資料,需要的朋友可以參考下2017-07-07詳解shell數(shù)組${arr[*]}和${arr[@]}區(qū)別
本文主要介紹了詳解shell數(shù)組${arr[*]}和${arr[@]}區(qū)別,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-05-05shell腳本實(shí)現(xiàn)的網(wǎng)站日志分析統(tǒng)計(可以統(tǒng)計9種數(shù)據(jù))
這篇文章主要介紹了shell腳本實(shí)現(xiàn)的網(wǎng)站日志分析統(tǒng)計,可以統(tǒng)計9種數(shù)據(jù),如訪問量、帶寬、訪客量、IP統(tǒng)計、搜索引擎等,需要的朋友可以參考下2014-05-05學(xué)習(xí)Linux網(wǎng)絡(luò)編程基本函數(shù)
這篇文章主要介紹了學(xué)習(xí)Linux網(wǎng)絡(luò)編程,網(wǎng)絡(luò)編程的一些基本函數(shù):也是實(shí)現(xiàn)tcp協(xié)議通訊的基本步驟,實(shí)現(xiàn)代碼在最后,IP需要修改為自己的IP,即可通信2021-08-08linux腳本實(shí)現(xiàn)自動發(fā)送和收取郵件的設(shè)置方法
這篇文章主要是介紹linux下通過腳本自動發(fā)送和收取郵件的設(shè)置方法,有需要的朋友可以參考下2013-05-05shell查找當(dāng)前目錄下大于1M的文件的三種方法分享
查找當(dāng)前目錄下大于1M的文件的三種方法,有需要的朋友可以參考下2013-02-02