XML响应XSD验证触发SAXParseException错误,求解决方案
SOAP接口XML响应XSD验证报错:Premature end of file
问题描述
对SOAP接口返回的XML响应进行XSD验证时,触发org.xml.sax.SAXParseException错误,错误信息显示“Premature end of file”,关联的systemId为http://schemas.xmlsoap.org/soap/envelope/。已将该链接对应的XSD文件下载到项目src/main/resources目录,但问题仍未解决。
错误日志
HTTP/1.1 200 OK Cache-Control: private, max-age=0 Content-Type: text/xml; charset=utf-8 Content-Encoding: gzip Vary: Accept-Encoding Server: Microsoft-IIS/10.0 X-AspNet-Version: 2.0.50727 X-Powered-By: ASP.NET X-Powered-By-Plesk: PleskWin Date: Thu, 31 Jul 2025 06:25:36 GMT Content-Length: 348 <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <soap:Body> <AddResponse xmlns="http://tempuri.org/"> <AddResult>5</AddResult> </AddResponse> </soap:Body> </soap:Envelope> FAILED: tests.XMLSchemaValidation.schemaValidation org.xml.sax.SAXParseException; systemId: http://schemas.xmlsoap.org/soap/envelope/; lineNumber: 1; columnNumber: 1; Premature end of file. at java.xml/com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.createSAXParseException(ErrorHandlerWrapper.java:204) at java.xml/com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.fatalError(ErrorHandlerWrapper.java:178) at java.xml/com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(XMLErrorReporter.java:400) at java.xml/com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(XMLErrorReporter.java:327) at java.xml/com.sun.org.apache.xerces.internal.impl.XMLScanner.reportFatalError(XMLScanner.java:1465) at java.xml/com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl$PrologDriver.next(XMLDocumentScannerImpl.java:1043) at java.xml/com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next(XMLDocumentScannerImpl.java:635) at java.xml/com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.next(XMLNSDocumentScannerImpl.java:113) at java.xml/com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(XMLDocumentFragmentScannerImpl.java:551) at java.xml/com.sun.org.apache.xerces.internal.impl.xs.opti.SchemaParsingConfig.parse(SchemaParsingConfig.java:640) at java.xml/com.sun.org.apache.xerces.internal.impl.xs.opti.SchemaParsingConfig.parse(SchemaParsingConfig.java:696) at java.xml/com.sun.org.apache.xerces.internal.impl.xs.opti.SchemaDOMParser.parse(SchemaDOMParser.java:530) at java.xml/com.sun.org.apache.xerces.internal.impl.xs.traversers.XSDHandler.getSchemaDocument(XSDHandler.java:2227) at java.xml/com.sun.org.apache.xerces.internal.impl.xs.traversers.XSDHandler.resolveSchema(XSDHandler.java:2129) at java.xml/com.sun.org.apache.xerces.internal.impl.xs.traversers.XSDHandler.constructTrees(XSDHandler.java:1050) at java.xml/com.sun.org.apache.xerces.internal.impl.xs.traversers.XSDHandler.parseSchema(XSDHandler.java:653) at java.xml/com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaLoader.loadSchema(XMLSchemaLoader.java:617) at java.xml/com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaLoader.loadGrammar(XMLSchemaLoader.java:576) at java.xml/com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaLoader.loadGrammar(XMLSchemaLoader.java:542) at java.xml/com.sun.org.apache.xerces.internal.jaxp.validation.XMLSchemaFactory.newSchema(XMLSchemaFactory.java:278) at java.xml/javax.xml.validation.SchemaFactory.newSchema(SchemaFactory.java:612) at javax.xml.validation.SchemaFactory$newSchema$0.call(Unknown Source) at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:45) at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:125) at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:139) at io.restassured.internal.matcher.xml.XmlXsdMatcher.matches(XmlXsdMatcher.groovy:82) at io.restassured.internal.assertion.BodyMatcher.validate(BodyMatcher.java:82) at io.restassured.internal.assertion.BodyMatcherGroup.lambda$validate$0(BodyMatcherGroup.java:30) at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:215) at java.base/java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1716) at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:570) at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:560) at java.base/java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:921) at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:265) at java.base/java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:727) at io.restassured.internal.assertion.BodyMatcherGroup.validate(BodyMatcherGroup.java:30) at io.restassured.internal.assertion.BodyMatcherGroup$validate$3.call(Unknown Source) at io.restassured.internal.ResponseSpecificationImpl$HamcrestAssertionClosure.validate(ResponseSpecificationImpl.groovy:499) at io.restassured.internal.ResponseSpecificationImpl$HamcrestAssertionClosure$validate$1.call(Unknown Source) at io.restassured.internal.ResponseSpecificationImpl.validateResponseIfRequired(ResponseSpecificationImpl.groovy:696) at io.restassured.internal.ResponseSpecificationImpl.this$2$validateResponseIfRequired(ResponseSpecificationImpl.groovy) at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:104) at java.base/java.lang.reflect.Method.invoke(Method.java:565) at org.codehaus.groovy.runtime.callsite.PlainObjectMetaMethodSite.doInvoke(PlainObjectMetaMethodSite.java:43) at org.codehaus.groovy.runtime.callsite.PogoMetaMethodSite$PogoCachedMethodSiteNoUnwrapNoCoerce.invoke(PogoMetaMethodSite.java:198) at org.codehaus.groovy.runtime.callsite.PogoMetaMethodSite.callCurrent(PogoMetaMethodSite.java:62) at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallCurrent(CallSiteArray.java:49) at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:171) at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:185) at io.restassured.internal.ResponseSpecificationImpl.body(ResponseSpecificationImpl.groovy:107) at io.restassured.internal.ValidatableResponseOptionsImpl.body(ValidatableResponseOptionsImpl.java:238) at tests.XMLSchemaValidation.schemaValidation(XMLSchemaValidation.java:48) at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:104) at java.base/java.lang.reflect.Method.invoke(Method.java:565) at org.testng.internal.invokers.MethodInvocationHelper.invokeMethod(MethodInvocationHelper.java:141) at org.testng.internal.invokers.TestInvoker.invokeMethod(TestInvoker.java:687) at org.testng.internal.invokers.TestInvoker.invokeTestMethod(TestInvoker.java:230) at org.testng.internal.invokers.MethodRunner.runInSequence(MethodRunner.java:63) at org.testng.internal.invokers.TestInvoker$MethodInvocationAgent.invoke(TestInvoker.java:995) at org.testng.internal.invokers.TestInvoker.invokeTestMethods(TestInvoker.java:203) at org.testng.internal.invokers.TestMethodWorker.invokeTestMethods(TestMethodWorker.java:154) at org.testng.internal.invokers.TestMethodWorker.run(TestMethodWorker.java:134) at java.base/java.util.ArrayList.forEach(ArrayList.java:1604) at org.testng.TestRunner.privateRun(TestRunner.java:741) at org.testng.TestRunner.run(TestRunner.java:616) at org.testng.SuiteRunner.runTest(SuiteRunner.java:421) at org.testng.SuiteRunner.runSequentially(SuiteRunner.java:413) at org.testng.SuiteRunner.privateRun(SuiteRunner.java:373) at org.testng.SuiteRunner.run(SuiteRunner.java:312) at org.testng.SuiteRunnerWorker.runSuite(SuiteRunnerWorker.java:52) at org.testng.SuiteRunnerWorker.run(SuiteRunnerWorker.java:95) at org.testng.TestNG.runSuitesSequentially(TestNG.java:1274) at org.testng.TestNG.runSuitesLocally(TestNG.java:1208) at org.testng.TestNG.runSuites(TestNG.java:1112) at org.testng.TestNG.run(TestNG.java:1079) at org.testng.remote.AbstractRemoteTestNG.run(AbstractRemoteTestNG.java:115) at org.testng.remote.RemoteTestNG.initAndRun(RemoteTestNG.java:293) at org.testng.remote.RemoteTestNG.main(RemoteTestNG.java:91)
测试代码
File file = new File("./SoapRequests/add.xml"); if(file.exists()) { System.out.println(">>>> File Exists <<<<"); } FileInputStream fileinputstream = new FileInputStream(file); String requestBody = IOUtils.toString(fileinputstream, "UTF-8"); baseURI = "http://www.dneonline.com"; given(). contentType("text/xml"). accept(ContentType.XML). body(requestBody). when(). post("/calculator.asmx"). then(). statusCode(200). log().all(). and(). body("//*:AddResult.text()", equalTo("5")). and(). assertThat().body(matchesXsdInClasspath("Calculator.xsd"));
请求XML文件
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"> <soap:Body> <Add xmlns="http://tempuri.org/"> <intA>2</intA> <intB>3</intB> </Add> </soap:Body> </soap:Envelope>
使用的XSD文件
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" targetNamespace="http://tempuri.org/" xmlns:xs="http://www.w3.org/2001/XMLSchema"> <xs:import namespace="http://schemas.xmlsoap.org/soap/envelope/" schemaLocation="http://schemas.xmlsoap.org/soap/envelope/"/> <xs:element name="AddResponse"> <xs:complexType> <xs:sequence> <xs:element type="xs:byte" name="AddResult"/> </xs:sequence> </xs:complexType> </xs:element> </xs:schema>
解决方案
错误原因
XSD文件中<xs:import>的schemaLocation仍指向远程地址,解析器尝试从该地址下载SOAP信封XSD时,因网络或访问限制导致下载失败,返回空内容,触发“Premature end of file”错误。即使已下载本地XSD文件,解析器也未使用。
修复步骤
- 修改XSD的import路径:将
Calculator.xsd中的<xs:import>语句的schemaLocation改为本地XSD文件名。假设下载的SOAP信封XSD文件名为soap-envelope.xsd,且与Calculator.xsd同处于src/main/resources目录,修改后代码如下:
<xs:import namespace="http://schemas.xmlsoap.org/soap/envelope/" schemaLocation="soap-envelope.xsd"/>
- 确认本地XSD位置:确保
soap-envelope.xsd确实放在src/main/resources目录下,编译后能被类路径加载。 - 重新运行测试:此时解析器会从本地类路径加载导入的XSD文件,无需访问远程地址,即可完成XML响应的验证。
内容的提问来源于stack exchange,提问作者ben ben
相关产品推荐
相关产品推荐

