Моя конечная цель — найти и удалить любой раздел библиографии из документа Microsoft Word.
Как упоминалось в этом выпуске .
В настоящее время нет поддержки API для тегов w:sdt
(думаю, только для библиографий). Однако в ответ на эту проблему был предложен обходной путь:
paragraph = ... # however you get the paragraph, maybe with `for paragraph in document.paragraphs`
p = paragraph._element
sdts = p.xpath('w:sdt')
for sdt in sdts:
parent = sdt.getparent()
parent.remove(sdt)
При использовании вышеизложенного XML документа обновляется и удаляет теги w:sdt
так, как я хочу. Однако когда я сохраняю новый документ, выходной файл .docx по-прежнему включает раздел библиографии.
Почему, несмотря на то, что XML-файл документа Python-docx не включает элементы w:sdt
, это не отражается после сохранения и открытия документа в Microsoft Word. Я прочитал здесь, что отношения документов могут иметь какое-то отношение к этому, но, учитывая, что я не получаю ошибок при открытии нового документа Word, я не думаю, что это проблема. Есть идеи?
Вот предварительная обработка фрагмента XML:
<w:p xmlns:w = "http://schemas.openxmlformats.org/wordprocessingml/2006/main" xmlns:w14 = "http://schemas.microsoft.com/office/word/2010/wordml" xmlns:wpc = "http://schemas.microsoft.com/office/word/2010/wordprocessingCanvas" xmlns:cx = "http://schemas.microsoft.com/office/drawing/2014/chartex" xmlns:cx1 = "http://schemas.microsoft.com/office/drawing/2015/9/8/chartex" xmlns:cx2 = "http://schemas.microsoft.com/office/drawing/2015/10/21/chartex" xmlns:cx3 = "http://schemas.microsoft.com/office/drawing/2016/5/9/chartex" xmlns:cx4 = "http://schemas.microsoft.com/office/drawing/2016/5/10/chartex" xmlns:cx5 = "http://schemas.microsoft.com/office/drawing/2016/5/11/chartex" xmlns:cx6 = "http://schemas.microsoft.com/office/drawing/2016/5/12/chartex" xmlns:cx7 = "http://schemas.microsoft.com/office/drawing/2016/5/13/chartex" xmlns:cx8 = "http://schemas.microsoft.com/office/drawing/2016/5/14/chartex" xmlns:mc = "http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:aink = "http://schemas.microsoft.com/office/drawing/2016/ink" xmlns:am3d = "http://schemas.microsoft.com/office/drawing/2017/model3d" xmlns:o = "urn:schemas-microsoft-com:office:office" xmlns:oel = "http://schemas.microsoft.com/office/2019/extlst" xmlns:r = "http://schemas.openxmlformats.org/officeDocument/2006/relationships" xmlns:m = "http://schemas.openxmlformats.org/officeDocument/2006/math" xmlns:v = "urn:schemas-microsoft-com:vml" xmlns:wp14 = "http://schemas.microsoft.com/office/word/2010/wordprocessingDrawing" xmlns:wp = "http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing" xmlns:w10 = "urn:schemas-microsoft-com:office:word" xmlns:w15 = "http://schemas.microsoft.com/office/word/2012/wordml" xmlns:w16cex = "http://schemas.microsoft.com/office/word/2018/wordml/cex" xmlns:w16cid = "http://schemas.microsoft.com/office/word/2016/wordml/cid" xmlns:w16 = "http://schemas.microsoft.com/office/word/2018/wordml" xmlns:w16sdtdh = "http://schemas.microsoft.com/office/word/2020/wordml/sdtdatahash" xmlns:w16se = "http://schemas.microsoft.com/office/word/2015/wordml/symex" xmlns:wpg = "http://schemas.microsoft.com/office/word/2010/wordprocessingGroup" xmlns:wpi = "http://schemas.microsoft.com/office/word/2010/wordprocessingInk" xmlns:wne = "http://schemas.microsoft.com/office/word/2006/wordml" xmlns:wps = "http://schemas.microsoft.com/office/word/2010/wordprocessingShape" w14:paraId = "2BE25C04" w14:textId = "0C685DB1" w:rsidR = "00572630" w:rsidRDefault = "006A14EA">
<w:r>
<w:t xml:space = "preserve">Hey there </w:t>
</w:r>
<w:sdt>
<w:sdtPr>
<w:id w:val = "-39898552"/>
<w:citation/>
</w:sdtPr>
<w:sdtContent>
<w:r>
<w:fldChar w:fldCharType = "begin"/>
</w:r>
<w:r>
<w:instrText xml:space = "preserve"> CITATION Fra69 \l 2057 </w:instrText>
</w:r>
<w:r>
<w:fldChar w:fldCharType = "separate"/>
</w:r>
<w:r>
<w:rPr>
<w:noProof/>
</w:rPr>
<w:t>(Herbert, 1969)</w:t>
</w:r>
<w:r>
<w:fldChar w:fldCharType = "end"/>
</w:r>
</w:sdtContent>
</w:sdt>
</w:p>
Вот постобработка фрагмента XML, где вы можете видеть, что библиография была удалена, но эти изменения не видны, когда я сохраняю и открываю документ:
<w:p xmlns:w = "http://schemas.openxmlformats.org/wordprocessingml/2006/main" xmlns:w14 = "http://schemas.microsoft.com/office/word/2010/wordml" xmlns:wpc = "http://schemas.microsoft.com/office/word/2010/wordprocessingCanvas" xmlns:cx = "http://schemas.microsoft.com/office/drawing/2014/chartex" xmlns:cx1 = "http://schemas.microsoft.com/office/drawing/2015/9/8/chartex" xmlns:cx2 = "http://schemas.microsoft.com/office/drawing/2015/10/21/chartex" xmlns:cx3 = "http://schemas.microsoft.com/office/drawing/2016/5/9/chartex" xmlns:cx4 = "http://schemas.microsoft.com/office/drawing/2016/5/10/chartex" xmlns:cx5 = "http://schemas.microsoft.com/office/drawing/2016/5/11/chartex" xmlns:cx6 = "http://schemas.microsoft.com/office/drawing/2016/5/12/chartex" xmlns:cx7 = "http://schemas.microsoft.com/office/drawing/2016/5/13/chartex" xmlns:cx8 = "http://schemas.microsoft.com/office/drawing/2016/5/14/chartex" xmlns:mc = "http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:aink = "http://schemas.microsoft.com/office/drawing/2016/ink" xmlns:am3d = "http://schemas.microsoft.com/office/drawing/2017/model3d" xmlns:o = "urn:schemas-microsoft-com:office:office" xmlns:oel = "http://schemas.microsoft.com/office/2019/extlst" xmlns:r = "http://schemas.openxmlformats.org/officeDocument/2006/relationships" xmlns:m = "http://schemas.openxmlformats.org/officeDocument/2006/math" xmlns:v = "urn:schemas-microsoft-com:vml" xmlns:wp14 = "http://schemas.microsoft.com/office/word/2010/wordprocessingDrawing" xmlns:wp = "http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing" xmlns:w10 = "urn:schemas-microsoft-com:office:word" xmlns:w15 = "http://schemas.microsoft.com/office/word/2012/wordml" xmlns:w16cex = "http://schemas.microsoft.com/office/word/2018/wordml/cex" xmlns:w16cid = "http://schemas.microsoft.com/office/word/2016/wordml/cid" xmlns:w16 = "http://schemas.microsoft.com/office/word/2018/wordml" xmlns:w16sdtdh = "http://schemas.microsoft.com/office/word/2020/wordml/sdtdatahash" xmlns:w16se = "http://schemas.microsoft.com/office/word/2015/wordml/symex" xmlns:wpg = "http://schemas.microsoft.com/office/word/2010/wordprocessingGroup" xmlns:wpi = "http://schemas.microsoft.com/office/word/2010/wordprocessingInk" xmlns:wne = "http://schemas.microsoft.com/office/word/2006/wordml" xmlns:wps = "http://schemas.microsoft.com/office/word/2010/wordprocessingShape" w14:paraId = "2BE25C04" w14:textId = "0C685DB1" w:rsidR = "00572630" w:rsidRDefault = "006A14EA">
<w:r>
<w:t xml:space = "preserve">Hey there </w:t>
</w:r>
</w:p>
Примечание. Я задаю этот вопрос здесь, поскольку python-docx GitHub в последнее время не проявляет особой активности.
3. Библиография обычно состоит из двух элементов множества, один из которых вложен в другой. Внутренний должен содержать элемент <w:bibliography>. (Не уверен, что вы увидите, если вставите старомодное поле {BIBLIOGRAPHY} вручную — я не проверял.). Но пока библиография всегда строится таким образом, если вы можете понять, как найти элементы/теги w:bibliography, а затем найти включающий тег set и заключающий его тег set, вы сможете заставить это работать.
4. Теги sdt описаны в стандартном документе ISO 29500, часть 1 (Справочник по основам и языку разметки) в разделе 17.5.2. У Microsoft есть собственные документы по стандартам, в которых документируются отклонения от стандартов ISO. 5. В вашем документе будет часть «Библиография», которая будет описана в разделе «Связь». Когда вы удаляете фактическую библиографию, вам также не нужно удалять часть «Библиография».
Спасибо за ответ, просматривая мой тестовый XML-файл документа, я вижу, что теги sdt не являются дочерними элементами какого-либо тега p, но, несмотря на это, включенный исходный код извлекает теги sdt. Кроме того, мой тестовый документ не содержит тега w:bibilography — тот, о котором идет речь, был создан с использованием функций библиографии Word по умолчанию.
Это интересно: в моем тесте также использовалась библиография, вставленная в Word, в частности (в настольном Word Windows), с использованием раскрывающегося списка «Цитаты и библиография» -> «Библиография» на ленте, выбрав встроенную запись «Библиография». То же самое и в Mac Word. В обоих есть элемент <w:bibliography/>. Так что, возможно, мы делаем что-то по-другому. Если вместо этого просто вставить поле {BIBLIOGRAPHY}, не будет ни структуры SDT, ни элемента <w:bibliography/>, а только обычная сложная структура поля с текстом поля, результатом поля и т. д.
Честно говоря, трудно понять, как удаление SDT не приводит к удалению библиографии, если библиография фактически не находится в SDT. Если вы еще не докопались до сути, было бы полезно опубликовать соответствующий XML до и после «удаления».
@jonsson Я добавил XML до и после
Честно говоря, самое простое объяснение этому состоит в том, что изменения в XmL фактически не были сохранены! Думаю, я бы разархивировал .docx и проверил.
Я понял, что моя проблема заключалась в том, что я удалял только элементы w:sdt, которые были дочерними элементами элементов абзаца, а не основной элемент w:sdt библиографии. Удаление обоих необходимо, чтобы полностью избавиться от всей библиографии и ссылок на нее.
Для справки: ниже приведены инструкции по удалению ссылок на библиографию:
paragraph = ... # however you get the paragraph, maybe with `for paragraph in document.paragraphs`
p = paragraph._element
sdts = p.xpath('w:sdt')
for sdt in sdts:
parent = sdt.getparent()
parent.remove(sdt)
А ниже будет удален основной элемент библиографии:
body = doc._body._element
sdts = body.xpath("w:sdt")
if sdts:
for sdt in sdts:
parent = sdt.getparent()
parent.remove(sdt)
Ха, потратил некоторое время на это и обнаружил, что ты опубликовал свой собственный ответ. Бывает! Но я опубликовал свой собственный, потому что он пытается удалить только наборы «Цитирование» и «Библиография», а не другие наборы, такие как «Контроль содержимого».
Поскольку я не мог понять, что происходит не так, я написал свой собственный код, фрагмент которого выглядит следующим образом:
from docx import Document
# The xpaths to look for.
# 1. Citations,
# 2. The outer sdt of a Bibliography, then
# 3. In case there were bibliographies without the outer sdt,
# Of these, [2] probably needs to be tightened up as it's conceivable
# that a non-bibliography sdt could use a DocPart from the Bibliographies gallery.
xpaths = ("w:sdt[w:sdtPr/w:citation]",
"w:sdt[w:sdtPr/w:docPartObj/w:docPartGallery[@w:val='Bibliographies']]",
"w:sdt[w:sdtPr/w:bibliography]")
f = open('x.docx', 'rb')
document = Document(f)
p = document._body._element
for xp in xpaths:
print(xp)
sdts = p.xpath(xp)
for sdt in sdts:
sdt.getparent().remove(sdt)
document.save('y.docx')
f.close()
некоторые примечания, которые могут вам помочь (я не знаю, как использовать библиотеку python-docx, чтобы определить, что нужно удалить, но вы можете это сделать). 1. Элементы w:set можно использовать для нескольких целей: не только для библиографии, но и для цитирования и различных типов управления контентом. 2. Элементы w:sdt не обязательно содержатся в элементах Paragraph. Фактически, если вы добавите библиографию в пустой абзац в Word, тег set не будет содержаться в теге w:p. Я не знаю, возможно ли это когда-нибудь.