Odoo添加XML附件报错:b2a_base64()参数应为字符串或缓冲区而非列表
解决Odoo创建XML附件时的TypeError问题
这个问题我之前处理过,核心原因有两个:一是你生成的root是列表类型,不符合base64编码函数的参数要求;二是对lxml.etree.tostring()的返回值以及Odooir.attachment字段的格式要求理解有偏差。下面一步步给你解决:
1. 为什么root会是列表?
正常情况下,lxml.etree.tostring()接收单个XML节点,返回的是字节串(bytes),而不是列表。你得到列表,大概率是因为传入的xml变量本身是一个节点列表(比如用xpath查询返回的结果),而不是单个XML根节点。
所以第一步要先把列表转成单个节点:
# 先确认xml的类型,如果是列表就取第一个有效节点 if isinstance(xml, list) and xml: xml_root_node = xml[0] else: xml_root_node = xml # 如果已经是单个节点就直接用
2. 正确生成XML字节串并编码
接下来用tostring()生成标准的XML字节串,建议指定编码和XML声明(避免乱码问题):
from lxml import etree import base64 # 生成带编码声明的XML字节串 xml_bytes = etree.tostring(xml_root_node, encoding='utf-8', xml_declaration=True)
注意:Python3中base64.encodestring()已经被标记为过时,官方推荐用base64.b64encode(),它接收bytes类型,返回也是bytes类型,最后我们需要把它转成字符串(因为Odoo的datas字段要求是base64编码的字符串)。
3. 修正Odoo附件创建代码
把上面的步骤整合后,最终的创建附件代码应该是这样的:
# 先处理XML节点 if isinstance(xml, list) and xml: xml_root_node = xml[0] else: xml_root_node = xml # 生成XML字节串 xml_bytes = etree.tostring(xml_root_node, encoding='utf-8', xml_declaration=True) # 创建附件 self.env['ir.attachment'].create({ 'name': 'NFe_Autorizada.xml', 'type': 'binary', 'datas': base64.b64encode(xml_bytes).decode('utf-8'), # 编码后转成字符串 'datas_fname': 'NFe_Autorizada.xml', 'res_model': 'invoice.eletronic', 'res_id': self.id, 'mimetype': 'application/xml' })
为什么之前用str(root)不行?
如果root是列表,str(root)会把列表转成类似[b'<xml>...</xml>']的字符串,里面包含了列表的括号和b''前缀,这不是纯XML内容,编码后肯定不符合要求。必须先把列表转成单个节点,再生成正确的XML字节串。
内容的提问来源于stack exchange,提问作者Marcelo Lima
相关产品推荐
相关产品推荐

