【问题标题】:Edit Multiple XML Nodes in Multiple XML files在多个 XML 文件中编辑多个 XML 节点
【发布时间】:2015-08-04 23:16:59
【问题描述】:

我有多个 XML 文件(60+),我需要编辑多个文本节点(我认为它被称为)。 我熟悉 Java、JavaScript、Python、JQuery、PHP、HTML。

我可以用什么语言完成这个?

这是我目前拥有的示例 XML 文档:

<?xml version="1.0" encoding="utf-8"?><bookstore>
    <book category="cooking">
        <title lang="en">Chinese</title>
        <author>chinese author</author>
        <year>2015</year>
        <price>fourth</price>
    </book>
    <book category="cooking">
        <title lang="en">All American</title>
        <author>American Author</author>
        <year>2015</year>
        <price>6.00</price>
    </book>
</bookstore>

例如,我想一次更改多个元素的作者和年份!

这是我的 Python 代码,一次编辑一个节点。我需要一个循环或其他东西来一次编辑更多。

from xml.dom.minidom import parse
import os

# create a backup of original file
new_file_name = 'dom.xml'
old_file_name = new_file_name + "~"
os.rename(new_file_name, old_file_name)

# change text value of element
doc = parse(old_file_name)
node = doc.getElementsByTagName('author')
node[0].firstChild.nodeValue = 'new author'


# persist changes to new file
xml_file = open(new_file_name, "w")
doc.writexml(xml_file, encoding="utf-8")
xml_file.close()

任何帮助将不胜感激。新手程序员来了!

谢谢! :D

【问题讨论】:

  • 您想在每个文件的每本书中将作者更改为new author 吗?或者您想将一些更改为new author 而不是其他?或者有些发给new other,有些发给another new author
  • “新作者”只是一个占位符(显然)。我需要一些改变,但不是全部。不过,知道这两种方式会很好。这都是虚拟数据。我有更大的文件需要应用。
  • 如果你只是想使用最好的工具来完成这项工作——正如你的第一段所暗示的那样——而不是专门使用 Python,我会避免标记这个 python(以同样的方式标记“how do我用 awk 和 sed 从 shell 做 X”,因为有人认为其中一种工具可能很方便,但不赞成)。同样,如果您想重用第三方库而不是编写自己的解析器,这不是解析问题。

标签: xml element textnode xml-editor


【解决方案1】:

创建函数:

def create_backup(new_file_name):
    """ create a backup of original file """
    old_file_name = new_file_name + "~"
    os.rename(new_file_name, old_file_name)
    return old_file_name

def change_author(doc, new_author)
    """ change text value of 'author' """
    node = doc.getElementsByTagName('author')
    node[0].firstChild.nodeValue = new_author

def save_changes(new_file_name, doc):
    """ persist changes to new file """
    xml_file = open(new_file_name, "w")
    doc.writexml(xml_file, encoding="utf-8")
    xml_file.close()

现在很容易创建一个循环:

file_names = ['dom.xml', ...]
for new_file_name in file_names:
    old_file_name = create_backup(new_file_name)
    doc = parse(old_file_name)
    change_author(doc, 'new author')
    save_changes(new_file_name, doc)

【讨论】:

  • 因此,如果我想编辑不同的元素或节点,我只需为其添加另一个函数,然后在保存更改之前最后调用它?
【解决方案2】:

就个人而言,我会使用 shell 脚本和XMLStarlet

for f in *.xml; do
  xmlstarlet ed \
    -u '//author' -v 'new author' \
    <"$f" >"$f.new" && mv "$f.new" "$f"
done

如果您只想更改“All American”一书的作者,并同时更改同一本书的价格,则可能改为:

for f in *.xml; do
  xmlstarlet ed \
    -u '//book[title="All American"]/author' -v 'new author' \
    -u '//book[title="All American"]/price' -v 12.34 \
    <"$f" >"$f.new" && mv "$f.new" "$f"
done

请注意,如果任何其他用户可以写入您正在使用的目录,则使用硬编码的临时文件名是一种不好的做法;如果是这样的话,使用mktemp 来生成一个唯一的临时文件名会更合适。

【讨论】:

  • 从未使用过其中任何一个。我该如何设置该环境?
  • 几乎完全取决于您的操作系统和环境。如果您使用的是安装了 MacPorts 的 Mac,那就是 sudo port install xmlstarlet;在 Ubuntu 上,无论在您当前运行的操作系统上安装软件的本地方式是什么,它都会是 sudo apt-get install xmlstarlet 等等。
  • ...对于mktemp,它包含在任何现代 Unix 的开箱即用中。
最近更新 更多