通过shell解析xml文件

本人在工作中遇到一个需要用shell文件定期解析xml文件取出其中标签中的值的工作。
在尝试了多种方法以后整理出了一个相对于比较简便的解析方法,仅供参考。

首先我们需要知道xml文件的结构,xml文件由文件头与文件体组成。文件体由根节点与子节点构成。
文件头顾名思义处于文件的开始部分,一般标明了xml文件的版本编码等信息。例如以下例子中的第一行:
                     <?xml version="1.0" encoding="utf-8"?>
根节点处于文件体的开始与结束,例如以下例子中的:<urlset></urlset>
子节点是相对的,比如说<url>是根节点<urlset>的子节点,<ID>是<url>的子节点。

例如我们现在需要解析xml文件中<url>标签的内容,也就是说要解析ID、姓名、电话、身份证号、微信号、申请时间、审批状态、审批时间这几个标签的值。
具体内容如下:
        <?xml version="1.0" encoding="utf-8"?>
         <urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">

           <url>
              <ID>AE0530A78C913635A</ID>
              <姓名>JOK</姓名>
              <电话>1325314002</电话>
              <身份证号>1234567890</身份证号>
              <微信号>dh1562</微信号>             
              <申请时间>2018-09-02</申请时间>
              <审批状态>1</审批状态>
              <审批时间>2018-09-02</审批时间>
           </url>

           <url>
             <ID>01053609F780A5FF6</ID>
             <姓名>TOM</姓名>
             <电话>1803270891</电话>
             <身份证号>1234567890</身份证号>
             <微信号>ch1234</微信号>           
             <申请时间>2018-09-02</申请时间>
             <审批状态>0</审批状态>
             <审批时间>null</审批时间>          
           </url>

         </urlset>

因为有多个url标签存在,所以本人解析xml文件的思路是首先设定分隔符将xml文件内容分隔成一段一段的只包含一对<url></url>标签以及子标签的内容。然后将该内容重定向到一个子文件,再从子件中设定分隔符来读取具体想要的值。
具体步骤如下:
  1.设定分隔符将xml文件内容分隔成一段一段的只包含一对<url></url>标签以及子标签的内容:
          text=`awk -v RS="</url>" "NR==$m{print}" $filename`
     awk的具体功能大家可以在网上查阅资料了解,应为涉及到循环所以{print}前面的参数是一个变量。
  2.然后将该内容重定向到一个子文件:
          echo $text >123.txt 
  3.再从子件中设定分隔符来读取具体想要的值,以取<ID><ID>中的值为例:
         ID=`awk -v RS="</*ID>" 'NR==2{print}' 123.txt`

具体代码如下:

#!/bin/sh
. ~/.profile

#本地文件存放地址
filepath=/testbk/ws

#取日期
vdate=$(date +%Y%m%d)
echo $vdate

#文件名称
filename="REGISTERINFO_"$vdate".xml"

#文件尾包含字符串(退出循环的判断条件)
endtxt="</urlset>"

#进入本地文件存放地址
cd $filepath

#取第几段内容的参数
m=1
#定义一个死循环
while :
do 
#取xml文件第m段的内同
text=`awk -v RS="</url>" "NR==$m{print}" $filename`
#将该内容重定向到特定文件
echo $text >123.txt 

#如果本次循环的域内容不包含文件尾,则解析该内容
if [ `grep -c "$endtxt" 123.txt` -eq '0' ]; then
ID=`awk -v RS="</*ID>" 'NR==2{print}' 123.txt`
NAME=`awk -v RS="</*姓名>" 'NR==2{print}' 123.txt`
TEL=`awk -v RS="</*电话>" 'NR==2{print}' 123.txt`
IDCARDNUM=`awk -v RS="</*身份证号>" 'NR==2{print}' 123.txt`
WCHAT=`awk -v RS="</*微信号>" 'NR==2{print}' 123.txt`
APPLYTIME=`awk -v RS="</*申请时间>" 'NR==2{print}' 123.txt`
APPSTATUS=`awk -v RS="</*审批状态>" 'NR==2{print}' 123.txt`
APPTIME=`awk -v RS="</*审批时间>" 'NR==2{print}' 123.txt`


else
echo "文件读取结束"
#退出死循环
break
fi
m=`expr $m + 1`
done


过程会是这样子,xml文件内容会被分解为三部分,分别是:
一:
         <urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">

           <url>
              <ID>AE0530A78C913635A</ID>
             <姓名>JOK</姓名>
             <电话>1325314002</电话>
             <身份证号>1234567890</身份证号>
              <微信号>dh1562</微信号>             
             <申请时间>2018-09-02</申请时间>
             <审批状态>1</审批状态>
             <审批时间>2018-09-02</审批时间>
           </url>
二:
         <url>
             <ID>01053609F780A5FF6</ID>
             <姓名>TOM</姓名>
             <电话>1803270891</电话>
             <身份证号>1234567890</身份证号>
              <微信号>ch1234</微信号>           
             <申请时间>2018-09-02</申请时间>
             <审批状态>0</审批状态>
             <审批时间>null</审批时间>          
           </url>
三:
       </urlset>

第一、二次循环会将内容重定向到123.txt中,然后在解析123.txt文件的内容,取出想要的节点中的值。
第三次循环取到的值包含根节点的结尾节点</url>,if判断结构为false,所以会走else分支,该分支中有break退出循环。

本人小白一枚,对shell的了解也不是很深入,如果有更加简便的解析xml文件方法的话希望大家多多指点,十分感谢!
posted @ 2018-09-12 10:27  小小短腿儿  阅读(11523)  评论(0编辑  收藏  举报