lxml 相关问题

lxml是一个功能齐全的高性能Python库,用于处理XML和HTML。

如何删除lxml中的元素

我需要根据属性的内容,使用python的lxml完全删除元素。例子: 将 lxml.etree 导入为 et xml=""" 我需要使用 python 的 lxml 根据属性的内容完全删除元素。示例: import lxml.etree as et xml=""" <groceries> <fruit state="rotten">apple</fruit> <fruit state="fresh">pear</fruit> <fruit state="fresh">starfruit</fruit> <fruit state="rotten">mango</fruit> <fruit state="fresh">peach</fruit> </groceries> """ tree=et.fromstring(xml) for bad in tree.xpath("//fruit[@state=\'rotten\']"): #remove this element from the tree print et.tostring(tree, pretty_print=True) 我想打印: <groceries> <fruit state="fresh">pear</fruit> <fruit state="fresh">starfruit</fruit> <fruit state="fresh">peach</fruit> </groceries> 有没有办法在不存储临时变量并手动打印的情况下执行此操作,如: newxml="<groceries>\n" for elt in tree.xpath('//fruit[@state=\'fresh\']'): newxml+=et.tostring(elt) newxml+="</groceries>" 使用 xmlElement 的 remove 方法: tree=et.fromstring(xml) for bad in tree.xpath("//fruit[@state=\'rotten\']"): bad.getparent().remove(bad) # here I grab the parent of the element to call the remove directly on it print et.tostring(tree, pretty_print=True, xml_declaration=True) 如果我必须与 @Acorn 版本进行比较,即使要删除的元素不直接位于 xml 的根节点下,我的版本也会工作。 您正在寻找 remove 功能。调用树的删除方法并向其传递一个要删除的子元素。 import lxml.etree as et xml=""" <groceries> <fruit state="rotten">apple</fruit> <fruit state="fresh">pear</fruit> <punnet> <fruit state="rotten">strawberry</fruit> <fruit state="fresh">blueberry</fruit> </punnet> <fruit state="fresh">starfruit</fruit> <fruit state="rotten">mango</fruit> <fruit state="fresh">peach</fruit> </groceries> """ tree=et.fromstring(xml) for bad in tree.xpath("//fruit[@state='rotten']"): bad.getparent().remove(bad) print et.tostring(tree, pretty_print=True) 结果: <groceries> <fruit state="fresh">pear</fruit> <fruit state="fresh">starfruit</fruit> <fruit state="fresh">peach</fruit> </groceries> 我遇到过一种情况: <div> <script> some code </script> text here </div> div.remove(script) 将删除我无意的 text here 部分。 按照here的答案,我发现etree.strip_elements对我来说是一个更好的解决方案,您可以通过with_tail=(bool)参数控制是否删除后面的文本。 但是我仍然不知道这是否可以使用xpath过滤器作为标签。只是为了通知而已。 这是文档: strip_elements(tree_or_element, *tag_names, with_tail=True) 从树中删除具有提供的标签名称的所有元素或 子树。这将删除元素及其整个子树, 包括它们的所有属性、文本内容和后代。它 还将删除元素的尾部文本,除非您 明确将 with_tail 关键字参数选项设置为 False。 标签名称可以包含通配符,如 _Element.iter。 请注意,这不会删除该元素(或 ElementTree 根 元素)您传递的即使它匹配。它只会治疗 它的后代。如果要包含根元素,请选中 在调用此函数之前就直接使用其标签名称。 使用示例:: strip_elements(some_element, 'simpletagname', # non-namespaced tag '{http://some/ns}tagname', # namespaced tag '{http://some/other/ns}*' # any tag from a namespace lxml.etree.Comment # comments ) 正如已经提到的,您可以使用 remove() 方法从树中删除(子)元素: for bad in tree.xpath("//fruit[@state=\'rotten\']"): bad.getparent().remove(bad) 但是它会删除包括其 tail 在内的元素,如果您正在处理 HTML 之类的混合内容文档,这是一个问题: <div><fruit state="rotten">avocado</fruit> Hello!</div> 成为 <div></div> 我想这就是你并不总是想要的:) 我创建了辅助函数来仅删除元素并保留其尾部: def remove_element(el): parent = el.getparent() if el.tail.strip(): prev = el.getprevious() if prev: prev.tail = (prev.tail or '') + el.tail else: parent.text = (parent.text or '') + el.tail parent.remove(el) for bad in tree.xpath("//fruit[@state=\'rotten\']"): remove_element(bad) 这样它将保留尾部文本: <div> Hello!</div> 您还可以使用 lxml 中的 html 来解决这个问题: from lxml import html xml=""" <groceries> <fruit state="rotten">apple</fruit> <fruit state="fresh">pear</fruit> <fruit state="fresh">starfruit</fruit> <fruit state="rotten">mango</fruit> <fruit state="fresh">peach</fruit> </groceries> """ tree = html.fromstring(xml) print("//BEFORE") print(html.tostring(tree, pretty_print=True).decode("utf-8")) for i in tree.xpath("//fruit[@state='rotten']"): i.drop_tree() print("//AFTER") print(html.tostring(tree, pretty_print=True).decode("utf-8")) 它应该输出这个: //BEFORE <groceries> <fruit state="rotten">apple</fruit> <fruit state="fresh">pear</fruit> <fruit state="fresh">starfruit</fruit> <fruit state="rotten">mango</fruit> <fruit state="fresh">peach</fruit> </groceries> //AFTER <groceries> <fruit state="fresh">pear</fruit> <fruit state="fresh">starfruit</fruit> <fruit state="fresh">peach</fruit> </groceries> remove 函数从树中分离元素,因此删除 XML 节点(元素、PI 或注释)、其内容(后代项)和 tail 文本。在这里,保留 tail 文本是多余的,因为它只包含空格和换行符,可以将其视为可忽略的空格。 要删除元素(及其内容),保留其 tail,您可以使用以下函数: def remove_node(child, keep_content=False): """ Remove an XML element, preserving its tail text. :param child: XML element to remove :param keep_content: ``True`` to keep child text and sub-elements. """ parent = child.getparent() parent_text = parent.text or u"" prev_node = child.getprevious() if keep_content: # insert: child text child_text = child.text or u"" if prev_node is None: parent.text = u"{0}{1}".format(parent_text, child_text) or None else: prev_tail = prev_node.tail or u"" prev_node.tail = u"{0}{1}".format(prev_tail, child_text) or None # insert: child elements index = parent.index(child) parent[index:index] = child[:] # insert: child tail parent_text = parent.text or u"" prev_node = child.getprevious() child_tail = child.tail or u"" if prev_node is None: parent.text = u"{0}{1}".format(parent_text, child_tail) or None else: prev_tail = prev_node.tail or u"" prev_node.tail = u"{0}{1}".format(prev_tail, child_tail) or None # remove: child parent.remove(child) 这是一个演示: from lxml import etree tree = etree.XML(u"<root>text <bad>before <bad>inner</bad> after</bad> tail</root>") bad1 = tree.xpath("//bad[1]")[0] remove_node(bad1) etree.dump(tree) # <root>text tail</root> 如果您想保留内容,您可以这样做: tree = etree.XML(u"<root>text <bad>before <bad>inner</bad> after</bad> tail</root>") bad1 = tree.xpath("//bad[1]")[0] remove_node(bad1, keep_content=True) etree.dump(tree) # <root>text before <bad>inner</bad> after tail</root>

回答 6 投票 0

有没有办法使用elementtree更改具有相同标签但不同元素的XML元素

所以我有一个 XML,其中有多行出生日期,但元素不同。 例如,在我的 XML 中,我有以下几行: 1998年3月12日 所以我有一个 XML,其中有多行出生日期,但元素不同。 例如,在我的 XML 中,我有以下几行: <date-of-birth>12-3-1998</date-of-birth> <date-of-birth>12-3-1998</date-of-birth> <date-of-birth>12-3-1998</date-of-birth> <date-of-birth>31-7-1941</date-of-birth> <date-of-birth>23-11-1965</date-of-birth> 我想将仅具有 DOB "12-3-1998" 的行更改为具有 DOB "14-11-2001" 并保持其他行不变,但我正在努力找出如何在不更改所有行或不更改任何行的情况下执行此操作。 我尝试这样做: import xml.etree.ElementTree as ET xml_tree = ET.parse(TestXML.xml) root = xml_tree.getroot() for DOB in root.findall(".//{*}12-3-1998"): DOB.text = "14-11-2001" ET.tostring(root) 但是我的root.findall(".//{*}12-3-1998")没有找到任何东西,所以我所有的出生日期都保持不变 我尝试执行以下操作,但它更改了我的所有 DOB 元素,而我只想更改具有“12-3-1998”的元素: import xml.etree.ElementTree as ET xml_tree = ET.parse(TestXML.xml) root = xml_tree.getroot() for DOB in root.findall(".//{*}date-of-birth"): DOB.text = "14-11-2001" ET.tostring(root) 所以我想知道是否有一种方法可以过滤我想要更改的特定 DOB 是否使用 elementtree 和/或另一个 Python 库? IIUC,你可以这样做: import xml.etree.ElementTree as ET data = """ <data> <date-of-birth>12-3-1998</date-of-birth> <date-of-birth>12-3-1998</date-of-birth> <date-of-birth>12-3-1998</date-of-birth> <date-of-birth>31-7-1941</date-of-birth> <date-of-birth>23-11-1965</date-of-birth> </data> """ root = ET.fromstring(data) for dob in root.findall("date-of-birth"): if dob.text == "12-3-1998": dob.text = "14-11-2001" print(ET.tostring(root).decode("utf-8")) 打印: <data> <date-of-birth>14-11-2001</date-of-birth> <date-of-birth>14-11-2001</date-of-birth> <date-of-birth>14-11-2001</date-of-birth> <date-of-birth>31-7-1941</date-of-birth> <date-of-birth>23-11-1965</date-of-birth> </data>

回答 1 投票 0

使用Python lxml时出现“无法加载外部实体”错误

我正在尝试解析从网络检索的 XML 文档,但解析后崩溃并出现以下错误: ': 加载外部实体失败“ 我正在尝试解析从网络检索的 XML 文档,但解析后出现此错误,它崩溃了: ': failed to load external entity "<?xml version="1.0" encoding="UTF-8"?> <?xml-stylesheet type="text/xsl" href="GreenButtonDataStyleSheet.xslt"?> 这是下载的 XML 中的第二行。有没有办法阻止解析器尝试加载外部实体,或者有其他方法来解决这个问题?这是我到目前为止的代码: import urllib2 import lxml.etree as etree file = urllib2.urlopen("http://www.greenbuttondata.org/data/15MinLP_15Days.xml") data = file.read() file.close() tree = etree.parse(data) 与 mzjn 所说的一致,如果你确实想将字符串传递给 etree.parse(),只需将其包装在 StringIO 对象中即可。 示例(python2): from lxml import etree from StringIO import StringIO myString = "<html><p>blah blah blah</p></html>" tree = etree.parse(StringIO(myString)) 示例 (python3) 从 io 而不是 StringIO 导入: from lxml import etree from io import StringIO myString = "<html><p>blah blah blah</p></html>" tree = etree.parse(StringIO(myString)) 此方法在lxml文档中使用。 etree.parse(source)预计source成为其中之一 文件名/路径 文件对象 类似文件的对象 使用 HTTP 或 FTP 协议的 URL 问题在于您以字符串形式提供 XML 内容。 您也可以不使用urllib2.urlopen()。只需使用 tree = etree.parse("http://www.greenbuttondata.org/data/15MinLP_15Days.xml") 演示(使用lxml 2.3.4): >>> from lxml import etree >>> tree = etree.parse("http://www.greenbuttondata.org/data/15MinLP_15Days.xml") >>> tree.getroot() <Element {http://www.w3.org/2005/Atom}feed at 0xedaa08> >>> 在竞争答案中,建议lxml失败,因为文档中的处理指令引用了样式表。但这不是这里的问题。 lxml 不会尝试加载样式表,并且如果按照上述操作,XML 文档就可以很好地解析。 如果你想实际加载样式表,你必须明确它。需要这样的东西: from lxml import etree tree = etree.parse("http://www.greenbuttondata.org/data/15MinLP_15Days.xml") # Create an _XSLTProcessingInstruction object pi = tree.xpath("//processing-instruction()")[0] # Parse the stylesheet and return an ElementTree xsl = pi.parseXSL() 用于解析的 lxml 文档说 要从字符串解析,请使用 fromstring() 函数。 parse(...) parse(source, parser=None, base_url=None) Return an ElementTree object loaded with source elements. If no parser is provided as second argument, the default parser is used. The ``source`` can be any of the following: - a file name/path - a file object - a file-like object - a URL using the HTTP or FTP protocol To parse from a string, use the ``fromstring()`` function instead. Note that it is generally faster to parse from a file path or URL than from an open file object or file-like object. Transparent decompression from gzip compressed sources is supported (unless explicitly disabled in libxml2). 您收到该错误是因为您正在加载的 XML 引用了外部资源: <?xml-stylesheet type="text/xsl" href="GreenButtonDataStyleSheet.xslt"?> LXML 不知道如何解析 GreenButtonDataStyleSheet.xslt。你和我可能意识到,它将相对于你的原始 URL 可用,http://www.greenbuttondata.org/data/15MinLP_15Days.xml...诀窍是告诉 lxml 如何加载它。 lxml 文档 包含标题为“文档加载和 URL 解析”的部分,其中几乎包含您需要的所有信息。

回答 4 投票 0

使用 Python 3.11.6 和 pip 23.3.1 在 Android 10 上的 Termux 上安装 lxml 时出现问题

pip 安装 lxml python setup.py bdist_wheel 未成功运行。 │ 退出代码:1 ╰─>【174行输出】 构建 lxml 版本 4.9.3。 /data/data/com.termux/files/usr/tmp/pip-

回答 1 投票 0

无法在windows上安装lxml

我需要安装lxml 4.9.2,因为我使用其他库,但我有这个错误 错误:无法为 lxml 构建轮子,这是安装基于 pyproject.toml 的项目所必需的 我用窗户 我试过了

回答 1 投票 0

beautifulsoup 上下文中 lxml 和 html5lib 的区别

在 beautifulsoup 的上下文中,lxml 和 html5lib 解析器的功能有区别吗?我正在尝试学习使用 BS4 并使用以下代码构造 - ret = 请求...

回答 2 投票 0

使用lxml xpath解析

我试图实现一个lxml,xpath代码来解析链接中的html:https://www.theice.com/productguide/ProductSpec.shtml?specId=251 具体来说,我试图解析

回答 3 投票 0

使用 LXML 在 Python 中查找字符串的 XPath

我正在尝试开发一个Python脚本,以便轻松提取XML或HTML文件中元素的XPath。 例如,假设我们有下面的 XML 文件 (test.xml),我们希望获得...

回答 1 投票 0

lxml 将元素转换为elementtree

以下测试代码读取文件,并使用lxml.html生成页面的DOM/Graph的叶节点。 然而,我也在试图弄清楚如何从“字符串”中获取输入......

回答 3 投票 0

AttributeError:“NoneType”对象没有属性“get_text” - 即使有一次显示价格,此错误仍不断显示

导入请求 从 bs4 导入 BeautifulSoup 导入lxml 网址 = 'https://www.amazon.com/dp/B075CYMYK6?ref_=cm_sw_r_cp_ud_ct_FM9M699VKHTT47YD50Q6&th=1' 标题={ “用户代理”:“

回答 1 投票 0

如何在 XML 文档上应用一组结构化的、通用的、嵌套的过滤器?

我有一组 XML 文档,需要根据父级上的一组条件进行过滤,以及匹配父级的后代上的一组过滤器。我希望用户能够编写一组

回答 1 投票 0

如何使用0(1)内存的lxml?

我正在尝试使用 ~72G XML 文件。我想将其转换为 CSV。 这是我假设在后台使用迭代器的代码,因为我可能在有关 lxml 的地方读过它。 来自

回答 1 投票 0

在lxml中设置默认命名空间映射

当使用 lxml 处理 XML 时,我的代码最终如下所示: 从 lxml 导入 etree NSMAP = { 'ns1': 'https://example.com/ns1/', 'ns2': 'https://example.com/ns2/', } 根= etree.p...

回答 1 投票 0

如何在Python中添加/使用库(3.5.1)

我最近一直在玩Python,现在已经扩展到做一些事情,比如抓取网站和其他很酷的东西,我需要为这些东西导入新的库,比如lxml,

回答 2 投票 0

使用lxml从href解析实际链接[重复]

使用jupyter笔记本,python 3。 我正在从网上下载一些文件,其中大部分是在本地批量下载的。这些文件列在网页上,但位于 href 属性中。我找到的代码给出了...

回答 1 投票 0

lxml iterparse 会占用 4GB XML 文件的内存,即使使用了clear() 也是如此

该脚本的目的是提取每年出版的文章/书籍的数量,并从 xml 文件 dblp-2023-10-01.xml 中的元素获取此信息。该文件可以找到...

回答 1 投票 0

添加/追加新的 xml 节点到现有 xml 文件 - python

我有一个如下所示的xml文件 a1 我有一个如下所示的 xml 文件 <add-g> <entry name="g1"> <static> <member>a1</member> </static> </entry> <entry name="g2"> <static> <member>a1</member> </static> </entry> </add-g> 我需要在同一个 xml 文件中附加另一个条目名称,例如 g3 和成员 a3,以便最终结构为: 如何使用 lxml 在 python 中执行此操作 <add-g> <entry name="g1"> <static> <member>a1</member> </static> </entry> <entry name="g2"> <static> <member>a1</member> </static> </entry> <entry name="g3"> <static> <member>a1</member> </static> </entry> </add-g> 请先尝试并在此处发布您的问题。 这就是您实现目标的方法。 from lxml import etree # Load your XML xml_string = '''<add-g> <entry name="g1"> <static> <member>a1</member> </static> </entry> <entry name="g2"> <static> <member>a1</member> </static> </entry> </add-g>''' # Parse the XML root = etree.fromstring(xml_string) # Create new entry new_entry = etree.Element("entry", name="g3") new_static = etree.SubElement(new_entry, "static") new_member = etree.SubElement(new_static, "member") new_member.text = "a3" # Append the new entry to the root element root.append(new_entry) # Convert back to string (or write to file) updated_xml = etree.tostring(root, pretty_print=True, xml_declaration=True, encoding="UTF-8") print(updated_xml.decode())

回答 1 投票 0

legacy-install-failure × 尝试安装包时遇到错误 - lxml

我正在尝试在我的 AMD win11 笔记本电脑上安装 harwest。 当我尝试使用 pip install harwest 安装它时,我得到以下输出 采集收获 使用缓存的 harwest-0.3....

回答 1 投票 0

如果我想要保留一组给定的元素,如何从 lxml 树中删除项目?

我正在编写一个Python xml(netconf)解析器,目标是从服务器获取rpc-reply xml,修改一些项目,并生成一个最小的配置.xml,然后可以将其发送到服务器。 当

回答 3 投票 0

使用 lxml 在文本前添加元素

我有一些 XML,我想在文本之前插入一个新元素。 我试过: 从 lxml 导入 etree xml =“一些文本” 根 = etree.froms...

回答 1 投票 0

© www.soinside.com 2019 - 2024. All rights reserved.