在文件的特定部分插入 XML 标签而不破坏格式

问题描述 投票:0回答:1

我正在尝试使用一些 XML 文件来进行句子标记,同时保持文件的原始结构。文件看起来像这样:

<text xml:lang="">
    <body>
      <div>
        <p>
          <p>
            <lb xml:id="p1z1" />19.
                    <lb xml:id="p1z2" />esse Christolam meam te adeo candide et humaniter Bullingere colendissime,
                    <lb xml:id="p1z3" />esse epistolam meam interpretatum. Caeterum, quod scribis te ex consilio consanguine
                    <lb xml:id="p1z4" />et affinium generi tui responsum fratri meo coram dedisse, non
                    <lb xml:id="p1z5" />possum satis mirari, qui hoc factum sit. Res enim ista ad me suum ad
                    <lb xml:id="p1z6" />fratrem pertinebat. Nec ita fueram abs te dimissus, quod vel tu tale
                    <lb xml:id="p1z7" />quid reciperes vel ego probarem, sed ita tua sponte pollicebaris vel te,
                    <lb xml:id="p1z8" />vel generum mihi per literas responsurum. Frater igitur dixit quidem
                    <lb xml:id="p1z9" />mihi te in praesentia nescio quorum (qui namque fuerint excidit) voluisse
                    <lb xml:id="p1z10" />respondere se vero voluisse recipere, imo admonuisse te ut, quemadmodum
                    <lb xml:id="p1z11" />promisisses, ita faceres. Ego simulatque tergiversationem istam cognoscere
                    <lb xml:id="p1z12" />non potui aliter interpretari quam ali fortassis aliquid monstri,
                    <lb xml:id="p1z13" />ut dicitur. Nam quae plana sunt et integra sive dicantur sive scripsisse
                    <lb xml:id="p1z14" />nihil refert. Utut sit, ego iniuriam illam, ex qua omnes istae
                    <lb xml:id="p1z15" />difficultates sunt ortae, iampridem domino deque commendavi, qui
                    <lb xml:id="p1z16" />per Mosen. Mea est ultro et ego retribuam eis in tempore.
                    <lb xml:id="p1z17" />De altero etiam capite accipio tuam excusationem. Quum enim tam sancte
                    <lb xml:id="p1z18" />affirmes te semper erga nos non aliter quam bene et fuisse et
...
...
...
        </p>
      </div>
    </body>
  </text>
</TEI>

我需要标记的句子跨越几行。这些行标有换行符标签“

<lb xml:id="n" />
。我需要以某种方式标记句子,然后将它们与原始形式一起附加到文件中。我遇到的问题是,虽然文本包含换行符,但一旦我创建句子的实例并尝试附加到换行符标记,新行字符就无效......

输出应如下所示:

<text xml:lang="">
    <body>
      <div>
        <p>
          <p>
            <lb xml:id="p1z1" /><s n="1" xml:lang="la">19.</s>
                    <lb xml:id="p1z2" /><s n="1" xml:lang="la">esse Christolam meam te adeo candide et humaniter Bullingere colendissime,
                    <lb xml:id="p1z3" />esse epistolam meam interpretatum.</s><s n="2" xml:lang="la"> Caeterum, quod scribis te ex consilio consanguine
                    <lb xml:id="p1z4" />et affinium generi tui responsum fratri meo coram dedisse, non
                    <lb xml:id="p1z5" />possum satis mirari, qui hoc factum sit.</s><s n="3" xml:lang="la"> Res enim ista ad me suum ad
                    <lb xml:id="p1z6" />fratrem pertinebat.</s><s n="4" xml:lang="la"> Nec ita fueram abs te dimissus, quod vel tu tale
                    <lb xml:id="p1z7" />quid reciperes vel ego probarem, sed ita tua sponte pollicebaris vel te,
                    <lb xml:id="p1z8" />vel generum mihi per literas responsurum.</s><s n="5" xml:lang="la"> Frater igitur dixit quidem
                    <lb xml:id="p1z9" />mihi te in praesentia nescio quorum (qui namque fuerint excidit) voluisse
                    <lb xml:id="p1z10" />respondere se vero voluisse recipere, imo admonuisse te ut, quemadmodum
                    <lb xml:id="p1z11" />promisisses, ita faceres.</s><s n="6" xml:lang="la"> Ego simulatque tergiversationem istam cognoscere
                    <lb xml:id="p1z12" />non potui aliter interpretari quam ali fortassis aliquid monstri,
                    <lb xml:id="p1z13" />ut dicitur.</s><s n="7" xml:lang="la"> Nam quae plana sunt et integra sive dicantur sive scripsisse
                    <lb xml:id="p1z14" />nihil refert.</s><s n="8" xml:lang="la"> Utut sit, ego iniuriam illam, ex qua omnes istae
                    <lb xml:id="p1z15" />difficultates sunt ortae, iampridem domino deque commendavi, qui
                    <lb xml:id="p1z16" />per Mosen.</s><s n="9" xml:lang="la"> Mea est ultro et ego retribuam eis in tempore.</s>
                    <lb xml:id="p1z17" /><s n="10" xml:lang="la">De altero etiam capite accipio tuam excusationem.</s><s n="11" xml:lang="la"> Quum enim tam sancte
                    <lb xml:id="p1z18" />affirmes te semper erga nos non aliter quam bene et fuisse et
