如何使用shell脚本读取XML并写入文本文件?

时间:2017-08-22 11:16:02

标签: xml bash shell

如何在Shell脚本中读取XML标签及其值? 我搜索并发现只有当我们知道标签名称时才有可能。

但是,我想要一个脚本,它读取XML中的所有标签(重复标签),其中包含值。 在我的XML中,标签可能会发生变化。所以,我想要可以用于不同XML的脚本。

<Data>
    <Employees>

        <Employee location = "Paris">
            <Name> Andy </Name>
            <ID> 101 </ID>
        </Employee>

        <Employee location = "Germany">
            <Name> Batman </Name>
            <ID> 202 </ID>
        </Employee>

    </Employees>
</Data>

我想阅读XML并写入文本文件,如下所示:

Name : Alex
ID: 101
Location: Paris

Name : Batman
ID: 202
Location: Germany

3 个答案:

答案 0 :(得分:2)

正如我在评论中所说,shell不适用于除了最简单的XML文件之外的所有文件。下面的Python脚本将处理您抛出的任何格式良好的XML,但是:

import xml.parsers.expat
import sys

def start_element(name, attrs):
    print('Start element:', name)
    for attribute_name, attribute_value in attrs.items():
        print('Attribute:', attribute_name, attribute_value)

def end_element(name):
    print('End element:', name)

def char_data(data):
    data = str(data).strip()
    if data:
        print('Character data:', data)

p = xml.parsers.expat.ParserCreate()

p.StartElementHandler = start_element
p.EndElementHandler = end_element
p.CharacterDataHandler = char_data

with open(sys.argv[1], 'rb') as xmlfile:
    p.ParseFile(xmlfile)

它几乎逐字地从documentation复制。您可以操纵三个函数start_elementend_elementchar_data以满足您的需求。 (也就是说,截至目前,它们并没有产生您指定的确切输出,但可以通过一点点努力进行调整。)

这样称呼:

python3 script_above.py your_xml_file.xml

答案 1 :(得分:1)

请尝试以下操作并告诉我这是否对您有所帮助。

awk '
/<\/Data>/{
  a="";
  next
}
/<Data>/{
  a=1;
  next
}
/location/ && a{
  gsub(/\"|>/,"",$NF);
  location=$NF;
  next
}
/Name/ && a{
  name=$2;
  next
}
/ID/ && a{
  print "Name : ",name RS "ID: ",$2 RS "Location: ",location;
  next
}
'    Input_file

根据OP的要求,正弦无标签应该是硬编码的,所以现在也加入以下解决方案。

EDIT2:我不是xml专家但是在这里试了一次,请你检查一次。

awk 'NF==1 && (/ +<[a-zA-Z]+>/ || /^<[a-zA-Z]+>/ || / +<\/[a-zA-Z]+>/){
next
}
{
sub(/^ +/,"")
gsub(/\"|<|>/,"",$0);
sub(/\/.*/,"");
if($0){
  print
}
}
'  Input_file

答案 2 :(得分:0)

awk -F [\>\<] '/<Name>/ { nam="Name  : " $3 } /<ID>/ { id="ID : "$3 } /Employee location/ { match($2,/".*"/);loc=substr($2,RSTART+1,RLENGTH-2) } /<\/Employee>/ { print nam"\n"id"\n"loc"\n\n" }' filename

模式匹配名称,ID和位置相应地创建变量。当我们找到关闭的Employee标记时,打印变量。