使用Python或脚本更新XML文档

1 投票
3 回答
945 浏览
提问于 2025-04-18 07:52

我有一个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

撰写回答