2015-03-10 4 views
3

Я пытаюсь добавить текстовые книги к строкам в файле XML. Если строка уже была переведена ранее, я хочу добавить @@@ и ### в начало и конец строки для дальнейшей обработки. Конечный результат будет выглядеть следующим образом:Записывая узел с текстом с элементом элемента Python

<group> 
    <seg-source> 
     <mrk mid="1" mtype="seg">I have a <g id="157">red</g> pen.</mrk> 
    </seg-source> 
    <target> 
     <mrk mid="1" mtype="seg">@@@J'ai un stylo <g id="157">rouge</g>.###</mrk> 
    </target> 
</group> 

Я пытался перед использованием xml.minidom и создал общий текстовый узел, такие как start_tag = xmldoc.createTextNode(u'@@@'), и был в состоянии вставить/добавить узлы в качестве дочерних узлов. (Я в конце концов отказался от использования minidom по разным причинам.)

я смог довольно быстро конвертировать мой скрипт из minidom в elementtree, но я застрял в этом самый ответственный момент. Я прочитал и перечитал документацию, но я не могу найти ничего конкретного в том, что мне нужно сделать, особенно потому, что многие элементы <mrk> имеют подэлементы, такие как тег <g> в примере. Кроме того, иногда первое, что находится в узле <mrk>, может не быть текстовым элементом, поэтому я просто не могу заменить текст.

Код Python довольно простой, и, как вы можете видеть, у меня есть владельцы мест для книг.

for target in group.iter('target'): 
    for mrk in target.iter('mrk'): 

     # Adding "@@@" at front of <mrk> 
     mrk.insert(0, <magical text-only element here>) 

     # Adding "###" to end of <mrk> 
     mrk.append(<magical text-only element here>) 

Большое спасибо!

ответ

2

ElementTree обрабатывает текст очень не-XML-способом. Здесь есть пара трюков. Первый заключается в том, что в <a>xxx<b>yyy</b>zzz<c>eee</c>rrr</a> способ, которым вы попадаете на «zzz», находится через tail элемента <b>. (Я знаю, XSLT mavens скрежетают зубами.)

Еще один трюк в том, что вы можете рассматривать ET Elements так, как если бы они были списком дочерних узлов. Таким образом, вы можете использовать len(root), чтобы узнать, сколько у него детей (игнорирование текстовых узлов).

Вот пример быстрой программы, которая, казалось, запускалась, когда я пробовал. Вы, вероятно, захотите настроить его на свои нужды, но вам это нужно.

import xml.etree.ElementTree as ET 

xmlin=""" 
    <group> 
     <mrk>I have a red pen.</mrk> 
     <mrk>I have a <g id="157">red</g> pen.</mrk> 
     <mrk><xyzzy>Hey!</xyzzy> I have a <g>red</g> pen.</mrk> 
     <mrk>There is text <and>this</and></mrk> 
    </group> 
""" 

root = ET.fromstring(xmlin) 

for mrk in root: 
    if (mrk.text == None): 
     mrk.text = "@@@" 
    else: 
     mrk.text = "@@@" + mrk.text 

    # do we have children? 
    if (len(mrk) == 0): 
     mrk.text = mrk.text + "###" 
    else: 
     last = mrk[len(mrk)-1] 
     if (last.tail == None): 
      last.tail = "###" 
     else: 
      last.tail = last.tail + "###" 

print('ET.tostring(root)') 
print ET.tostring(root) 
+0

Это было очень полезно. Каждый XML-модуль имеет свои недостатки и сильные стороны, и ElementTree, конечно, легче изучить \ code, чем 'minidom'. Тем не менее, ElementTree добавляет пространства имен при записи XML, поэтому при вставке текстовых узлов в «очень XML-путь» «минидомом» было лучшее решение. – Pantagrool