【问题标题】:lxml find all elements between two tagslxml 查找两个标签之间的所有元素
【发布时间】:2022-11-18 01:35:00
【问题描述】:

提取一个word文档并在所有书签中搜索。但是书签标签没有结束标签,所以 lxml 只找到 bookmarkStart 而不是 bookmarkStart 和 bookmarkEnd 之间的元素。如何获取 bookmarkStart 和 bookmarkEnd 中的所有元素?谢谢!

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<w:document xmlns:wpc="http://schemas.microsoft.com/office/word/2010/wordprocessingCanvas" xmlns:cx="http://schemas.microsoft.com/office/drawing/2014/chartex" xmlns:cx1="http://schemas.microsoft.com/office/drawing/2015/9/8/chartex" xmlns:cx2="http://schemas.microsoft.com/office/drawing/2015/10/21/chartex" xmlns:cx3="http://schemas.microsoft.com/office/drawing/2016/5/9/chartex" xmlns:cx4="http://schemas.microsoft.com/office/drawing/2016/5/10/chartex" xmlns:cx5="http://schemas.microsoft.com/office/drawing/2016/5/11/chartex" xmlns:cx6="http://schemas.microsoft.com/office/drawing/2016/5/12/chartex" xmlns:cx7="http://schemas.microsoft.com/office/drawing/2016/5/13/chartex" xmlns:cx8="http://schemas.microsoft.com/office/drawing/2016/5/14/chartex" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:aink="http://schemas.microsoft.com/office/drawing/2016/ink" xmlns:am3d="http://schemas.microsoft.com/office/drawing/2017/model3d" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:oel="http://schemas.microsoft.com/office/2019/extlst" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" xmlns:m="http://schemas.openxmlformats.org/officeDocument/2006/math" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:wp14="http://schemas.microsoft.com/office/word/2010/wordprocessingDrawing" xmlns:wp="http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing" xmlns:w10="urn:schemas-microsoft-com:office:word" xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main" xmlns:w14="http://schemas.microsoft.com/office/word/2010/wordml" xmlns:w15="http://schemas.microsoft.com/office/word/2012/wordml" xmlns:w16cex="http://schemas.microsoft.com/office/word/2018/wordml/cex" xmlns:w16cid="http://schemas.microsoft.com/office/word/2016/wordml/cid" xmlns:w16="http://schemas.microsoft.com/office/word/2018/wordml" xmlns:w16sdtdh="http://schemas.microsoft.com/office/word/2020/wordml/sdtdatahash" xmlns:w16se="http://schemas.microsoft.com/office/word/2015/wordml/symex" xmlns:wpg="http://schemas.microsoft.com/office/word/2010/wordprocessingGroup" xmlns:wpi="http://schemas.microsoft.com/office/word/2010/wordprocessingInk" xmlns:wne="http://schemas.microsoft.com/office/word/2006/wordml" xmlns:wps="http://schemas.microsoft.com/office/word/2010/wordprocessingShape" mc:Ignorable="w14 w15 w16se w16cid w16 w16cex w16sdtdh wp14">
    <w:body>
        <w:p w14:paraId="2DDA6990" w14:textId="44789F6F" w:rsidR="0067078D" w:rsidRDefault="003F5B0A">
            <w:bookmarkStart w:id="0" w:name="testmark"/>
            <w:proofErr w:type="spellStart"/>
            <w:r>
                <w:t>sometext</w:t>
            </w:r>
            <w:bookmarkEnd w:id="0"/>
            <w:proofErr w:type="spellEnd"/>
        </w:p>
        <w:sectPr w:rsidR="0067078D">
            <w:pgSz w:w="11906" w:h="16838"/>
            <w:pgMar w:top="1417" w:right="1417" w:bottom="1134" w:left="1417" w:header="708" w:footer="708" w:gutter="0"/>
            <w:cols w:space="708"/>
            <w:docGrid w:linePitch="360"/>
        </w:sectPr>
    </w:body>
</w:document>
from lxml import etree as ET

ns = {'w': 'http://schemas.openxmlformats.org/wordprocessingml/2006/main'}
ns2 = '{http://schemas.openxmlformats.org/wordprocessingml/2006/main}'

with open('document.xml', 'r', encoding='utf-8') as xml_file:
    tree_word = ET.parse(xml_file)

findall_param = 'w:bookmarkStart'
find_param = 'w:t'

root_word = tree_word.getroot()
field_content = tree_word.findall('.//'+findall_param, ns)

for bookmark in field_content:
    textmarker = bookmark.attrib[f"{ns2}name"]
    print(ET.tostring(bookmark))
    t = bookmark.find('.//w:t', ns)

【问题讨论】:

  • 您问题中的 xml 似乎不是实际 xml 的代表性示例 - 例如,缺少名称空间声明。请编辑您的问题并发布一个简短、格式正确、具有代表性的 xml sn-p。
  • 我用 word 中的 xml 更新了问题。
  • 好多了!所以给出新的示例 xml - 什么确切地是你的预期输出? “书签开始和书签结束内的所有元素”不够清楚。
  • 这样我就有了每个书签的内部元素。例如,我想替换 w:t 文本。 <w:t>sometext</w:t> 到 <w:t>some_new_text</w:t>。当 xml 有一个结束标记时,如 <bookmark>this 和 that</bookmark>,findall 会找到所有之间的内容,但 xml 一词没有这个。

标签: python lxml


【解决方案1】:

如果我对你的理解正确,并且基于问题中的示例 xml,以下内容应该至少让你接近你正在尝试做的事情:

word = """[your sample xml]"""
doc = etree.XML(word.encode())
ns = {'w': 'http://schemas.openxmlformats.org/wordprocessingml/2006/main'}
start_param = 'w:bookmarkStart'
t_param = 'w:t'
end_param = "bookmarkEnd"

doc.xpath(f'/{start_param}',namespaces=ns)
for el in doc.xpath(f'//w:p[.//{book_param}]//{book_param}/following-sibling::*',namespaces=ns): 
    if etree.QName(el).localname==f"{end_param}":
        break
    else:
        if len(el.xpath(f'.//{t_param}',namespaces=ns) )>0:
           el.xpath(f'.//{t_param}',namespaces=ns)[0].text="some new text"
print(etree.tostring(doc).decode())

在您的实际文档上尝试一下,看看它是否有效。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-08-03
    • 1970-01-01
    • 2011-06-11
    • 2020-02-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多