如何用xmllint解析XML并转换为指定格式的CSV?
问题
需要解析XML文件,将其中<ac>标签的val属性(区号)与对应<ph>标签的val属性(电话号码)转换为指定格式的CSV,每行格式为「区号, '电话号码'」。曾尝试用循环结合xmllint的XPath查询,但由于每个区号对应的电话号码数量不固定,循环次数无法确定,想找更简便的xmllint用法。
示例XML
<list type='full' level='state' val='WI'> <ac val='262'> <ph val='0000000' /> <ph val='0003639' /> <ph val='0129292' /> </ac> <ac val='363'> <ph val='0000000' /> <ph val='0003639' /> </ac> </list>
期望输出
262, '0000000' 262, '0003639' 262, '0129292' 363, '0000000' 363, '0003639'
尝试代码
for i in {1..2}; do for j in {1..3}; do echo "i=$i, j=$j" xmllint --xpath "concat(//ac[$i]/@val,',', //ac/ph[$j]/@val)" test.xml done done
解决方案
可以直接通过XPath遍历所有<ph>节点,同时关联其父节点<ac>的区号,无需手动嵌套循环。具体命令如下:
xmllint --xpath "//ac/ph/concat(../@val, ', ', '\'', @val, '\'')" test.xml | sed 's/ /\n/g'
命令解释
//ac/ph:选中所有<ac>节点下的<ph>节点,自动遍历所有区号对应的全部电话号码,无需手动指定循环次数concat(../@val, ', ', '\'', @val, '\''):拼接成目标格式,../@val获取当前<ph>父节点<ac>的区号,@val获取当前<ph>的电话号码,同时添加要求的单引号和分隔符sed 's/ /\n/g':xmllint默认会把所有拼接结果用空格分隔输出,通过sed将空格替换为换行符,让每条记录单独占一行
如果偏好更简洁的换行处理,也可以用tr命令替代sed:
xmllint --xpath "//ac/ph/concat(../@val, ', ', '\'', @val, '\'')" test.xml | tr ' ' '\n'
内容的提问来源于stack exchange,提问作者Tahir Khalil
相关产品推荐
相关产品推荐

