首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Python lxml高效查找文本

Python lxml高效查找文本
EN

Stack Overflow用户
提问于 2021-06-30 18:14:41
回答 3查看 38关注 0票数 0

使用python lxml,我想测试XML文档是否包含EXPERIMENT_TYPE,如果存在,则提取。

示例:

代码语言:javascript
复制
<EXPERIMENT_SET>
  <EXPERIMENT center_name="BCCA" alias="Experiment-pass_2.0">
    <TITLE>WGBS (whole genome bisulfite sequencing) analysis of SomeSampleA (library: SomeLibraryA).</TITLE>
    <STUDY_REF accession="SomeStudy" refcenter="BCCA"/>
    <EXPERIMENT_ATTRIBUTES>
      <EXPERIMENT_ATTRIBUTE><TAG>EXPERIMENT_TYPE</TAG><VALUE>DNA Methylation</VALUE></EXPERIMENT_ATTRIBUTE>
      <EXPERIMENT_ATTRIBUTE><TAG>EXPERIMENT_ONTOLOGY_URI</TAG><VALUE>http://purl.obolibrary.org/obo/OBI_0001863</VALUE></EXPERIMENT_ATTRIBUTE>
      <EXPERIMENT_ATTRIBUTE><TAG>EXPERIMENT_ONTOLOGY_CURIE</TAG><VALUE>obi:0001863</VALUE></EXPERIMENT_ATTRIBUTE>
      <EXPERIMENT_ATTRIBUTE><TAG>MOLECULE</TAG><VALUE>genomic DNA</VALUE></EXPERIMENT_ATTRIBUTE>
    </EXPERIMENT_ATTRIBUTES>
  </EXPERIMENT>
</EXPERIMENT_SET>

有没有比遍历所有元素更快的方法?

代码语言:javascript
复制
    all = etree.findall('EXPERIMENT/EXPERIMENT_ATTRIBUTES/EXPERIMENT_ATTRIBUTE/TAG')
    
    for e in all:
        if e.text == 'EXPERIMENT_TYPE':
            print("Found")

当我想要提取的时候,这种尝试也变得很混乱。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2021-06-30 19:00:26

你最好用XPath来做这件事,这肯定是非常快的。我的建议(测试和工作)。它将返回一个(可能为空的) VALUE元素列表,您可以从中获得额外的text

PS:不要使用诸如all之类的“特殊”字作为变量名。糟糕的实践可能会导致意想不到的错误。

代码语言:javascript
复制
import lxml.etree as ET
from lxml.etree import Element
from typing import List

xml_str = """
<EXPERIMENT_SET>
  <EXPERIMENT center_name="BCCA" alias="Experiment-pass_2.0">
    <TITLE>WGBS (whole genome bisulfite sequencing) analysis of SomeSampleA (library: SomeLibraryA).</TITLE>
    <STUDY_REF accession="SomeStudy" refcenter="BCCA"/>
    <EXPERIMENT_ATTRIBUTES>
      <EXPERIMENT_ATTRIBUTE><TAG>EXPERIMENT_TYPE</TAG><VALUE>DNA Methylation</VALUE></EXPERIMENT_ATTRIBUTE>
      <EXPERIMENT_ATTRIBUTE><TAG>EXPERIMENT_ONTOLOGY_URI</TAG><VALUE>http://purl.obolibrary.org/obo/OBI_0001863</VALUE></EXPERIMENT_ATTRIBUTE>
      <EXPERIMENT_ATTRIBUTE><TAG>EXPERIMENT_ONTOLOGY_CURIE</TAG><VALUE>obi:0001863</VALUE></EXPERIMENT_ATTRIBUTE>
      <EXPERIMENT_ATTRIBUTE><TAG>MOLECULE</TAG><VALUE>genomic DNA</VALUE></EXPERIMENT_ATTRIBUTE>
    </EXPERIMENT_ATTRIBUTES>
  </EXPERIMENT>
</EXPERIMENT_SET>
"""


tree = ET.ElementTree(ET.fromstring(xml_str))
vals: List[Element] = tree.xpath(".//EXPERIMENT_ATTRIBUTE/TAG[text()='EXPERIMENT_TYPE']/following-sibling::VALUE")
print(vals[0].text)
# DNA Methylation

Michael Kay在下面提供了一个替代的XPath声明,该声明与Martin Honnen的答案相同。

代码语言:javascript
复制
.//EXPERIMENT_ATTRIBUTE[TAG='EXPERIMENT_TYPE']/VALUE
票数 1
EN

Stack Overflow用户

发布于 2021-06-30 18:21:09

就XPath而言,您似乎只需要使用/EXPERIMENT_SET/EXPERIMENT/EXPERIMENT_ATTRIBUTES/EXPERIMENT_ATTRIBUTE[TAG = 'EXPERIMENT_TYPE']/VALUE等标记元素来选择VALUE元素。

我认为在Python和lxml中,人们经常使用文本节点选择,例如/EXPERIMENT_SET/EXPERIMENT/EXPERIMENT_ATTRIBUTES/EXPERIMENT_ATTRIBUTE[TAG = 'EXPERIMENT_TYPE']/VALUE/text(),然后xpath函数将其作为Python字符串返回。

票数 0
EN

Stack Overflow用户

发布于 2021-06-30 18:50:17

使用findall是一种很自然的方式。我建议使用以下代码来查找这些值:

代码语言:javascript
复制
from lxml import etree

root = etree.parse('toto.xml').getroot()

all = root.findall('EXPERIMENT/EXPERIMENT_ATTRIBUTES/EXPERIMENT_ATTRIBUTE/TAG')
for e in all:
    if e.text == 'EXPERIMENT_TYPE':
        v = e.getparent().find('VALUE')
        if v is not None:
            print(f'Found val="{v.text}"')

这将输出以下内容:

代码语言:javascript
复制
Found val="DNA Methylation"
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/68192833

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档