如何让Gsoap解析ONVIF响应时读取正确元素并忽略错误/损坏元素?
问题背景
根据ONVIF规范,ImagingSettings20类型的tt:Focus元素应对应tt:FocusConfiguration20类型,XSD定义如下:
<xs:complexType name="ImagingSettings20"> <xs:annotation> <xs:documentation>Type describing the ImagingSettings of a VideoSource. The supported options and ranges can be obtained via the GetOptions command.</xs:documentation> </xs:annotation> <xs:sequence> ... <xs:element name="Focus" type="tt:FocusConfiguration20" minOccurs="0"> <xs:annotation> <xs:documentation>Focus configuration.</xs:documentation> </xs:annotation> </xs:element> ... </xs:sequence> <xs:anyAttribute processContents="lax"/> </xs:complexType>
但某款ONVIF摄像头返回的GetImagingSettingsResponse中,tt:Focus元素实际为tt:FocusOptions20类型(包含多值AutoFocusModes、DefaultSpeed等节点),不符合规范,导致gSOAP生成的C++代码解析时直接终止,无法获取Brightness、ColorSaturation等正确字段。
需求:确保解析过程不终止,优先获取所有正确字段;仅当tt:Focus元素类型错误/损坏时忽略它,符合规范时正常解析。
最优实现方案
方案1:修改gSOAP解析逻辑,添加容错处理
这是最直接的方案,无需修改XSD或预处理XML:
- 生成代码时启用宽松解析:使用gSOAP的
wsdl2h工具生成头文件时,添加- lax参数,让gSOAP对XML解析采用宽松模式,允许跳过无法匹配类型的元素,继续解析后续节点。 - 手动修改解析代码:如果已生成代码,找到处理
tt__ImagingSettings20结构的解析函数(通常在soapC.cpp中),在tt:Focus字段解析失败的分支中,调用soap_skip_element(soap)跳过当前错误元素,然后返回SOAP_OK,让解析流程继续执行。
示例代码片段(修改解析函数):
// 原解析Focus字段的代码 if (soap_element_begin_in(soap, "Focus", NULL, NULL, 0)) goto error; if (soap_get_tt__FocusConfiguration20(soap, &a->Focus, "Focus", NULL)) { // 添加容错逻辑:跳过当前元素 soap_skip_element(soap); a->Focus = NULL; // 标记Focus未解析 } if (soap_element_end_in(soap, "Focus")) goto error;
方案2:自定义兼容XSD,重新生成代码
通过修改XSD定义,让tt:Focus元素兼容两种类型:
- 复制原ONVIF XSD中
ImagingSettings20的定义,修改Focus元素的类型定义,允许同时接受FocusConfiguration20和FocusOptions20:
<xs:element name="Focus" minOccurs="0"> <xs:complexType> <xs:choice> <xs:element name="FocusConfig" type="tt:FocusConfiguration20"/> <xs:element name="FocusOpts" type="tt:FocusOptions20"/> </xs:choice> </xs:complexType> </xs:element>
或者更简单地将类型改为xs:anyType,让gSOAP接受任意结构的Focus元素,后续再手动判断类型并解析。
2. 使用修改后的XSD重新生成gSOAP的头文件和代码,生成时同样可配合- lax参数增强容错性。
方案3:预处理XML响应,修正错误节点
在gSOAP解析前拦截XML响应,修正错误的tt:Focus元素:
- 拦截gSOAP接收的XML响应内容,使用XML解析库(如libxml2)遍历节点。
- 检查
tt:Focus节点的子元素,如果发现是FocusOptions20的结构(如多值AutoFocusModes、包含Min/Max的DefaultSpeed等),直接删除该节点。 - 将修改后的XML内容传给gSOAP进行解析,确保后续正确字段能被正常读取。
方案优先级推荐
优先选择方案1,无需修改XSD或额外XML处理,仅通过调整gSOAP解析逻辑即可实现需求,开发成本最低;若方案1无法满足(如gSOAP版本限制),再考虑方案2;方案3作为兜底方案,适合无法修改gSOAP代码的场景。
内容的提问来源于stack exchange,提问作者Lucky Man
相关产品推荐
相关产品推荐

