Я борюсь с минидомом. Мне нужно найти запись в dom, обновить содержащийся в ней текст, а затем сохранить файл. До сих пор единственный способ, которым мне удалось найти конкретный элемент, - это очень явный, прямой, жестко закодированный метод:
doc.childNodes[0].childNodes[3].childNodes[5].childNodes[11].childNodes[1].childNodes[3]
Я просто хочу обновить первый <text> в <typeBox type="counter">.
<typeBoxes>
<typeBox type="counter">
<text fontSize="140">123456</text>
<text fontSize="26">Foobar</text>
<incrementTextFieldNum>1</incrementTextFieldNum>
<timing>1</timing>
<increment>1</increment>
</typeBox>
<typeBox>
<image>images/foo.png</image>
<text fontSize="26">Foo</text>-->
</typeBox>
...
Предложения?
Ответ 1 · рейтинг 4 · SingleNegationElimination
minidom не очень мощный, большинство людей в наши дни используют некоторые варианты ElementTree. В Python 2.5 и более поздних версиях он встроен.
>>> from xml.etree import ElementTree as etree
>>> corpus = """<typeBoxes>
... <typeBox type="counter">
... <text fontSize="140">123456</text>
... <text fontSize="26">Foobar</text>
... <incrementTextFieldNum>1</incrementTextFieldNum>
... <timing>1</timing>
... <increment>1</increment>
... </typeBox>
... <typeBox>
... <image>images/foo.png</image>
... <text fontSize="26">Foo</text>-->
... </typeBox>
... </typeBoxes>"""
>>>
>>> doc = etree.fromstring(corpus)
>>>
>>> for typeBox in doc.findall('typeBox'):
... if typeBox.attrib.get('type') == 'counter':
... fieldnum = int(typeBox.find('incrementTextFieldNum').text)
... incr = int(typeBox.find('increment').text)
... text_field = typeBox.findall('text')[fieldnum-1]
... text_field.text = str(int(text_field.text) + incr)
...
>>> print etree.tostring(doc)
<typeBoxes>
<typeBox type="counter">
<text fontSize="140">123457</text>
<text fontSize="26">Foobar</text>
<incrementTextFieldNum>1</incrementTextFieldNum>
<timing>1</timing>
<increment>1</increment>
</typeBox>
<typeBox>
<image>images/foo.png</image>
<text fontSize="26">Foo</text>-->
</typeBox>
</typeBoxes>
>>>
Ответ 2 · TorelTwiddler
Если вы хотите найти первый элемент в списке childNodes, попробуйте использовать:
typeBox_node = next((node for node in typeBoxs_node.childNodes \
if node.localName == 'typeBox'))
Если вы хотите сделать это для каждого элемента, попробуйте:
for typeBox_node in doc.getElementsByTagName('typeBox'):
text_node = next((node for node in typeBox_node.childNodes \
if node.localName == 'text'))