如何在lxml / elementtree .iter()

时间:2019-02-23 16:31:25

标签: python lxml elementtree

思考以下树型迭代问题的工作方式已经打结了我的大脑,也许有些人可以帮助解决/解决问题。

我有(TEI)个XML文本,并希望按<milestone> s对其进行分段。为了标记分段,我想使用<milestone>父元素<div>属性。我认为这意味着我不能使用itertext()方法,因为它不允许我在处理文本节点时访问那些属性。因此,我的方法是使用iter()方法,将所有文本内容输入缓冲区,并在遇到里程碑元素时将其刷新到输出段(该段的标签和文本内容的字典)中。当我不在迭代中的里程碑元素上时,我将当前节点的.text写入缓冲区。

困难的是何时以及如何处理.tail文本:当我仅测试.tail的当前节点并将其附加到缓冲区时,它将出现在.text之前当前节点的子节点(实际上应该在之后),如果我不对其进行测试,我将再也没有机会抓住它,还是我弄错了?

我可以完全使用lxml的iter()还是必须构建自己的递归迭代函数? (我之前曾尝试通过XPath表达式对文本进行分段,但其性能无法接受(> 24h)。

我为冗长且混乱的xml代码段道歉,但是我无法弄清楚我可以整理或跳过哪些段落来解决这个问题。 (以及其他一些问题(例如this)由于我的XML更加混乱而无法准确应用。

感谢您的帮助。

代码:

from typing import Dict
import lxml
from lxml import etree

def segment(chapter: lxml.etree._Element) -> Dict[str, str]:
    segments = {} # this will be returned
    t = []        # this is a buffer
    chap_label = str(chapter.get("n"))
    sect_label = "0"
    for element in chapter.iter():
        if element.get("unit")=="number":
            # milestone: fill and close the previous segment:
            label = chap_label + "_" + sect_label
            segments[label] = " ".join(t)
            # reset buffer
            t = []
            # if there is text after the milestone,
            # add it as first content to the buffer
            if element.tail:
                t.append(" ".join(str.replace(element.tail, "\n", " ").strip().split()))
            # prepare for next labelmaking
            sect_label = str(element.get("n"))
        else:
            if element.text:
                t.append(" ".join(str.replace(element.text, "\n", " ").strip().split()))
            if element.tail:
                t.append(" ".join(str.replace(element.tail, "\n", " ").strip().split()))
    # all elements are processed,
    # add text remainder/current text buffer content
    label = chap_label + "_" + sect_label
    segments[label] = " ".join(t)
    return segments

nsmap = {"tei": "http://www.tei-c.org/ns/1.0"}
xp_divs = etree.XPath("(//tei:body/tei:div)", namespaces = nsmap)

segmented = {}
divs = xp_divs(document)
segments = (segment(div) for div in divs)
for d in segments:
    print(d)

输入文档(我在其中留了很多文字,因此更容易看到短语在输出文档中的结尾位置)

document=etree.fromstring("""
<TEI xmlns="http://www.tei-c.org/ns/1.0">
<text>
  <body>
    <div n="1">
      <p>
      ... <milestone unit="number" n="9"/>aun que el amor de Dios ha de ser
      grandissimo ..., como despues de. S. Tho.
      <ref target="#nm-0406">b</ref><note xml:id="nm-0406"><p>1. Sec. quaestio
      109. ar. 3.</p></note>, poco ha lo tratamos
      <ref target="#nm-0407">c</ref><note xml:id="nm-0407"><p>in addit. ca.
      Quoniam. de consec. disti. 1. nu. 10.</p></note>. Anadimos, (virtual)
      <milestone unit="number" n="10"/>porque aquella basta, ...
      <ref target="#nm-0408">d</ref><note xml:id="nm-0408"><p>in 4. dis. 14.
      q. 1. art. 3.</p></note>, que pone exemplo ..., que Gabriel sigue
      <ref target="#nm-0409">e</ref><note xml:id="nm-0409"><p>in 4. dis. 14.
      q. 1. col. 12. &amp; 13. &amp; in. 3. di. 27. q. 1. co. 15.</p></note>.
      <milestone unit="other" rendition="#asterisk"/> Y aun, aquel doctissimo,
      ... <ref target="#nm-040a">f</ref><note xml:id="nm-040a"><p>In Codice de
      poeni. q. 2.</p></note>, y con razon, ..., el martyrio atribuya esto
      <ref target="#nm-040b">g</ref><note xml:id="nm-040b"><p>Lib. 2. c. 16.
      de natu. &amp; gra.</p></note>, porque mas haze para esto el amor, ...
      que lo que se padece <ref target="#nm-040c">h</ref><note xml:id="nm-040c">
      <p>Arg. c. 13. 1. ad Corinth.</p></note>. Y puede ser que mas ame, ...,
      como lo prueua bien Medina
      <ref target="#nm-040d">i</ref><note xml:id="nm-040d"><p>in predi.
      q. 2.</p></note>. Por lo qual largamente paresce quan lexos esta esto
      dela opinion de Luthero<milestone unit="other" rendition="#asterisk"/>.
      De lo dicho se collige la razon, ..., segun Syluestro
      <ref target="#nm-040e">k</ref><note xml:id="nm-040e"><p>verb. Contritio.
      q. 1.</p></note>. Diximos <milestone unit="number" n="11"/> (auer
      pecado,) porque el arrepentimiento ...
      </p>
    </div>
  </body>
</text>
</TEI>""")

结果(出于可读性考虑,将其换行并在此处显示为csv):

1_9,"aun que el amor de Dios ha de ser grandissimo ..., como despues
     de. S. Tho. b , poco ha lo tratamos 1. Sec. quaestio 109. ar. 3.
     c . Anadimos, (virtual) in addit. ca. Quoniam. de consec. disti.
     1. nu. 10."
1_10,"porque aquella basta, ... d , que pone exemplo ..., que Gabriel
      sigue in 4. dis. 14. q. 1. art. 3. e . in 4. dis. 14. q. 1. col.
      12. & 13. & in. 3. di. 27. q. 1. co. 15. Y aun, aquel doctissimo,
      ... f, y con razon, ..., el martyrio atribuya esto In Codice de
      poeni. q. 2. g , porque mas haze para esto el amor, ... que lo que
      se padece Lib. 2. c. 16. de natu. & gra. h . Y puede ser que mas
      ame, ..., como lo prueua bien Medina Arg. c. 13. 1. ad Corinth.
      i . Por lo qual largamente paresce quan lexos esta esto dela
      opinion de Luthero in predi. q. 2. . De lo dicho se collige la
      razon, ..., segun Syluestro k . Diximos verb. Contritio. q. 1."
1_11,"(auer pecado,) porque el arrepentimiento ..."

(例如,您可以看到注释nm-0408的内容应位于“ porque aquella basta,... d”之后,但仅在“ que Gabriel sigue”之后出现。 ..)

0 个答案:

没有答案