我正在尝试使用一些 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 文件并逐行插入标签到不匹配的行上...
此时感谢所有帮助。
可以利用
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>