簡體   English   中英

如何在python-docx中聲明新的oxml / xmlchemy標簽?

[英]How do I declare new oxml/xmlchemy tags in python-docx?

我正在嘗試將基本的方程式功能構建到python-docx中,以將公式輸出到docx文件。 有人可以通過標准操作程序來在oxml中注冊新類嗎? 查看源代碼,似乎通過創建復雜類型的類來聲明標簽。

class CT_P(BaseOxmlElement):
    """
    ''<w:p>'' element, containing the properties and text for a paragraph.
    """
    pPr = ZeroOrOne('w:pPr')
    r = ZeroOrMore('w:r')

然后使用register_element_cls()函數進行注冊

from .text.paragraph import CT_P
register_element_cls('w:p', CT_P)

一些類包含其他方法,但許多類不包含,因此,看起來一個最小的工作示例如下:

from docx import Document
from docx.oxml.xmlchemy import BaseOxmlElement, ZeroOrOne, ZeroOrMore, OxmlElement
import docx.oxml
docx.oxml.ns.nsmap['m'] = ('http://schemas.openxmlformats.org/officeDocument/2006/math')

class CT_OMathPara(BaseOxmlElement):
    r = ZeroOrMore('w:r')

docx.oxml.register_element_cls('m:oMathPara',CT_OMathPara)  
p = CT_OMathPara()

(請注意,我必須聲明m命名空間,因為在包中未使用它)。 不幸的是,這根本不適合我。 如果我聲明一個如上述示例中派生的新類,然后檢查該新類的__repr__ ,它將導致異常

>> p

File "C:\ProgramData\Anaconda3\lib\site-packages\docx\oxml\ns.py", line 50, in from_clark_name
    nsuri, local_name = clark_name[1:].split('}')

ValueError: not enough values to unpack (expected 2, got 1)

發生這種情況是因為我類中的標記與從python-docx包創建的aw:p標記非常不同

>> paragraph._element.tag
 '{http://schemas.openxmlformats.org/wordprocessingml/2006/main}p'

>> p.tag
 'CT_OMathPara'

但是我不知道為什么會這樣。 通過源代碼進行文件搜索不會發現CT_P類的任何其他提及,因此我有些困惑。

我認為錯誤是來自docx.oxml.ns.pfxmap字典中不存在的'm'名稱空間前綴(nspfx)。 兩種方式都需要查找名稱空間(從nspfx到名稱空間url 從url到nspfx)。

因此,要從“外部”添加新的名稱空間,這意味着在加載ns模塊之后,您需要同時進行這兩項操作(如果要直接修補ns模塊代碼,則第二步將在加載時自動處理):

nsmap, pfxmap = docx.oxml.ns.nsmap, docx.oxml.ns.pfxmap
nsmap['m'] = 'http://schemas.openxmlformats.org/officeDocument/2006/math'
pfxmap['http://schemas.openxmlformats.org/officeDocument/2006/math'] = 'm'

這應該使您能夠克服遇到的錯誤,但是還有更多需要理解的地方。

CT_OMathPara類是自定義元素類的示例。 這意味着lxml為每個具有已注冊標記( m:oMathPara )的元素實例化此類的對象,而不是通用lxml _Element類。

關鍵是, 您需要讓lxml進行構造 ,該構造在解析XML時發生。 您不能通過自己構造該類來獲得有意義的對象。

創建新的“松散”元素(不存在於XML文檔樹中)的最簡單方法是使用docx.oxml.OxmlElement()

oMathPara = OxmlElement('m:oMathPara')

不過,更常見的是docx.oxml.parse_xml()函數用於解析整個XML代碼段。 解析器需要配置為使用自定義元素類,並且這些元素必須在解析器中注冊,因此當oxml模塊中的oxml所有需要時,您可能不想自己做。

因此,通常,要獲取CT_OMathPara的實例,只需打開一個包含m:oMathPara元素的docx(在注冊新的名稱空間和自定義元素類之后),但是您也可以僅在XML代碼段中進行解析。 如果您在oxml模塊中搜索parse_xml ,則會發現很多示例。 您需要在提供的XML的頂部獲得名稱空間聲明,這可能有些棘手,但是如果您願意的話,您當然可以只在文本中拼出整個XML代碼段,只是有些冗長。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM