如何在gSOAP的SOAP-ENV:Header中添加多个直接子元素?
问题:gSOAP生成ONVIF协议要求的多直接子元素SOAP Header失败
需要生成符合ONVIF协议的SOAP报文,其中SOAP-ENV:Header需包含多个直接子元素(如dom0:SubscriptionId、dom1:SubscriptionId)。使用gSOAP生成的SOAP_ENV__Header结构体中的__any字段尝试添加自定义子元素时,通过soap_elt_new构建的next链表仅第一个元素被序列化,无法满足需求。
解决方案
1. 正确构建soap_dom_element链表并配置元素属性
gSOAP的__any字段支持通过next指针链接多个同级元素,需确保每个元素正确初始化命名空间、属性和文本内容:
// 创建第一个SubscriptionId元素,指定命名空间前缀、名称和URI struct soap_dom_element *subId1 = soap_elt_new(m_event_proxy.Get(), "dom0", "SubscriptionId", "http://trololo/111/event"); // 添加wsa5:IsReferenceParameter属性 soap_elt_add_attr(m_event_proxy.Get(), subId1, "wsa5", "IsReferenceParameter", "http://www.w3.org/2005/08/addressing", "true"); // 设置元素文本内容 soap_elt_set_text(m_event_proxy.Get(), subId1, "1715065920077"); // 创建第二个SubscriptionId元素 struct soap_dom_element *subId2 = soap_elt_new(m_event_proxy.Get(), "dom1", "SubscriptionId", "http://trololo/222/event"); soap_elt_add_attr(m_event_proxy.Get(), subId2, "wsa5", "IsReferenceParameter", "http://www.w3.org/2005/08/addressing", "true"); soap_elt_set_text(m_event_proxy.Get(), subId2, "1715065920078"); // 链接元素链表 subId1->next = subId2; // 将链表赋值给Header的__any字段 m_event_proxy.Get()->header->__any = subId1;
2. 自定义WSDL生成专属Header结构体(可选)
修改ONVIF的WSDL文件,添加SubscriptionId元素的定义,重新生成gSOAP代码。这样SOAP_ENV__Header结构体中会直接包含对应的字段,无需手动操作DOM元素。注意:这种方法需要维护自定义WSDL,版本升级时需同步调整。
3. 手动序列化Header元素
在调用服务方法前,绕过自动序列化逻辑,手动写入Header元素:
// 手动插入第一个SubscriptionId元素 soap_begin_elt(m_event_proxy.Get(), m_event_proxy.Get()->header, "dom0", "SubscriptionId", "http://trololo/111/event"); soap_add_attr(m_event_proxy.Get(), "wsa5", "IsReferenceParameter", "http://www.w3.org/2005/08/addressing", "true"); soap_put_text(m_event_proxy.Get(), "1715065920077"); soap_end_elt(m_event_proxy.Get()); // 手动插入第二个SubscriptionId元素 soap_begin_elt(m_event_proxy.Get(), m_event_proxy.Get()->header, "dom1", "SubscriptionId", "http://trololo/222/event"); soap_add_attr(m_event_proxy.Get(), "wsa5", "IsReferenceParameter", "http://www.w3.org/2005/08/addressing", "true"); soap_put_text(m_event_proxy.Get(), "1715065920078"); soap_end_elt(m_event_proxy.Get());
问题原因
之前的代码未指定元素的命名空间,也未设置必要的属性和文本内容,导致gSOAP序列化时无法正确识别后续元素,仅处理第一个节点。
内容的提问来源于stack exchange,提问作者Danil
相关产品推荐
相关产品推荐

