У меня возникла проблема с API проверки Java Java. Когда массив XSDs (файлы схемы) передаются метода javax.xml.validation.SchemaFactory.newSchema (Источник [] схема), он выдает следующее исключение:Создание схем из массивов XSD
org.xml.sax.SAXParseException; src-resolve: Cannot resolve the name 'Report' to a(n) 'type definition' component.
at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.createSAXParseException(ErrorHandlerWrapper.java:198)
at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.error(ErrorHandlerWrapper.java:134)
at com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(XMLErrorReporter.java:396)
at com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(XMLErrorReporter.java:306)
at com.sun.org.apache.xerces.internal.impl.xs.traversers.XSDHandler.reportSchemaErr(XSDHandler.java:4162)
at com.sun.org.apache.xerces.internal.impl.xs.traversers.XSDHandler.reportSchemaError(XSDHandler.java:4141)
at com.sun.org.apache.xerces.internal.impl.xs.traversers.XSDHandler.getGlobalDecl(XSDHandler.java:1674)
at com.sun.org.apache.xerces.internal.impl.xs.traversers.XSDElementTraverser.traverseNamedElement(XSDElementTraverser.java:405)
at com.sun.org.apache.xerces.internal.impl.xs.traversers.XSDElementTraverser.traverseGlobal(XSDElementTraverser.java:242)
at com.sun.org.apache.xerces.internal.impl.xs.traversers.XSDHandler.traverseSchemas(XSDHandler.java:1429)
at com.sun.org.apache.xerces.internal.impl.xs.traversers.XSDHandler.parseSchema(XSDHandler.java:626)
at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaLoader.loadSchema(XMLSchemaLoader.java:613)
at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaLoader.loadGrammar(XMLSchemaLoader.java:572)
at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaLoader.loadGrammar(XMLSchemaLoader.java:538)
at com.sun.org.apache.xerces.internal.jaxp.validation.XMLSchemaFactory.newSchema(XMLSchemaFactory.java:252)
...
Ниже показана часть из код, используемый для создания схемы.
public static Object converToObject(byte[] xmlByteBuffer, int offset, int length, Class<?>... type) throws JAXBException {
JAXBContext context = JAXBContext.newInstance(type);
final List<DOMResult> results = new ArrayList<DOMResult>();
try {
context.generateSchema(new SchemaOutputResolver() {
@Override
public Result createOutput(String namespaceUri, String suggestedFileName) throws IOException {
DOMResult result = new DOMResult();
result.setSystemId(suggestedFileName);
results.add(result);
return result;
}
});
} catch (IOException e1) {
e1.printStackTrace();
}
final SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
DOMSource[] sources = new DOMSource[results.size()];
for (int i = 0; i < results.size(); i++) {
DOMResult result = results.get(i);
Node node = result.getNode();
sources[i] = new DOMSource(node);
}
// First Solution: Reverse Order
// DOMSource[] resortedSources = new DOMSource[results.size()];
// for(int i=1; i<results.size(); i++){
// sourcesSorted[results.size()-(i+1)] = sources[i];
// }
// Second Solution: Look for the XSD with imports with namespace
// attribute
for (int i = 0; i < results.size(); i++) {
Node node = sources[i].getNode();
if(thereIsElementImportWithAttributeNamespace(node)) {
DOMSource sourceBackup = sources[0];
sources[0] = sources[i];
sources[i] = sourceBackup;
break;
}
}
Schema schema = null;
try {
schema = schemaFactory.newSchema(sources);
// schema = schemaFactory.newSchema(resortedSources);
} catch (SAXException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Unmarshaller unmarshaller = context.createUnmarshaller();
unmarshaller.setSchema(schema);
unmarshaller.setEventHandler(new javax.xml.bind.helpers.DefaultValidationEventHandler());
String str;
try {
str = new String(xmlByteBuffer, offset, length, "UTF-8");
} catch (UnsupportedEncodingException uee) {
try {
str = new String(xmlByteBuffer, "ISO-8859-1");
} catch (UnsupportedEncodingException ex) {
throw new JAXBException(ex);
}
}
StreamSource ss = new StreamSource(new StringReader(str));
Object obj = unmarshaller.unmarshal(ss);
return obj;
}
Ниже приведены печатные части истинных XSDs, которые передаются методу newSchema.
schema1.xsd:
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="http://service.mw.uw/" version="1.0">
<xs:import schemaLocation="schema4.xsd"/>
<xs:element name="Report" type="Report"/>
...
</xs:schema>
schema2.xsd:
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="http://service.gather.mw.uw/" version="1.0">
<xs:import schemaLocation="schema4.xsd"/>
<xs:element name="DataReport" type="DataReport"/>
...
</xs:schema>
schema3.xsd:
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:tns="http://service.commons.uw/" targetNamespace="http://service.commons.uw/" version="1.0">
<xs:import schemaLocation="schema4.xsd"/>
<xs:element name="ApplicationRequest" type="ApplicationRequest"/>
...
</xs:schema>
schema4.xsd:
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:ns1="http://service.commons.uw/" xmlns:ns2="http://service.gather.mw.uw/" version="1.0">
<xs:import namespace="http://service.commons.uw/" schemaLocation="schema3.xsd"/>
<xs:import namespace="http://service.gather.mw.uw/" schemaLocation="schema2.xsd"/>
<xs:complexType name="message">
...
</xs:complexType>
...
</xs:schema>
Оно пронеслось, что SchemaFactory.newSchema не может иметь дело с несколькими XSDs импортерах несколько XSDs.
Согласно Hedleys, решением будет сортировать любой массив XSD с импортированными XSD перед теми, которые фактически импортируют их. Я столкнулся с проблемой с этим решением, потому что в моем проекте существует несколько взаимного импорта среди XSD. Так как это могло быть отсортировано?
Также, согласно jtahlborn, еще одним решением является применение XSD-массивов в обратном порядке. Это сработало хорошо! Тем не менее, я продолжал исследовать проблему, потому что в то время у меня было всего несколько различных случаев, чтобы проверить, достаточно ли это решение!
Java-Документирование метод SchemaFactory.newSchema государства следующее: «Раздел 4.2.3 рекомендации XML-схемы описаны варианты процессоров, которые есть в этом отношении Хотя процессор должен быть последовательным в лечении JAXP схемы. источников и импорта XML-схем, поведение между синтаксическими анализаторами, совместимыми с JAXP, может различаться, в частности, синтаксические анализаторы могут выбрать игнорировать все, кроме первого для данного пространства имен, независимо от информации, представленной в схеме Location ». Поэтому, основываясь на этом заявлении, я мог бы исправить упомянутое выше исключение, поставив XSD с импортом, содержащим атрибут пространства имен, в первую позицию массива XSD. Итак, наконец, здесь возникает мой вопрос:
Является ли причиной исключения отсутствие атрибута пространства имен в импорте первого XSD из массива XSD?
Я мог только проверить это последнее решение с несколькими различными случаями, но все работало просто отлично! Если у кого-то есть больше тестовых примеров, пожалуйста, сообщите нам, действительно ли это последнее решение действительно работает в любом случае.
Вы не продемонстрировали, что ваша проблема такая же сложная, как вы описываете. Уменьшите его до [mcve]: покажите минимальный, полный набор XSD и Java-валидации, которые показывают проблему. То, что вы опубликовали, нигде близко не подходит. – kjhughes
Вы добавили фрагменты XSD, но ваша проблема *** все еще не поддается проверке ***: вы опутали множество оборванных ссылок *, включая объявление самого типа **, упомянутого в сообщении об ошибке ***. Опять же, создайте наименьший возможный пример, который полностью демонстрирует проблему, и опубликуйте **, что **. – kjhughes
@kjhughes Я не могу объявить классы, которые я передаю в типе аргумента, и я не могу превратить общедоступные XSD, созданные этими классами. Это я могу написать здесь. Я думаю, что я очень хорошо разделил проблему, которая является методом ** newSchema **, бросающим ту же самую исключение, когда получает массив XSD. Я также упомянул, что когда я отменяю порядок любого массива XSD из своих тестовых примеров, это хорошо работает или когда я нахожу XSD, содержащий импорт с пространством имен, и помещаю этот XSD в первую позицию, это тоже хорошо работает. Наконец, я также ссылался на другие открытые вопросы! –