lxml是一个功能齐全的高性能Python库,用于处理XML和HTML。
Python etree 解析 html 文本失败(返回 NoneType)
为什么输出为“None”?它应该像“”或其他东西。 注意:仅在我的 Mac 上出现问题。我尝试过使用 p...
我有一些 xml,其中有多个同名元素,但每个元素都采用不同的语言,例如: 都铎王朝 <question vote="2"> <p>我有一些 xml,其中包含多个同名元素,但每个元素都采用不同的语言,例如:</p> <pre><code><Title xml:lang="FR" type="main">Les Tudors</Title> <Title xml:lang="DE" type="main">Die Tudors</Title> <Title xml:lang="IT" type="main">The Tudors</Title> </code></pre> <p>通常,我会使用其属性检索元素,如下所示:</p> <pre><code>titlex = info.find('.//xmlns:Title[@someattribute=attributevalue]', namespaces=nsmap) </code></pre> <p>如果我尝试使用 [@xml:lang="FR"] (例如)执行此操作,我会收到回溯错误:</p> <pre><code> File "D:/Python code/RBM CRID, Title, Genre/CRID, Title, Genre, Age rating, Episode Number, Descriptions V1.py", line 29, in <module> titlex = info.find('.//xmlns:Title[@xml:lang=PL]', namespaces=nsmap) File "lxml.etree.pyx", line 1457, in lxml.etree._Element.find (src\lxml\lxml.etree.c:51435) File "C:\Python34\lib\site-packages\lxml\_elementpath.py", line 282, in find it = iterfind(elem, path, namespaces) File "C:\Python34\lib\site-packages\lxml\_elementpath.py", line 272, in iterfind selector = _build_path_iterator(path, namespaces) File "C:\Python34\lib\site-packages\lxml\_elementpath.py", line 256, in _build_path_iterator selector.append(ops[token[0]](_next, token)) File "C:\Python34\lib\site-packages\lxml\_elementpath.py", line 134, in prepare_predicate token = next() File "C:\Python34\lib\site-packages\lxml\_elementpath.py", line 80, in xpath_tokenizer raise SyntaxError("prefix %r not found in prefix map" % prefix) SyntaxError: prefix 'xml' not found in prefix map </code></pre> <p>我对此并不感到惊讶,但我希望获得有关如何解决该问题的建议。</p> <p>谢谢!</p> <p>根据要求,一组精简但完整的代码(如果我删除[方括号中的位],它会按预期工作):</p> <pre><code>import lxml import codecs file_name = (input('Enter the file name, excluding .xml extension: ') + '.xml')# User inputs file name print('Parsing ' + file_name) #----- Sets up import and namespace from lxml import etree parser = lxml.etree.XMLParser() tree = lxml.etree.parse(file_name, parser) # Name of file to test goes here root = tree.getroot() nsmap = {'xmlns': 'urn:tva:metadata:2012', 'mpeg7': 'urn:tva:mpeg7:2008'} #----- This code writes the output to a file with codecs.open(file_name+'.log', mode='w', encoding='utf-8') as f: # Name the output file f.write(u'CRID|Title|Genre|Rating|Short Synopsis|Medium Synopsis|Long Synopsis\n') for info in root.xpath('//xmlns:ProgramInformation', namespaces=nsmap): titlex = info.find('.//xmlns:Title[xml:lang="PL"]', namespaces=nsmap) # Retreve the title title = titlex.text if titlex != None else 'Missing' # If there isn't a title, print an alternative word f.write(u'{}\n'.format(title)) # Write all the retrieved values to the same line with bar seperators and a new line </code></pre> </question> <answer tick="false" vote="3"> <p><strong>使用<pre><code>find()</code></pre></strong></p> <p><pre><code>xml</code></pre>中的<pre><code>xml:lang</code></pre>前缀不需要在XML文档中声明,但是如果你想在XPath查找中使用<pre><code>xml:lang</code></pre>(使用<pre><code>find()</code></pre>或<pre><code>findall()</code></pre>),你必须定义一个前缀Python 代码中的映射。</p> <p><pre><code>xml</code></pre>前缀是保留的(与任意的“正常”命名空间前缀相反)并定义为绑定到<pre><code>http://www.w3.org/XML/1998/namespace</code></pre>。请参阅 <a href="http://www.w3.org/TR/REC-xml-names/#ns-decl" rel="nofollow noreferrer">XML 1.0 中的命名空间</a> W3C 建议。</p> <p>示例:</p> <pre><code>from lxml import etree # Required mapping when using "find" nsmap = {"xml": "http://www.w3.org/XML/1998/namespace"} XML = """ <root> <Title xml:lang="FR" type="main">Les Tudors</Title> <Title xml:lang="DE" type="main">Die Tudors</Title> <Title xml:lang="IT" type="main">The Tudors</Title> </root>""" doc = etree.fromstring(XML) title_FR = doc.find('Title[@xml:lang="FR"]', namespaces=nsmap) print(title_FR.text) </code></pre> <p>输出:</p> <pre><code>Les Tudors </code></pre> <p>如果 <pre><code>xml</code></pre> 前缀没有映射,您会收到“在前缀映射中找不到<em>前缀 'xml'”错误。如果映射到 </em><code>xml</code><pre> 前缀的 URI 不是 </pre><code>http://www.w3.org/XML/1998/namespace</code><pre>,则上面代码片段中的 </pre><code>find</code><pre> 方法不会返回任何内容。</pre> </p><p>使用<strong><code>xpath()</code><pre></pre></strong> </p>使用<p><code>xpath()</code><pre>方法,不需要前缀:URI映射:</pre> </p><code>title_FR = doc.xpath('Title[@xml:lang="FR"]')[0] print(title_FR.text) </code><pre> </pre>输出:<p> </p><code>Les Tudors </code><pre> </pre> </answer> <answer tick="false" vote="0">如果您可以控制 <p><code>xml</code><pre> 文件,则应将 </pre><code>xml:lang</code><pre> 属性更改为 </pre><code>lang</code><pre> 。</pre> </p>或者如果您没有该控制权,我建议在 nsmap 中添加 <p><code>xml</code><pre>,例如 -</pre> </p><code>nsmap = {'xmlns': 'urn:tva:metadata:2012', 'mpeg7': 'urn:tva:mpeg7:2008', 'xml': '<namespace>'} </code><pre> </pre> </answer></body>
我有以下xml文件: 福 我有以下 xml 文件: <components version="1.0.0"> <component type="foo"> <sample>Foo</sample> <sample xml:lang="a">abc</sample> <sample xml:lang="b">efj</sample> </component> </components> from lxml import etree def parse(path: str): return etree.parse(path) def components(path: str) -> list: components = parse(path).xpath("/components/component") return list(components) def sample(path: str) -> str: sample = components(path)[0].find("sample").text return str(sample) path = "test.xml" print(sample(path)) 我想遍历所有 sample 标签并获取没有 xml:lang 属性的标签的值,即。第一个。我该怎么做呢?我知道我需要使用 for 循环,但不确定如何检查 xml:lang 是否存在。 您可以检查lang是否不在标签的属性中: from lxml import etree xml_string = """ <components version="1.0.0"> <component type="foo"> <sample>Foo</sample> <sample lang="a">abc</sample> <sample lang="b">efj</sample> </component> </components> """ root = etree.fromstring(xml_string) for sample in root.findall("component/sample"): if "lang" not in sample.attrib: print(sample.text) 打印: Foo 编辑:如果您有命名空间lang:,您可以尝试: from lxml import etree xml_string = """ <components version="1.0.0"> <component type="foo"> <sample>Foo</sample> <sample xml:lang="a">abc</sample> <sample xml:lang="b">efj</sample> </component> </components> """ root = etree.fromstring(xml_string) for sample in root.findall("component/sample"): # use http://www.w3.org/XML/1998/namespace here # or other Namespace URI found in your document lang = sample.attrib.get(r"{http://www.w3.org/XML/1998/namespace}lang") if not lang: print(sample.text) 您的 xml 片段有一个未关闭的标记,并且属性参数 a 和 b 必须是字符串“a”和“b”。比解析有效,你可以检查 .get('attrib_argument'): from lxml import etree as et xml_str = """<components version="1.0.0"> <component type="foo"> <sample>Foo</sample> <sample lang="a">abc</sample> <sample lang="b">efj</sample> </component> </components> """ root = et.fromstring(xml_str) for elem in root.findall('.//sample'): if elem.get('lang') is not None: pass else: print(f"sample <tag> on list position {root.findall('.//sample').index(elem)} has no 'lang' attrib, Text: {elem.text}") 输出: sample <tag> on list position 0 has no 'lang' attrib, Text: Foo
我有以下xml文件: 福 abc 我有以下 xml 文件: <components version="1.0.0"> <component type="foo"> <sample>Foo<sample> <sample lang=a>abc</sample> <sample lang=b>efj</sample> </component> </components> from lxml import etree def parse(path: str): return etree.parse(path) def components(path: str) -> list: components = parse_appinfo_xml(path).xpath("/components/component") return list(components) def sample(path: str) -> str: sample = components(path)[0].find("sample").text return str(sample) path = "test.xml" print(sample(path)) 我想遍历所有 sample 标签并获取没有 lang 属性的标签的值,即。第一个。我该怎么做呢?我知道我需要使用 for 循环,但不确定如何检查 lang 是否存在。 您可以检查lang是否不在标签的属性中: from lxml import etree xml_string = """ <components version="1.0.0"> <component type="foo"> <sample>Foo</sample> <sample lang="a">abc</sample> <sample lang="b">efj</sample> </component> </components> """ root = etree.fromstring(xml_string) for sample in root.findall("component/sample"): if "lang" not in sample.attrib: print(sample.text) 打印: Foo
我有以下xml文件: 我有以下 xml 文件: <?xml version="1.0" encoding="utf-8"?> <components version="1.0.0"> <component type="foo"> <maintag> <subtag> <check>Foo</check> </subtag> <subtag> <check></check> </subtag> <subtag> </subtag> </maintag> </component> </components> 我想检查每个 subtag 元素是否具有非空值的子元素 check。如果出现以下情况,它应该打印错误: check 存在但为空 check 根本不存在于一个或多个 subtag 中 我该怎么做? 我想出了这个,但它并没有完全达到我想要的效果 from lxml import etree # type: ignore def parse_xml(path: str) -> list: root = etree.parse(path) components = root.xpath("/components/component") return list(components) path = "test.xml" for p in parse_xml(path)[0].iter('check'): if not len(str(p)) > 0: print("check tag empty") 基本上,我的想法是: 遍历子标签列表中的每个子标签。 找到 check 元素。 如果 check_elements 列表为空(即,检查元素不存在)。打印错误消息。 否则,获取其文本内容并检查它是否为空或仅包含空格。如果是,则打印错误消息。 示例如下: # ...rest for component in components: subtags = component.xpath(".//maintag/subtag") for subtag in subtags: check_elements = subtag.xpath("./check") if not check_elements: print(f"check tag not present at line {subtag.sourceline}") else: check_element = check_elements[0] check_text = check_element.text if not check_text or check_text.strip() == "": print(f"check tag empty at line {check_element.sourceline}")
创建具有多个命名空间和 xsi:type 属性的 XML 文档
如何使用 Python 和 lxml 创建此 XML 结构? 如何使用 Python 和 lxml 创建此 XML 结构? <?xml version="1.0" encoding="utf-8"?> <cfdi:Comprobante xmlns:cfdi="http://www.sat.gob.mx/cfd/4" xmlns:cce11="http://www.sat.gob.mx/ComercioExterior11" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.sat.gob.mx/cfd/4 http://www.sat.gob.mx/sitio_internet/cfd/4/cfdv40.xsd http://www.sat.gob.mx/ComercioExterior11 http://www.sat.gob.mx/sitio_internet/cfd/ComercioExterior11/ComercioExterior11.xsd" Version="4.0" Fecha="2023-12-27T11:53:50"> <cfdi:Emisor Rfc="XAXX010101XXX" Nombre="COMPANY" RegimenFiscal="601"/> <cfdi:Receptor Rfc="XEXX010101XXX" Nombre="COMPANY" DomicilioFiscalReceptor="00000" RegimenFiscalReceptor="601" UsoCFDI="G01"/> <cfdi:Conceptos> <cfdi:Concepto ClaveProdServ="00000000" NoIdentificacion="XXXXX" Cantidad="1.000000" ClaveUnidad="EA" Unidad="PIEZA" Descripcion="XXXXX" ValorUnitario="1.00" Importe="1.00" ObjetoImp="00"> <cfdi:Impuestos> <cfdi:Traslados> <cfdi:Traslado Base="1.00" Importe="1.00" Impuesto="000" TipoFactor="Tasa" TasaOCuota="0.000000"/> </cfdi:Traslados> </cfdi:Impuestos> </cfdi:Concepto> </cfdi:Conceptos> <cfdi:Impuestos TotalImpuestosTrasladados="1.00"> <cfdi:Traslados> <cfdi:Traslado Base="1.00" Importe="1.00" Impuesto="000" TipoFactor="Tasa" TasaOCuota="0.000000"/> <cfdi:Traslado Base="1.00" Importe="1.00" Impuesto="000" TipoFactor="Tasa" TasaOCuota="0.000000"/> </cfdi:Traslados> </cfdi:Impuestos> </cfdi:Comprobante> 此结构用于墨西哥发票。 使用 Powershell 脚本。我对这些值进行了硬编码。我也硬编码了总数。 using assembly System.Xml.Linq $filename = 'c:\temp\test.xml' $emisorRfc = 'XAXX010101XXX' $receptorRfc = 'XEXX010101XXX' $nombre = 'COMPANY' $regimenFiscal = '601' $domicilioFiscalReceptor = '00000' $regimenFiscalReceptor = '601' $usoCFDI = 'G01' $claveProdServ = '00000000' $noIdentificacion = 'XXXXX' $cantidad = '1.000000' $claveUnidad = 'EA' $unidad = 'PIEZA' $descripcion = 'XXXXX' $valorUnitario = '1.00' $importe = '1.00' $objetoImp = '00' $base = '1.00' $importe = '1.00' $impuesto = '000' $tipoFactor = 'Tasa' $tasaOCuota = '0.000000' $ident = @' <?xml version="1.0" encoding="utf-8"?> <cfdi:Comprobante xmlns:cfdi="http://www.sat.gob.mx/cfd/4" xmlns:cce11="http://www.sat.gob.mx/ComercioExterior11" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.sat.gob.mx/cfd/4 http://www.sat.gob.mx/sitio_internet/cfd/4/cfdv40.xsd http://www.sat.gob.mx/ComercioExterior11 http://www.sat.gob.mx/sitio_internet/cfd/ComercioExterior11/ComercioExterior11.xsd" Version="4.0" Fecha="2023-12-27T11:53:50"> </cfdi:Comprobante> '@ $xDoc = [System.Xml.Linq.XDocument]::Parse($ident) $root = $xDoc.Root $nscfdi = $root.GetNamespaceOfPrefix('cfdi') $nscce11 = $root.GetNamespaceOfPrefix('cce11') $nsxsi = $root.GetNamespaceOfPrefix('xsdi') $emisor = [System.Xml.Linq.XElement]::new([System.Xml.Linq.XName]::Get($nscfdi + 'Emisor')) $emisorRfcAttr = [System.Xml.Linq.XAttribute]::new([System.Xml.Linq.XName]::Get('RFC'), $emisorRfc) $emisor.Add($emisorRfcAttr) $emisorNombre = [System.Xml.Linq.XAttribute]::new([System.Xml.Linq.XName]::Get('Nombre'), $nombre) $emisor.Add($emisorNombre) $emisorRegimen = [System.Xml.Linq.XAttribute]::new([System.Xml.Linq.XName]::Get('RegimenFiscal'), $regimenFiscal) $emisor.Add($emisorRegimen) $root.Add($emisor) $receptor = [System.Xml.Linq.XElement]::new([System.Xml.Linq.XName]::Get($nscfdi + 'Receptor')) $receptorRfcAttr = [System.Xml.Linq.XAttribute]::new([System.Xml.Linq.XName]::Get('RFC'), $receptorRfc) $receptor.Add($receptorRfcAttr) $receptor.Add($emisorNombre) $receptorDomicilioFiscal = [System.Xml.Linq.XAttribute]::new([System.Xml.Linq.XName]::Get('DomicilioFiscalReceptor'), $domicilioFiscalReceptor) $receptor.Add($receptorDomicilioFiscal) $receptorRegimenFiscal = [System.Xml.Linq.XAttribute]::new([System.Xml.Linq.XName]::Get('RegimenFiscalReceptor'), $regimenFiscalReceptor) $receptor.Add($receptorRegimenFiscal) $receptorUsoCFDI = [System.Xml.Linq.XAttribute]::new([System.Xml.Linq.XName]::Get('UsoCFDI'), $usoCFDI) $receptor.Add($receptorUsoCFDI) $root.Add($receptor) $conceptos = [System.Xml.Linq.XElement]::new([System.Xml.Linq.XName]::Get($nscfdi + 'Conceptos')) $concepto = [System.Xml.Linq.XElement]::new([System.Xml.Linq.XName]::Get($nscfdi + 'Concepto')) $claveProdServAttr = [System.Xml.Linq.XAttribute]::new([System.Xml.Linq.XName]::Get('ClaveProdServ'), $claveProdServ) $concepto.Add($claveProdServAttr) $noIdentificacionAttr = [System.Xml.Linq.XAttribute]::new([System.Xml.Linq.XName]::Get('NoIdentificacion'), $noIdentificacion) $concepto.Add($noIdentificacionAttr) $cantidadAttr = [System.Xml.Linq.XAttribute]::new([System.Xml.Linq.XName]::Get('Cantidad'), $cantidad) $concepto.Add($cantidadAttr) $claveUnidadAttr = [System.Xml.Linq.XAttribute]::new([System.Xml.Linq.XName]::Get('ClaveUnidad'), $claveUnidad) $concepto.Add($claveUnidadAttr) $unidadAttr = [System.Xml.Linq.XAttribute]::new([System.Xml.Linq.XName]::Get('Unidad'), $unidad) $concepto.Add($unidadAttr) $descripcionAttr = [System.Xml.Linq.XAttribute]::new([System.Xml.Linq.XName]::Get('Descripcion'), $descripcion) $concepto.Add($descripcionAttr) $valorUnitarioAttr = [System.Xml.Linq.XAttribute]::new([System.Xml.Linq.XName]::Get('ValorUnitario'), $valorUnitario) $concepto.Add($valorUnitarioAttr) $importeAttr = [System.Xml.Linq.XAttribute]::new([System.Xml.Linq.XName]::Get('Importe'), $importe) $concepto.Add($importeAttr) $objetoImpAttr = [System.Xml.Linq.XAttribute]::new([System.Xml.Linq.XName]::Get('ObjetoImp'), $objetoImp) $concepto.Add($objetoImpAttr) $impuestos = [System.Xml.Linq.XElement]::new([System.Xml.Linq.XName]::Get($nscfdi + 'Impuestos')) $traslados = [System.Xml.Linq.XElement]::new([System.Xml.Linq.XName]::Get($nscfdi + 'Traslados')) $traslado = [System.Xml.Linq.XElement]::new([System.Xml.Linq.XName]::Get($nscfdi + 'Traslado')) $baseAttr = [System.Xml.Linq.XAttribute]::new([System.Xml.Linq.XName]::Get('Base'), $base) $traslado.Add($baseAttr) $importeAttr = [System.Xml.Linq.XAttribute]::new([System.Xml.Linq.XName]::Get('Importe'), $importe) $traslado.Add($importeAttr) $impuestoAttr = [System.Xml.Linq.XAttribute]::new([System.Xml.Linq.XName]::Get('Impuesto'), $impuesto) $traslado.Add($impuestoAttr) $tipoFactorAttr = [System.Xml.Linq.XAttribute]::new([System.Xml.Linq.XName]::Get('TipoFactor'), $tipoFactor) $traslado.Add($tipoFactorAttr) $tasaOCuotaAttr = [System.Xml.Linq.XAttribute]::new([System.Xml.Linq.XName]::Get('TasaOCuota'), $tasaOCuota) $traslado.Add($tasaOCuotaAttr) $traslados.Add($traslado) $impuestos.Add($traslados) $concepto.Add($impuestos) $conceptos.Add($concepto) $root.Add($conceptos) $impuestos = [System.Xml.Linq.XElement]::new([System.Xml.Linq.XName]::Get($nscfdi + 'Impuestos')) $totalImpuestosTrasladados = '1.00' $totalImpuestosTrasladadosAttr = [System.Xml.Linq.XAttribute]::new([System.Xml.Linq.XName]::Get('TotalImpuestosTrasladados'), $totalImpuestosTrasladados) $impuestos.Add($totalImpuestosTrasladadosAttr) $root.Add($impuestos) $xDoc.Save($filename)
BS4:从BeautifulSoup对象获取lxml etree
如果我将 BeautifulSoup4 与 lxml 解析器一起使用,如何从 BeautifulSoup 对象获取 lxml etree 对象? 我会用它通过 XPath 查找元素。 BeautifulSoup4 本身不支持 XPath
我正在尝试解析一个xml文件,以便我可以操作其中包含的数据。 它有 900 万行,所以我不会发布它。 这是我的代码: 从 lxml 导入 etree 解析器 = etree.XMLPar...
我使用 lxml 从 html 页面检索标签的属性。 html 页面的格式如下: ... 我使用 lxml 从 html 页面检索标签的属性。 html 页面的格式如下: <div class="my_div"> <a href="/foobar"> <img src="my_img.png"> </a> </div> 我用来检索 <a> 标签内的 url 以及同一 src 内 <img> 标签的 <div> 值的 python 脚本是这样的: from lxml import html ... tree = html.fromstring(page.text) for element in tree.xpath('//div[contains(@class, "my_div")]//a'): href = element.xpath('/@href') src = element.xpath('//img/@src') 为什么我拿不到琴弦? 您正在使用 lxml,因此您正在使用 lxml 对象 - HtmlElement 实例进行操作。 HtmlElement 嵌套在 etree.Element 中:http://lxml.de/api/lxml.etree._Element-class.html, 它有 get 方法,返回属性值。 所以适合你的方法是: from lxml import html ... tree = html.fromstring(page.text) for link_element in tree.xpath('//div[contains(@class, "my_div")]//a'): href = link_element.get('href') image_element = href.find('img') if image_element: img_src = image_element.get('src') 如果您将代码更改为: from lxml import html ... tree = html.fromstring(page.text) for element in tree.xpath('//div[contains(@class, "my_div")]//a'): href = element.items()[0][1] #gives you the value corresponding to the key "href" src = element.xpath('//img/@src')[0] print(href, src) 你会得到你需要的。 lxml的文档提到了其中一些内容,但我觉得它缺少一些内容,您可能需要考虑使用交互式Python shell来研究tree.xpath()返回的实例的属性。或者你可以完全研究另一个解析器,例如 BeautifulSoup,它有非常好的示例和文档。只是分享... 您没有获得想要的结果的原因是因为您试图从 NEXT 子节点而不是现有节点获取属性。 看这个: from lxml import html s = '''<div class="my_div"> <a href="/foobar"> <img src="my_img.png"> </a> </div>''' tree = html.fromstring(s) # when you do path... //a, you are ALREADY at 'a' node for el in tree.xpath('//div[contains(@class, "my_div")]//a'): # you were trying to get next children /@href, which doesn't exist print el.xpath('@href') # you should instead access the existing node's print el.xpath('img/@src') # same here, not /img/@src ... ['/foobar'] ['my_img.png'] 希望这有帮助。
我在从 xml 文件中提取文本时遇到问题,但我的代码不允许我获得我期望获得的内容。 这是代码的一部分。 根 = etree.fromstring(xml) 标题 = root.findall('
python lxml 添加/修改/替换 html 元素的innerHTML
我正在使用 lxml 来解析示例 html。像这样: 导入lxml.html __dom = lxml.html.fromstring("") ...
python lxml xpath 查询在硬编码的 url 上失败,但适用于字节字符串
我正在尝试从文本标签中提取 xml 属性 parsable-cite 。我正在从 url“https://www.congress.gov/118/bills/hr61/BILLS-118hr61ih.xml”解析 xml。 我正在使用的代码...
无法在python中使用docx lib,无法从lxml导入etree
我在尝试使用 python 操作 MS 文档时遇到了这个问题。 我面临的错误是这样的: 回溯(最近一次调用最后一次): 文件“C:\Users\user\Desktop\Report Writer\
我必须转换一些漂亮的汤代码。 基本上我想要的只是获取主体节点的所有子节点并选择其中包含文本并存储它们。 这是 bs4 的代码: def get_children(se...
我需要根据属性的内容,使用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>
有没有办法使用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>
我正在尝试解析从网络检索的 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 解析”的部分,其中几乎包含您需要的所有信息。
使用 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-
我需要安装lxml 4.9.2,因为我使用其他库,但我有这个错误 错误:无法为 lxml 构建轮子,这是安装基于 pyproject.toml 的项目所必需的 我用窗户 我试过了