使用 XSD 加载为文件与输入流进行 XML 验证

问题描述 投票:0回答:1

如果 XSD 作为文件或资源加载,我在 XML 验证中会遇到不同的行为。

如果我将 XSD 作为文件加载,一切都很好并且验证工作正常:

SchemaFactory sf = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
Schema schema = sf.newSchema(new ClassPathResource("my/perfect/path/myFile.xsd").getFile());
Validator validator = schema.newValidator();
validator.validate(sourceToValidate);

相反,因为我决定将 xsd 文件包含到 jar 中,所以我将其作为资源加载,但行为不同,当我构建架构时,我遇到了 SAXParseException,并且错误抱怨在解析 xsd 文件中的名称时出现一些问题:类型定义。 xsd 文件绝对正确

SchemaFactory sf = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
InputStream inputStream = getClass().getClassLoader().getResourceAsStream("my/perfect/path/myFile.xsd");
Source schemaSource = new StreamSource(inputStream);
Schema schema = sf.newSchema(schemaSource); // here i get the SAXParseException
Validator validator = schema.newValidator();
validator.validate(sourceToValidate);

我真的不明白为什么加载 xsd 作为 ResourceAsStream 会导致不同的行为

我使用 JAXB 进行 xml 验证

java xml xsd-validation
1个回答
0
投票

我猜测您的 xsd 引用了其他 xsd,并且您的验证器不知道如何解析这些引用。

您可能需要向 Validator

 提供 
LSResourceResolver

ClassLoader loader = getClass().getClassLoader();
LSResourceResolver resolver = new LSResourceResolver() {
   public LSInput resolveResource(String type, String namespaceURI, String publicId, String systemId, String baseURI) {
      InputStream stream = loader.getResourceAsStream(systemId);
      if (stream == null) throw new RuntimeException("Could not find " + systemId);
      LSInput input = new DOMInputImpl();
      input.setPublicId(publicId);
      input.setSystemId(systemId);
      input.setBaseURI(baseURI);
      input.setByteStream(stream);             
      return input;
   }
};
Validator validator = schema.newValidator();
validator.setResourceResolver(resolver);

您还需要通过调用

systemId
的两个参数构造函数来设置
InputSource
上的
StreamSource

String xsdPath = "my/perfect/path/myFile.xsd";
InputStream inputStream = getClass().getClassLoader().getResourceAsStream(xsdPath);
Source schemaSource = new StreamSource(inputStream, xsdPath);

参见 StreamSource(InputStream, String)

除了输入流之外,此构造函数还允许设置 systemID,从而允许处理相对 URI。

© www.soinside.com 2019 - 2024. All rights reserved.