python - 如何从 lxml 正确使用 xmlfile api

标签 python xml python-3.x lxml

我有一个大的(超过 5 个演出)XML 文件,我需要对其进行解析、执行一些操作并编写一个新的 XML 文件。

虚拟.xml

<?xml version="1.0" encoding="UTF-8"?>
<catalog xmlns="http://www.namespace.com" catalog-id="test-catalog">
    <header>
        <name>Product Catalog</name>
    </header>

    <product product-id="1234">
        <available-flag>false</available-flag>
        <name>product1</name>
    </product>
    <product product-id="5678">
        <available-flag>false</available-flag>
        <name>product1</name>
    </product>
    <product product-id="9999">
        <available-flag>false</available-flag>
        <name>product1</name>
    </product>    
</catalog>

如您所见,上面的 XML 有 3 个 product标签,我需要根据预定义的 ID 列表过滤一些产品 ID。

我正在使用 lxml iterparse迭代地解析 XML 并想使用 xmlfile以增量方式创建新 XML 以保持低内存占用的 API。因此,我的动机是过滤掉不符合条件的产品标签,并按原样复制其余的 XML 标签。

from lxml import etree
f = './dummy.xml'

f1 = './test.xml'
context = etree.iterparse(f, events=('start',))
productsToExport = ['1234']


with etree.xmlfile(f1, encoding='utf-8') as xf:
    xf.write_declaration()
    with xf.element('catalog xmlns="http://www.namespace.com" catalog-id="test-catalog"'):
        for event, element in context:
            tagName = etree.QName(element.tag).localname
            if (tagName == 'product'):
                pid = element.get('product-id')
                if (pid in productsToExport):
                    xf.write(element)
            elif (tagName == 'header'):
                xf.write(element) # copy existing header tag as it is

上面的代码工作正常并生成如下的 XML

<?xml version='1.0' encoding='utf-8'?>
<catalog xmlns="http://www.namespace.com" catalog-id="test-catalog">
    <header xmlns="http://www.namespace.com">
        <name>Product Catalog</name>
    </header>

    <product xmlns="http://www.namespace.com" product-id="1234">
        <available-flag>false</available-flag>
        <name>product1</name>
    </product>
</catalog xmlns="http://www.namespace.com" catalog-id="test-catalog">

如果您观察上面的 XML,它几乎没有问题:

  • 关闭 <catalog>标签有 xmlns & catalog-id出现在里面
  • 所有标签如 header, productxmlns其中存在的属性

我检查了xmlfile api documentation但找不到解决上述问题的方法。

编辑:

我设法通过使用以下方法解决了第一个问题

attribs = {'xmlns' : 'http://www.namespace.com', 'catalog-id' : 'test-catalog'}
 with xf.element('catalog', attribs):
     # previous logic

因此,现在只剩下从每个元素中删除 namespace 了。

最佳答案

考虑使用 lxml.etree 方法而不是 xmlfile API 简单地重建 XML 树,仍然在 iterparse 的上下文中:

from lxml import etree

f = './dummy.xml'
f1 = './test.xml'    
productsToExport = ['1234']

# ROOT ELEMENT WITH DEFUALT NAMESPACE
my_nmsp = {None: 'http://www.namespace.com'}

# INITIALIZE ITERATOR
context = etree.iterparse(f, events=('start',))

for event, element in context:    
    tagName = etree.QName(element.tag).localname   

    for prod in productsToExport:
        root = etree.Element('catalog', nsmap=my_nmsp)
        root.text = '\n\t'
        root.attrib['catalog-id'] = "test-catalog"

        # PRODUCT ELEMENT
        if tagName == 'product':
            pid = element.get('product-id')

            if pid == prod:
                root.append(element)

        # HEADER ELEMENT        
        elif (tagName == 'header'):
            root.append(element)

        # OUTPUT TREE TO FILE
        with open(f1, 'wb') as f:
            f.write(etree.tostring(root, pretty_print=True))

输出

<catalog xmlns="http://www.namespace.com" catalog-id="test-catalog">
    <header>
        <name>Product Catalog</name>
    </header>

    <product product-id="1234">
        <available-flag>false</available-flag>
        <name>product1</name>
    </product> 
</catalog>

关于python - 如何从 lxml 正确使用 xmlfile api,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52279722/

相关文章:

python-3.x - 如何确定我的Linux机器上安装了哪个版本的python3 tkinter?

python - 在 Jupyter Notebook Markdown Cell Python 中打印变量

python - 在给定的提及代码中,我想要将鼠标悬停在线图上时 X 和 Y 的实际值,我该怎么办?

android - 我有一个用 XML 制作的自定义编辑文本,仅在 KITKAT 版本中它具有黑色背景

python - 如何对列表进行排序首先写入相同的元素,然后按升序排列

Python 将回车符视为换行符。我能做什么呢?

python - 无法在 python graphql 框架中启用 CORS/允许 header - ariadne

python - 读取2个.txt文件,访问其中的数据,然后打印

java - 在 Android 中具有弯曲底线的自定义形状布局

java - 有人可以解释膨胀方法吗?深入理解Android View