Загружается ли импорт XSD автоматически при загрузке ресурса?
Я использую следующие фрагменты, чтобы сделать объект схемы внутри статического блока:
URL url = getClass().getClassLoader().getResource("test.xsd");
и test.xsd импортирует три других файла XSD,
Мой вопрос заключается в том, будут ли доступны импорт, когда будет сделана ссылка на них (например, при проверке), или мне придется загружать импорт специально, создав объект URL.
3 ответа
Потому что, когда вы используете getClass().getClassLoader().getResource("test.xsd");
вы на самом деле не загружаете test.xsd
, но только получить URL к нему вам больше ничего не нужно делать.
XSD import
имеет значение только для соответствующих инструментов. В качестве примера валидатора.
Таким образом, когда вы передаете расположение схемы в валидатор, это может быть абсолютный путь, относительный путь к текущему рабочему каталогу или URL.
Затем, когда валидатор обрабатывает XSD, он пытается получить imports
Точно так же - абсолютный путь, относительно test.xsd
расположение схемы или URL, как это определено в test.xsd
,
Нет, вам придется загружать импортированные XSD явно, потому что getResource()
не знает семантики XSD - он работает на уровне ресурсов / файлов, а не на уровне XSD.
Если вы хотите реализовать валидатор xml с ресурсами xsd, вам необходимо создать собственный LSResourceResolver
для примера: учитывая, что я загружаю base.xsd, который импортирует "my_complex.xsd", "my_types.xsd"
class LSInputImpl implements LSInput {
private byte[] bytes;
private String publicId;
private String systemId;
private String baseURI;
...
}
class SchemaResourceResolver implements LSResourceResolver{
public static List<String> schemas = Arrays.asList("my_complex.xsd","my_types.xsd");
@Override
public LSInput resolveResource(String type, String namespaceURI, String publicId, String systemId,String baseURI) {
if(schemas.contains(systemId)){
LSInputImpl input = new LSInputImpl();
InputStream in = UtilFile.resourceInputStream("relative/resource/path/"+systemId);
input.setByteStream(in);
input.setSystemId(systemId);
input.setPublicId(publicId);
input.setBaseURI(baseURI);
return input;
}
return null;
}
}
public class XmlValidator {
public static boolean validateSchema(InputStream xsd,InputStream xml ){
try {
// Create a SchemaFactory and specify XML schema language
SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
// Set the custom resource resolver
factory.setResourceResolver(new SchemaResourceResolver());
// Load the schema from file
Schema schema = factory.newSchema(new StreamSource(xsd));
// Create a Validator instance from the schema
Validator validator = schema.newValidator();
// Create a Source from the XML string
Source source = new StreamSource(xml);
// Perform the validation
validator.validate(source);
// If no exception is thrown, the XML is valid
System.out.println("XML is valid.");
return true;
} catch (SAXException e) {
System.out.println("XML is not valid: " + e.getMessage());
} catch (Exception e) {
System.out.println("Error during XML validation: " + e.getMessage());
}
return false;
}
public static void main(String[] args) {
try {
InputStream xsd = UtilFile.resourceInputStream("relative/resource/path/base.xsd");
InputStream xml = UtilFile.loadFile("/samples/test.xml");
validateSchema(xsd, xml);
} catch (IOException e) {
e.printStackTrace();
}
}
для LSInputImpl важно преобразовать byteStream в bytes[] для его кратного чтения, в противном случае вы получите ошибку: неожиданный конец файла, поскольку входной поток уже прочитан