...
...
...
       </p>
      </div>
    </body>
  </text>
</TEI>

我的代码如下所示:

import xml.etree.ElementTree as ET
from nltk.tokenize import sent_tokenize
import nltk

# Ensure NLTK's sentence tokenizer is available
nltk.download('punkt')

def remove_ns_prefix(tree):
    for elem in tree.iter():
        if '}' in elem.tag:
            elem.tag = elem.tag.split('}', 1)[1]  # Removing namespace
    return tree

def process_file(input_xml, output_xml):
    tree = ET.parse(input_xml)
    root = remove_ns_prefix(tree.getroot())

    for body in root.findall('.//body'):
        for paragraph in body.findall('.//p'):
            # Extract all lb elements and following texts
            lb_elements = list(paragraph.findall('.//lb'))
            lb_ids = [lb.attrib.get('xml:id', '') for lb in lb_elements]  # Store lb ids
            text_after_lb = [(lb.tail if lb.tail else '') for lb in lb_elements]
            
            # Combine the text and tokenize into sentences
            entire_text = ' '.join(text_after_lb)
            sentences = sent_tokenize(entire_text)
            sentences2 = " ".join(sentences).split("\n")
            print(sentences2)
            
            # Clear the paragraph's existing content
            paragraph.clear()

            # Pair up lb tags and sentences using zip, reinsert them into the paragraph
            for lb_id, sentence in zip(lb_ids, sentences):
                # Reinsert lb element
                lb_attrib = {'xml:id': lb_id} if lb_id else {}
                new_lb = ET.SubElement(paragraph, 'lb', attrib=lb_attrib)
                # Attach sentence to this lb
                if sentence:
                    sentence_elem = ET.SubElement(paragraph, 's', attrib={'xml:lang': 'la'})
                    sentence_elem.text = sentence

    # Write the modified tree to a new file
    tree.write(output_xml, encoding='utf-8', xml_declaration=True, method='xml')

我快失去理智了。希望有一位 XML 专家愿意来帮助我。

我也尝试过先添加标签,然后重新插入换行符标签,但由于 XML 的性质,这很困难。我可能会尝试的下一件事是创建临时 .txt 文件并逐行插入标签到不匹配的行上...

此时感谢所有帮助。

python xml xml-parsing nltk
1个回答
0
投票

可以利用

tail
元素的
lb
属性来完成这项工作,这些元素是此列表中索引 > 0 的元素(由
r'(\.|\n)'
正则表达式分割)。整个连接字符串然后被解析为 xml

['<lb xml:id="p1z1"/>', '19', '.', '', '\n', '            ']

该列表代表该元素;引用以显示空格

'<lb xml:id="p1z1"/>19.
                '

脚本不考虑命名空间,并作为解析技术的 POC 提供

import re
from lxml import etree
doc = etree.parse('/home/luis/tmp/tmp.xml')
# parse first file
lbs = doc.xpath('//div/p/p/lb')

all='<p>'
i=1
is_open=False
for t in lbs:
  parts = ['']
  parts.extend(re.split(r'(\.|\n)', t.tail))
  
  t.tail=None
  lstr=etree.tostring(t)
  parts[0]=etree.tostring(t).decode('utf-8')

  print(parts)
  for p, e in enumerate(parts):
    skip = (e == '' or re.match(r'^(\n|\s+)$', e) is not None)
    
    if p > 0 and not is_open and not skip:
      parts[p] = f'<s n="{i}">{e}'
      is_open=True
    elif is_open and e == '.':
      parts[p] = '.</s>'
      is_open=False
      i += 1
    elif p == len(parts) - 1:
        all += ''.join(parts)
    else:
      continue

all +='''</s>             
</p>'''

# parse the string to verify is valid xml
xfrag = etree.fromstring(all)
print(etree.tostring(xfrag).decode('utf-8'))

