2016-08-25 1 views
0

У меня возникла проблема с 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?

Я мог только проверить это последнее решение с несколькими различными случаями, но все работало просто отлично! Если у кого-то есть больше тестовых примеров, пожалуйста, сообщите нам, действительно ли это последнее решение действительно работает в любом случае.

+0

Вы не продемонстрировали, что ваша проблема такая же сложная, как вы описываете. Уменьшите его до [mcve]: покажите минимальный, полный набор XSD и Java-валидации, которые показывают проблему. То, что вы опубликовали, нигде близко не подходит. – kjhughes

+0

Вы добавили фрагменты XSD, но ваша проблема *** все еще не поддается проверке ***: вы опутали множество оборванных ссылок *, включая объявление самого типа **, упомянутого в сообщении об ошибке ***. Опять же, создайте наименьший возможный пример, который полностью демонстрирует проблему, и опубликуйте **, что **. – kjhughes

+0

@kjhughes Я не могу объявить классы, которые я передаю в типе аргумента, и я не могу превратить общедоступные XSD, созданные этими классами. Это я могу написать здесь. Я думаю, что я очень хорошо разделил проблему, которая является методом ** newSchema **, бросающим ту же самую исключение, когда получает массив XSD. Я также упомянул, что когда я отменяю порядок любого массива XSD из своих тестовых примеров, это хорошо работает или когда я нахожу XSD, содержащий импорт с пространством имен, и помещаю этот XSD в первую позицию, это тоже хорошо работает. Наконец, я также ссылался на другие открытые вопросы! –

ответ

0

Я не вижу тип с именем Report (без пространства имен) в любом из этих документов схемы, поэтому сообщение об ошибке кажется мне совершенно законным.

+0

Я обобщил XSD, заменив их содержимое на «** ... **». Обратите внимание, когда я инвертирую порядок массива (решение 1º); или переместить XSD, содержащий импорт с пространством имен, в первую позицию массива, все работает хорошо! Мои вопросы: какой лучший подход? Гарантировано ли, что решение 2º всегда найдет только один XSD, содержащий импорт с пространством имен и просто перенесет его на первую позицию? В чем проблема? Ни одно из обоих решений не кажется мне достаточно общим! –

Смежные вопросы