【问题标题】:lxml iterparse, child with same tag namelxml iterparse,具有相同标签名称的孩子
【发布时间】:2016-01-10 01:58:30
【问题描述】:

我想从文件(1,5gb 文件)中即时解析 xml,如下所示:

<product product_id="x" name="x" sku_number="x">
    <category>
        <primary>x</primary>
        <secondary>y</secondary>
    </category>
    <URL>
        <product>URL__I_WANT_TO_PULLOUT</product>
        <productImage>x</productImage>
    </URL>
    <description>
        <short>x</short>
        <long>x</long>
    </description>
</product>

我正在使用lxml.etree.iterparse 喜欢:

for event, elem in ET.iterparse(f, events=('end',), tag='product'):
    save_product(elem)

我从 xml 节点获取所有必需的值。我唯一无法拔出的节点是URL&gt;product(它只是空的)。我认为这是由相同的标签名称引起的。除了iterparse,还有什么方法可以即时解析xml?

【问题讨论】:

  • 如果您更改样品的名称,它会起作用吗?
  • 我没试过,但它是外部数据馈送,所以我不负责更改它

标签: python xml django scrapy lxml


【解决方案1】:

如果我在您的样本上运行etree.iterparse,它会发现'product' 标签两次:一个是外部的,一个是内部的&lt;product&gt;。外部标签有子元素,其text 为空。因此,您需要跳过那些外部 'product' 标记,以便仅与那些没有子元素的标记一起使用,例如:

for event, elem in etree.iterparse(f, events=('end',), tag='product'):
    if not len(elem):
        save_product(elem)

如果需要处理顶部product标签的所有元素,可以在主循环中删除所有内部product字段,然后按路径处理所有子元素,例如python's lxml and iterparse method

def save_product(elem):
    cat_prim = elem.xpath('category/primary')[0].text;
    cat_sec = elem.xpath('category/secondary')[0].text;
    url_prod = elem.xpath('URL/product')[0].text;
    url_img = elem.xpath('URL/productImage')[0].text;
    desc_short = elem.xpath('description/short')[0].text;
    desc_long = elem.xpath('description/long')[0].text;

for event, elem in etree.iterparse(f, events=('end',), tag='product'):
    if len(elem):
        save_product(elem)

【讨论】:

  • 没错,但我正在构建产品数据,所以我同时需要两者(外部 的子节点和内部 的文本)。
  • @mdargacz 有什么问题?在循环内部或save_product 函数中,您可以区分内部&lt;product&gt; 和顶部&lt;product&gt; 标签,因此可以根据您的需要对它们进行不同的处理。
  • 是的,它们可以有不同的处理方式,但有严格的相关性,如果我有几十个产品,我可以确定解析顶部的下一个内部 包含该产品 url 吗?即使那是真的,我也可以制作(顶部,内部)然后save_product()的元组。但我不希望以这种 hacky 的方式这样做。
  • @mdargacz 它以这种方式工作,但我不确定至少在库文档没有明确具体的情况下做这样的假设是否好。无论如何,如果您有一个用于顶部 product 元素的主循环并为其字段提供单独的处理程序,那么代码结构会好得多。我通过这样的例子更新了答案。
  • 但是这个:url_prod = elem.xpath('URL/product/text()');不起作用,因为此时节点为空
【解决方案2】:

我知道这可能会很晚,但对于那里的任何人,我使用了以下解决方案:

   file_contents = xml_file.read()
   xml_obj = etree.fromstring(file_contents)
   context = xml_obj.xpath(tag)

我的tag 变量是产品的路径,例如//parent/product。然后你可以使用上下文容器对你的元素做一些事情。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-25
    • 1970-01-01
    • 1970-01-01
    • 2021-07-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多