Редактирование плавающего текстового поля с помощью python-docx или редактирование document.xml?

Я редактирую шаблон docx, содержащий кучу плавающих изображений и текстовых полей. Я пытаюсь редактировать эти текстовые поля с помощью python-docx или напрямую редактируя document.xml. Однако похоже, что текущая итерация python-docx позволяет редактировать только встроенные «картинки» (в данном случае текстовое поле). Конечная цель - либо отредактировать текстовое поле с помощью python-docx, либо отредактировать его, открыв и отредактировав файл document.xml (в идеале без разархивирования и последующего архивирования).

До сих пор я пытался использовать python-docx для их редактирования, но, судя по моим исследованиям, текстовое поле нельзя редактировать с помощью python-docx.

Я также попытался просто отредактировать document.xml отдельно, что мне удалось сделать, однако, когда я попытался заархивировать резервные копии каталогов и изменить расширение обратно на docx, я не смог его открыть.

import lxml.etree as ET

xmlfile = r"path\document.xml"

with open(xmlfile) as f:
  tree = ET.parse(f)
  root = tree.getroot()


  for elem in root.getiterator():
    try:
      elem.text = elem.text.replace('current id in document', 'new ID in document')
    except AttributeError:
      pass

tree.write(r"path\documentedit.xml", xml_declaration=True, method='xml')

Это была моя первая распаковка docx без использования python. Затем используйте python для редактирования XML. Затем я бы заархивировал его без использования python, просто чтобы посмотреть, смогу ли я заставить его работать, но я не мог открыть документ.


person MoxGoat    schedule 14.07.2019    source источник


Ответы (1)


Есть много деталей, связанных с открытием пакета Open Packaging Convention (OPC) и его возвратом в форму, которая должна быть открыта Word.

Вы можете использовать python-docx для прямого доступа к XML, оставив при этом детали правильного сохранения (или переупаковки) на python-docx.

Если вы используете lxml, вы можете получить XML для части документа как объект lxml.etree._Element, используя document._element. Какие бы изменения вы ни внесли в это XML-дерево, они будут сохранены при вызове document.save().

Другой альтернативой является прямой доступ к тексту XML с помощью document.part.blob. Измененной версии можно присвоить (как Python 2 str / Python 3 байта) document.part._blob (обратите внимание на начальное подчеркивание), и она будет сохранена при вызове document.save().

Это избавляет вас от всех тонкостей упаковки.

person scanny    schedule 15.07.2019
comment
Спасибо, я понял, что ранее в коде исходный шаблон, который копируется в мою рабочую область, уже был распакован (разархивирован), поэтому я отредактировал doument.xml прямо из него, используя lxml намного раньше в коде, и его нужно было упаковать только один раз. Приведенное выше предложение полезно для всех, кто хочет вообще избежать упаковки / переупаковки. Некоторые примеры кода были бы полезны. Я видел ваши сообщения по многим другим темам, связанным с python-docx. - person MoxGoat; 25.07.2019
comment
document.save() не сохраняет измененное содержимое. Однако document.part._blob изменен. Что может быть причиной? - person Naazneen Jatu; 04.01.2021