鉴于此示例

<text xml:lang="">
  <body>
    <div>
      <p>
        <p>
            <lb xml:id="p1z1"/>19.
            <lb xml:id="p1z2"/>esse Christolam meam te adeo candide et humaniter Bullingere colendissime,
            <lb xml:id="p1z3"/>esse epistolam meam interpretatum. Caeterum, quod scribis te ex consilio consanguine
            <lb xml:id="p1z4"/>et affinium generi tui responsum fratri meo coram dedisse, non
            <lb xml:id="p1z5"/>possum satis mirari, qui hoc factum sit. Res enim ista ad me suum ad
            <lb xml:id="p1z6"/>fratrem pertinebat. Nec ita fueram abs te dimissus, quod vel tu tale
            <lb xml:id="p1z7"/>quid reciperes vel ego probarem, sed ita tua sponte pollicebaris vel te,
            <lb xml:id="p1z8"/>vel generum mihi per literas responsurum. Frater igitur dixit quidem
            <lb xml:id="p1z9"/>mihi te in praesentia nescio quorum (qui namque fuerint excidit) voluisse
            <lb xml:id="p1z10"/>respondere se vero voluisse recipere, imo admonuisse te ut, quemadmodum
            <lb xml:id="p1z11"/>promisisses, ita faceres. Ego simulatque tergiversationem istam cognoscere
            <lb xml:id="p1z12"/>non potui aliter interpretari quam ali fortassis aliquid monstri,
            <lb xml:id="p1z13"/>ut dicitur. Nam quae plana sunt et integra sive dicantur sive scripsisse
            <lb xml:id="p1z14"/>nihil refert. Utut sit, ego iniuriam illam, ex qua omnes istae
            <lb xml:id="p1z15"/>difficultates sunt ortae, iampridem domino deque commendavi, qui
            <lb xml:id="p1z16"/>per Mosen. Mea est ultro et ego retribuam eis in tempore.
            <lb xml:id="p1z17"/>De altero etiam capite accipio tuam excusationem. Quum enim tam sancte
            <lb xml:id="p1z18"/>affirmes te semper erga nos non aliter quam bene et fuisse et
        </p>
      </p>
    </div>
  </body>
</text>

结果

<p><lb xml:id="p1z1"/><s n="1">19.</s>
            <lb xml:id="p1z2"/><s n="2">esse Christolam meam te adeo candide et humaniter Bullingere colendissime,
            <lb xml:id="p1z3"/>esse epistolam meam interpretatum.</s><s n="3"> Caeterum, quod scribis te ex consilio consanguine
            <lb xml:id="p1z4"/>et affinium generi tui responsum fratri meo coram dedisse, non
            <lb xml:id="p1z5"/>possum satis mirari, qui hoc factum sit.</s><s n="4"> Res enim ista ad me suum ad
            <lb xml:id="p1z6"/>fratrem pertinebat.</s><s n="5"> Nec ita fueram abs te dimissus, quod vel tu tale
            <lb xml:id="p1z7"/>quid reciperes vel ego probarem, sed ita tua sponte pollicebaris vel te,
            <lb xml:id="p1z8"/>vel generum mihi per literas responsurum.</s><s n="6"> Frater igitur dixit quidem
            <lb xml:id="p1z9"/>mihi te in praesentia nescio quorum (qui namque fuerint excidit) voluisse
            <lb xml:id="p1z10"/>respondere se vero voluisse recipere, imo admonuisse te ut, quemadmodum
            <lb xml:id="p1z11"/>promisisses, ita faceres.</s><s n="7"> Ego simulatque tergiversationem istam cognoscere
            <lb xml:id="p1z12"/>non potui aliter interpretari quam ali fortassis aliquid monstri,
            <lb xml:id="p1z13"/>ut dicitur.</s><s n="8"> Nam quae plana sunt et integra sive dicantur sive scripsisse
            <lb xml:id="p1z14"/>nihil refert.</s><s n="9"> Utut sit, ego iniuriam illam, ex qua omnes istae
            <lb xml:id="p1z15"/>difficultates sunt ortae, iampridem domino deque commendavi, qui
            <lb xml:id="p1z16"/>per Mosen.</s><s n="10"> Mea est ultro et ego retribuam eis in tempore.</s>
            <lb xml:id="p1z17"/><s n="11">De altero etiam capite accipio tuam excusationem.</s><s n="12"> Quum enim tam sancte
            <lb xml:id="p1z18"/>affirmes te semper erga nos non aliter quam bene et fuisse et
        </s>             
</p>
© www.soinside.com 2019 - 2024. All rights reserved.