使用Python或脚本更新XML文档
我有一个XML文件,它用作动态面板的索引,结构如下:
<?xml version="1.0"?>
<Addons>
<line>
<text>My collection 1</text>
<level>3</level>
<comment/>
<file>Collection1.zip</file>
<size>120</size>
<parent>Collection</parent>
<directory>picture</directory>
<type>jpeg</type>
<filedate>22/05/2014</filedate>
</line>
<line>
<text>My collection 2</text>
<level>3</level>
<comment/>
<file>Collection2.zip</file>
<size>880</size>
<parent>Collection</parent>
<directory>picture</directory>
<type>jpeg</type>
<filedate>01/04/2013</filedate>
</line>
</Addons>
我的面板使用这个文件作为构建索引。当我在服务器上更新文件时,我需要手动更新filedate
这个元素……但是这个文件有80行,真是太麻烦了。
有没有办法通过脚本来完成这个工作呢?具体步骤是:
- 逐行解析文件
- 从
<file>
元素中读取文件名 - 获取文件的最后修改日期
- 如果存在,就更新
<filedate>
元素 - 继续处理下一行
服务器上可以使用Shell脚本和Python。
谢谢!!
3 个回答
0
这是一个使用Python的解决方案,它利用XML解析器(xml.etree
)来稳健地处理输入:
#!/usr/bin/env python
import os
import datetime
from xml.etree import ElementTree
inFile = "in.xml"
outFile = "out.xml"
# Parse the entire document.
tree = ElementTree.parse(inFile)
# Loop over the <line> elements
for elem in tree.iter('line'):
# Get the child element [values] of interest.
fname = elem.find('file').text.strip()
elemFDate = elem.find('filedate')
# Determine the new modification date.
# Note: As @glenn jackman notes, %Y-%m-%d would be a better date format to use.
newDate = datetime.datetime.fromtimestamp(os.path.getmtime(fname)) \
.strftime("%d/%m/%y")
# Update the date element.
elemFDate.text = newDate
# Write the output file.
tree.write(outFile)
注意:
- 整个文档会一次性读取和写入,这种方法只适合较小的XML文件。
- 没有错误处理——假设所有相关的元素和引用的文件都存在。
1
这里有一个简单的Python脚本,可以帮你完成这个任务:
#!/usr/bin/python
import re
from datetime import date
input_file = open("input.xml", "r")
output_file = open("output.xml", "w")
today = date.today().strftime("%d/%m/%Y")
replacement = '<filedate>' + today + '</filedate>'
for line in input_file:
updated_line = re.sub(r'<filedate>.*?</filedate>', replacement, line)
output_file.write(updated_line)
input_file.close()
output_file.close()
2
使用xmlstarlet
这个命令行工具:
xmlstarlet sel -t -v '//file' -n file.xml |
while IFS= read -r filename; do
filedate=$(date -d "@$(stat -c %Y "$filename")" +%d/%m/%Y)
xmlstarlet ed --inplace -u "//filedate[../file = '$filename']" -v "$filedate" file.xml
done