Java 11 Spring Boot 2.7中如何用含import的XSD验证XML
解决Spring Boot中XSD导入文件的验证问题(JAR包部署场景)
问题原因
你之前传入多个StreamSource的方式无效,是因为主XSD中的相对路径导入(如core-schema.xsd)无法与你手动传入的第二个StreamSource关联——StreamSource本身不带位置上下文,SchemaFactory不知道这个流对应的就是导入语句里的文件。
解决方案
针对JAR包中resources目录下的XSD文件,有两种可靠的实现方式:
方法一:给StreamSource设置正确的SystemId(推荐)
利用类加载器获取XSD资源的URL,将其作为StreamSource的systemId,这样SchemaFactory就能根据主XSD的位置上下文自动解析相对路径的导入文件。
代码示例:
SchemaFactory sf = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); // 加载主XSD的输入流和资源URL String mainXsdName = "your-main-schema.xsd"; // 替换为你的主XSD文件名 InputStream mainXsdStream = classLoader.getResourceAsStream(mainXsdName); URL mainXsdUrl = classLoader.getResource(mainXsdName); StreamSource mainSource = new StreamSource(mainXsdStream); // 设置systemId为资源的URL字符串,提供位置上下文 mainSource.setSystemId(mainXsdUrl.toExternalForm()); // 创建Schema和Validator Schema schema = sf.newSchema(mainSource); Validator validator = schema.newValidator(); // 验证XML内容 StringReader xmlReader = new StringReader(content); validator.validate(new StreamSource(xmlReader));
原理:主XSD的systemId是其在JAR包中的完整资源URL(如jar:file:/app.jar!/BOOT-INF/classes!/your-main-schema.xsd),SchemaFactory解析导入语句时,会基于这个URL的父路径拼接core-schema.xsd,自动找到对应的资源并加载。
方法二:自定义LSResourceResolver(灵活扩展)
如果需要更灵活的资源加载逻辑(比如XSD分布在不同目录),可以实现LSResourceResolver,手动处理导入文件的加载。
代码示例:
SchemaFactory sf = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); // 设置自定义资源解析器 sf.setResourceResolver((type, namespaceURI, publicId, systemId, baseURI) -> { // systemId就是导入语句中的schemaLocation(如"core-schema.xsd") InputStream xsdStream = classLoader.getResourceAsStream(systemId); if (xsdStream == null) { throw new IllegalArgumentException("找不到指定的XSD文件: " + systemId); } LSInput lsInput = sf.newLSInput(); lsInput.setByteStream(xsdStream); lsInput.setSystemId(systemId); return lsInput; }); // 加载主XSD InputStream mainXsdStream = classLoader.getResourceAsStream("your-main-schema.xsd"); Schema schema = sf.newSchema(new StreamSource(mainXsdStream)); Validator validator = schema.newValidator(); // 验证XML内容 StringReader xmlReader = new StringReader(content); validator.validate(new StreamSource(xmlReader));
原理:当SchemaFactory遇到导入语句时,会调用自定义的resolveResource方法,你可以根据systemId直接从resources目录加载对应的XSD文件。
内容的提问来源于stack exchange,提问作者anonyme
相关产品推荐
相关产品推荐

