如何在Sage X3脚本中解析第三方Webservice返回的XML响应字段
Sage X3 解析SOAP接口响应XML字段实操方案
Sage X3自带原生XML解析库ASYRFICXML,专门用来处理这类结构化XML报文,比正则、字符串截取稳定性高很多,适配带命名空间的SOAP报文场景。
实现步骤
- 第一步:预处理响应内容,初始化解析器
你从func ASYRWEBSER.EXEC_HTTP拿到的响应字符串里可能带转义引号,先做格式修正再加载到解析器里,示例代码:# 定义变量:WS_RESP为EXEC_HTTP返回的原始响应内容 Local Char XML_RESP(0) Local Integer XML_DOC, TARGET_NODE, CHILD_NODE Local Integer RET_CODE XML_RESP = WS_RESP # 替换转义的反斜杠和引号,保证XML格式合法 XML_RESP = replace$(XML_RESP, '\\"', '"') XML_RESP = replace$(XML_RESP, "\\", "") # 加载XML文档到解析器 Call OPEN_DOC(XML_RESP, 0, 0, XML_DOC) With ASYRFICXML If XML_DOC = 0 # 此处加错误处理:打印XML_RESP内容排查格式问题 End Endif # 开启命名空间忽略,不用管s:、a:这类前缀,避免命名空间导致节点匹配失败 Call SET_IGNORE_NS(XML_DOC, 1) With ASYRFICXML - 第二步:按节点层级提取需要的字段
所有节点查找直接写层级路径即可,不用带命名空间前缀:- 提取Status状态值
Local Char WS_STATUS(50) Call FIND_NODE(XML_DOC, 0, "Envelope/Body/CreateShipmentResponse/CreateShipmentResult/Status", 0, TARGET_NODE) With ASYRFICXML If TARGET_NODE <> 0 Call GET_VALUE(XML_DOC, TARGET_NODE, WS_STATUS) With ASYRFICXML # WS_STATUS即返回的状态值,示例中为"Success" Endif- 提取LastObject运单值
Local Char LAST_OBJ_CODE(100) Call FIND_NODE(XML_DOC, 0, "Envelope/Body/CreateShipmentResponse/CreateShipmentResult/ShipmentData/ShipmentDataOutput/LastObject", 0, TARGET_NODE) With ASYRFICXML If TARGET_NODE <> 0 Call GET_VALUE(XML_DOC, TARGET_NODE, LAST_OBJ_CODE) With ASYRFICXML # LAST_OBJ_CODE即你要的运单号,示例中为"DB112320353PT" Endif- 提取LabelList下LabelData的全部子节点内容
LabelData下包含BestEncoding、FileName、Label三个字段,先定位到LabelData父节点,再逐个取子节点值:
Local Char LABEL_ENCODING(20), LABEL_FILENAME(100), LABEL_RAW_CONTENT(0) Local Integer LABEL_DATA_NODE # 先定位到LabelData节点 Call FIND_NODE(XML_DOC, 0, "Envelope/Body/CreateShipmentResponse/CreateShipmentResult/ShipmentData/ShipmentDataOutput/LabelList/LabelData", 0, LABEL_DATA_NODE) With ASYRFICXML If LABEL_DATA_NODE <> 0 # 取编码格式 Call FIND_NODE(XML_DOC, LABEL_DATA_NODE, "BestEncoding", 1, CHILD_NODE) With ASYRFICXML If CHILD_NODE <> 0 Call GET_VALUE(XML_DOC, CHILD_NODE, LABEL_ENCODING) With ASYRFICXML Endif # 取标签文件名 Call FIND_NODE(XML_DOC, LABEL_DATA_NODE, "FileName", 1, CHILD_NODE) With ASYRFICXML If CHILD_NODE <> 0 Call GET_VALUE(XML_DOC, CHILD_NODE, LABEL_FILENAME) With ASYRFICXML Endif # 取ZPL标签原始内容 Call FIND_NODE(XML_DOC, LABEL_DATA_NODE, "Label", 1, CHILD_NODE) With ASYRFICXML If CHILD_NODE <> 0 Call GET_VALUE(XML_DOC, CHILD_NODE, LABEL_RAW_CONTENT) With ASYRFICXML Endif Endif - 第三步:释放解析资源
字段提取完成后关闭XML文档对象,避免内存残留:Call CLOSE_DOC(XML_DOC) With ASYRFICXML
排错提示
如果FIND_NODE返回节点为0,先把预处理后的XML_RESP输出到日志核对路径:部分SOAP接口会在Body和业务节点之间加额外的安全校验节点,或者存在多包裹场景下LabelData是多个重复节点的情况,遇到多节点可以用
FIND_NEXT_NODE方法循环遍历所有子节点即可。
绝对不要用instr、seg$这类字符串函数硬切XML内容,只要接口返回的换行、属性顺序、节点层级稍有变动,代码就会取错值。
内容的提问来源于stack exchange,提问作者Rui Leming
相关产品推荐
相关产品推荐

