Ich erinnerte mich an ein altes Sprichwort, "benutze die Quelle, Luke!", Und konnte es herausfinden. Ein Post von Python-Docx-Besitzer auf seiner Git-Projektseite gab mir auch einen Hinweis: https://github.com/python-openxml/python-docx/issues/7.
Das vollständige XML-Dokumentmodell kann mit der Eigenschaft _document_part._element
erreicht werden. Es verhält sich genau wie ein lxml-etree-Element. Von dort ist alles möglich.
Um mein spezifisches Einfügepunktproblem zu lösen, habe ich ein temporäres docx.Document-Objekt erstellt, mit dem ich meinen generierten Inhalt speichern konnte.
import docx
from docx.oxml.shared import qn
tmp_doc = docx.Document()
# Generate content in tmp_doc document
tmp_doc.add_heading('New heading', 1)
# more content generation using docx API.
# ...
# Reference the tmp_doc XML content
tmp_doc_body = tmp_doc._document_part._element.body
# You could pretty print it by using:
#print(docx.oxml.xmlchemy.serialize_for_reading(tmp_doc_body))
Ich lud dann meine docx-Vorlage in ein zweites docx.Document Objekt (ein Lesezeichen namens ‚insertion_point‘ enthält).
Der nächste Schritt ist das Analysieren des XML-Dokuments, um den Index des Einfügepunkts zu finden. Ich definiert eine kleine Funktion für die Aufgabe in der Hand, die eine benannte Lesezeichen Mutterabsatzelement zurückgibt:
def get_bookmark_par_element(document, bookmark_name):
"""
Return the named bookmark parent paragraph element. If no matching
bookmark is found, the result is '1'. If an error is encountered, '2'
is returned.
"""
doc_element = document._document_part._element
bookmarks_list = doc_element.findall('.//' + qn('w:bookmarkStart'))
for bookmark in bookmarks_list:
name = bookmark.get(qn('w:name'))
if name == bookmark_name:
par = bookmark.getparent()
if not isinstance(par, docx.oxml.CT_P):
return 2
else:
return par
return 1
Die neu definierte Funktion toget das Lesezeichen ‚insertion_point‘ parent Absatz verwendet wurde. Die Fehlerkontrolle bleibt dem Leser überlassen.
bookmark_par = get_bookmark_par_element(doc, 'insertion_point')
Wir haben jetzt bookmark_par die etree Index einfügen unsere tmp_doc generierte Inhalte am richtigen Ort einsetzen können:
bookmark_par_parent = bookmark_par.getparent()
index = bookmark_par_parent.index(bookmark_par) + 1
for child in tmp_doc_body:
bookmark_par_parent.insert(index, child)
index = index + 1
bookmark_par_parent.remove(bookmark_par)
Das Dokument nun abgeschlossen ist, der erzeugte Inhalt eingefügt wurde, an dem Lesezeichen Ort eines vorhandenes Word-Dokument.
# Save result
# print(docx.oxml.xmlchemy.serialize_for_reading(doc_body))
doc.save('/some/path/generated_doc.docx')
Ich hoffe, dass dies jemand helfen kann, da die Dokumentation diesbezüglich noch zu schreiben ist.
Thanks for sharing! Ich musste noch nicht mit Bildern experimentieren, also bin ich mir nicht sicher über die Herausforderungen auf dieser Seite. – Apteryx