Java实现XSD校验XML出现cvc-complex-type.2.4.a报错咨询
问题原因
你的Java校验代码逻辑没有问题,报错完全是XSD文件和待校验XML不匹配导致的,具体不匹配的点如下:
- 命名空间覆盖不全:你写的XSD仅定义了
http://schemas.xmlsoap.org/soap/envelope/(SOAP协议命名空间)下的元素结构,而XML中Body下的业务节点ns1:LanguageName属于独立的业务命名空间http://www.oorsprong.org/websamples.countryinfo,这个命名空间的结构规则完全没有在当前XSD中定义,校验器无法识别该命名空间下的元素。 - 允许的节点规则与实际内容不符:你在XSD中硬编码规定SOAP Body下只能出现SOAP命名空间下的
LanguageNameResponse节点,但实际XML里Body下的节点是业务命名空间下的LanguageName,完全不在XSD允许的元素列表里,直接触发了报错里提示的Invalid content错误。 - 校验对象搞反了:你XSD里定义的
LanguageNameResponse带LanguageNameResult子节点,是接口的响应报文结构,但你现在待校验的XML是带sISOCode子节点的请求报文,请求节点名本来就叫LanguageName,和你XSD里写的响应节点根本不是同一个东西。 - XSD写法不符合SOAP规范:SOAP作为传输协议,本身不会限制Body里放什么业务节点,标准SOAP XSD不会把Body的子节点写死,而是用通配符放行任意业务结构。你现在硬写死Body子节点的写法本身就不符合SOAP XSD的编写规则。
修复方法
- 第一步:修正SOAP基础结构的XSD定义,不要硬编码Body下的业务节点,改用通配符放行任意业务内容,参考写法如下:
<?xml version="1.0"?> <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" targetNamespace="http://schemas.xmlsoap.org/soap/envelope/" elementFormDefault="qualified"> <xsd:element name="Envelope"> <xsd:complexType> <xsd:sequence> <xsd:element name="Header" minOccurs="0" type="xsd:anyType"/> <xsd:element name="Body"> <xsd:complexType> <xsd:sequence> <!-- 放行任意命名空间的业务节点,不限制节点名称 --> <xsd:any namespace="##any" processContents="lax" minOccurs="0" maxOccurs="unbounded"/> </xsd:sequence> </xsd:complexType> </xsd:element> </xsd:sequence> </xsd:complexType> </xsd:element> </xsd:schema>
用这个XSD跑你现在的Java代码,就能通过SOAP外壳的校验,不会再抛当前的元素不匹配错误。
- 第二步(可选):如果需要同时校验Body里的业务内容是否符合接口规则,需要单独编写业务命名空间
http://www.oorsprong.org/websamples.countryinfo对应的XSD,定义好LanguageName节点下必须存在sISOCode字符串子节点的规则,再通过<xsd:import>标签把业务XSD导入到SOAP XSD中,同时把上面<xsd:any>的processContents属性改为strict,就可以实现全报文校验。
注意:不要拿响应结构的XSD去校验请求报文,请求和响应的节点结构、节点名都是分开定义的。
内容的提问来源于stack exchange,提问作者Haritha
相关产品推荐
相关产品推荐

