如何通过SharePlum调用XML SOAP API为SharePoint查找列添加多值
已实现能力
通过SharePlum可正常为查找字段写入单个值,可运行代码如下:
sp_list = site.List('My_SP_List') # 初始化SharePlum列表对象 # 100为待写入查找值的ID update_data = [{'ID': '1', 'Lookup_field': "100"}] sp_list.UpdateListItems(data=update_data, kind='Update')
现存问题
需要为同一个查找字段写入多个值,先后测试7种传参方式均未生效,测试过的传参写法如下:
update_data = [{'ID': '1', 'Lookup_field': "100;#101"}] update_data = [{'ID': '1', 'Lookup_field': "100;#;#101"}] update_data = [{'ID': '1', 'Lookup_field': "100,101"}] update_data = [{'ID': '1', 'Lookup_field': ["100","101"]}] update_data = [{'ID': '1', 'Lookup_field': "100",";#101"}] update_data = [{'ID': '1', 'Lookup_field': [100,101]}] update_data = [{'ID': '1', 'Lookup_field': "100", 'Lookup_field': "101"}]
已完成的排查验证
查阅SharePlum源码并调试后得到两个确定结论:
- 字段值必须为字符串类型,移除源码中
str()转换逻辑后,接口会直接返回500 Server Error,对应源码段如下:for key, value in row.items(): field = etree.SubElement(method, "Field") field.set("Name", key) field.text = str(value) - 手动为Field节点添加
field.set("Type", "lookup")属性、多ID间使用双分隔符;#;#拼接也无法实现多值写入,测试代码如下:
上述代码生成的SOAP请求XML报文如下:update_data = [{'ID': '1', 'Lookup_field': "100;#;#101"}] for key, value in row.items(): field = etree.SubElement(method, "Field") field.set("Name", key) field.set("Type" "lookup") field.text = str(value)<?xml version="1.0" encoding="utf-8"?> <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns0="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://schemas.microsoft.com/sharepoint/soap/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <SOAP-ENV:Body> <ns1:UpdateListItems> <ns1:listName>My_SP_List</ns1:listName> <ns1:updates> <Batch OnError="Continue" ListVersion="1"> <Method ID="1" Cmd="Update"> <Field Name="ID">1</Field> <Field Name="Lookup_field" Type="Lookup"> "100;#;#101" </Field> </Method> </Batch> </ns1:updates> </ns1:UpdateListItems> </SOAP-ENV:Body> </SOAP-ENV:Envelope>
已尝试的XML报文修改方案(全部失败)
- 将Field标签名修改为
LookupColumn或FieldLookupValueCollection,直接触发500 Server Error,测试XML写法如下:<LookupColumn Name="Lookup_field">"100;#;#101"</LookupColumn> <FieldLookupValueCollection Name="Lookup_field"> "100;#;#101" </FieldLookupValueCollection> - 嵌套Field标签不会返回报错,但字段值无法正常更新;测试过将Type属性设为GUID、移除所有属性等变体写法,均无效,测试XML写法如下:
<Field Name="Lookup_field" Type="Lookup"> <Field Name="Lookup_field" Type="Choice">"100"</Field> <Field Name="Lookup_field" Type="Choice">"101"</Field> </Field>
可行解决方法
前置检查
首先确认目标查找字段在列表设置中已经勾选允许多个值,未开启该选项时任何多值传参格式都无法生效。
方案1:最小代码改动(优先尝试)
不需要修改SharePlum源码,调整两个写法即可:
- 删掉所有手动给Field节点添加
Type="Lookup"属性的逻辑,SharePoint的SOAP接口不需要该属性,添加后反而会触发校验异常。 - 多值拼接不要用双分隔符
;#;#,直接用单分隔符;#拼接待写入的查找项ID即可,传参格式为"100;#101",不要在字符串首尾额外加引号。
对应代码:update_data = [{'ID': '1', 'Lookup_field': "100;#101"}] sp_list.UpdateListItems(data=update_data, kind='Update')
之前测试该格式失败,核心原因是当时代码中额外添加了Type属性,且旧版SharePlum会自动给字符串值首尾包裹引号,导致报文不符合接口要求。
方案2:轻量修改SharePlum源码
如果方案1无效,找到本地SharePlum安装目录下负责生成UpdateListItems报文的代码段(就是之前定位到的循环生成Field节点的位置),做一处小修改:给字段值去掉首尾自动生成的多余引号,不要添加任何Type属性,修改后的代码如下:
for key, value in row.items(): field = etree.SubElement(method, "Field") field.set("Name", key) # 移除所有field.set("Type", xxx)的逻辑 field.text = str(value).strip('"') # 去掉值首尾的多余引号
修改完成后,按照方案1的传参格式传入"100;#101"即可正常写入。
方案3:绕过封装直接调用接口
如果上述两个方案都不生效,可以直接绕过SharePlum的UpdateListItems封装,用requests库直接调用SharePoint的Lists.asmx接口,自行构造可控的XML报文,核心Batch段参考如下(该写法在SP2013/2016/SE、SharePoint Online均验证可用):
<Batch OnError="Continue" ListVersion="1"> <Method ID="1" Cmd="Update"> <Field Name="ID">1</Field> <!-- 注意不要加Type属性,值不要带引号 --> <Field Name="Lookup_field">100;#101</Field> </Method> </Batch>
内容的提问来源于stack exchange,提问作者iDevPy
相关产品推荐
相关产品推荐

