【问题标题】:Iterate through all sub-tags and strings from an XML tag in python, without specifying sub-tag name遍历python中XML标签的所有子标签和字符串,而不指定子标签名称
【发布时间】:2018-07-11 15:50:23
【问题描述】:

我的问题是来自here 的附加问题,但我不打算将答案部分用于附加问题。

如果我有这样的 XML 文件的一部分:

  <eligibility>
    <criteria>
      <textblock>
        Inclusion Criteria:

          -  women undergoing cesarean section for any indication

          -  literate in german language

        Exclusion Criteria:

          -  history of keloids

          -  previous transversal suprapubic scars

          -  known patient hypersensitivity to any of the suture materials used in the protocol

          -  a medical disorder that could affect wound healing (eg, diabetes mellitus, chronic
             corticosteroid use)
      </textblock>
    </criteria>
    <gender>Female</gender>
    <minimum_age>18 Years</minimum_age>
    <maximum_age>45 Years</maximum_age>
    <healthy_volunteers>No</healthy_volunteers>
  </eligibility>

我想提取此资格部分中的所有字符串(即文本块部分和性别、最小年龄、最大年龄和健康志愿者部分中的字符串)

使用上面的代码我做到了:

import sys
from bs4 import BeautifulSoup

soup = BeautifulSoup(open(sys.argv[1], 'r'), 'lxml')
eligibi = []

for eligibility in soup.find_all('eligibility'):
    d = {'other_name':eligibility.criteria.textblock.string, 'gender':eligibility.gender.string}
    eligibi.append(d)

print eligibi

我的问题是我有很多文件。有时 XML 文件的结构可能是:

eligibility -> criteria -> textblock -> text
eligibility -> other things (e.g. gender as above) -> text
eligibility -> text

例如 如果有办法只取'取所有子标题及其文本'

所以在上面的例子中,列表/字典将包含: {标准文本块:纳入和排除标准,性别:xxx,minimum_age:xxx,maximum_age:xxx,health_volunteers:xxx}

我的问题是,实际上,我不会知道资格标签的所有特定子标签,因为每个实验都可能不同(例如,可能有人说“接受孕妇”、“接受 XXX 的药物史” '等)

所以我只想,如果我给它一个标签名称,它会给我字典中的所有子标签和这些子标签的文本。

用于评论的扩展 XML:

<brief_title>Subcutaneous Adaption and Cosmetic Outcome Following Caesarean Delivery</brief_title>
<source>Klinikum Klagenfurt am Wörthersee</source>

...然后是上面的资格 XML 部分。

【问题讨论】:

    标签: python xml parsing


    【解决方案1】:

    由于您已安装 lxml,您可以尝试以下操作(此代码假定给定元素中的叶元素,即 eligibility 是唯一的):

    from lxml import etree
    tree = etree.parse(sys.argv[1])
    root = tree.getroot()
    
    eligibi = []
    
    for eligibility in root.xpath('//eligibility'):
        d = {}
        for e in eligibility.xpath('.//*[not(*)]'):
            d[e.tag] = e.text
        eligibi.append(d)
    
    print eligibi
    

    XPath 解释:

    • .//* :查找当前eligibility 中的所有元素,无论其深度(//)和标签名称(*)如何
    • [not(*)] :将前一位找到的元素过滤到没有任何子元素(即叶元素)的元素

    【讨论】:

    • 请问,我很抱歉,我没有意识到您的代码将意味着我也无法打印深度仅为 1 的元素(例如,请参阅我在底部所做的编辑问题;一些 XML 文件嵌套在资格中,但其他的不像brief_title,如上所述)。使用您的方法,我无法打印brief_title 或source,因为我正在过滤掉子元素。在这种情况下,您是否会建议我以某种方式运行此函数两​​次,一次如上所述,然后一次我删除子节点的过滤器,以便我也得到只有深度为 1 的标签?谢谢
    • 尝试更改 xpath 以包含当前上下文元素(自身):descendant-or-self::*[not(*)]
    • 我发现我丢失了一些解析的数据,因为一些标签看起来像这样:&lt;enrollment type="Actual"&gt;60&lt;/enrollment&gt;;在标签有一个属性的地方,我想拔出 60 字(如果可能的话,还有“实际”,但也许这太难了)。如果有帮助,我可以在这里发布完整的代码和 XML 文件。我认为一般的想法是我需要编辑上面的sn-p代码来查看标签(例如这里的注册)是否有一个属性(比如这个注册.attrib [任何属性]然后打印标签、属性和值?我想检查这是否是正确的想法,因为我无法让它发挥作用?
    • lxml 元素模型中的属性只是一个字典,因此您可以从给定元素中获取属性值,例如:my_element.attrib["attribute_name"]。无论如何,您应该为此发布一个新问题,确保包含代表性 XML 示例和您尝试的代码
    猜你喜欢
    • 1970-01-01
    • 2015-09-08
    • 1970-01-01
    • 2012-03-17
    • 1970-01-01
    • 2020-11-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多