Валидатор Java XML Schema с пользовательским распознавателем ресурсов не может разрешить элементы

Проверка XML-схемы Java - проблема с ResourceResolver

Я пытаюсь встроить компонент в веб-приложение, которое будет проверять различные документы XML на основе набора схем.

У меня есть класс валидатора в пакете Java com.example.xml, а затем у меня есть "пакет" для схем com.example.xml.Schemas, где они организованы в соответствии с пространством имен вместе с любыми включенными схемами, например так:

com.example.xml/SchemaValidator.java

com.example.xml.Schemas/2008/07/05/Message.xsd
com.example.xml.Schemas/2008/07/05/Person.xsd
com.example.xml.Schemas/2008/07/05/Address.xsd

com.example.xml.Schemas/2010/09/21/Message.xsd
com.example.xml.Schemas/2010/09/21/Organization.xsd
com.example.xml.Schemas/2010/09/21/Person.xsd
com.example.xml.Schemas/2010/09/21/Address.xsd

Таким образом, большинство элементов документа называются сообщениями, но в разных пространствах имен и разных внутренних элементах. С помощью сопоставления я могу определить, где находится правильная схема, и затем загрузить XSD, соответствующий имени корневого элемента, - но чтобы синтаксический анализатор смог прочитать включенные схемы, я попытался выполнить org.w3c.dom.ls. Реализация.LSResourceResolver для получения правильных файлов на основе systemId.

public class ResourceResolver implements LSResourceResolver {
    private String basePath;

    public ResourceResolver( String baseDirectory ){
        basePath = baseDirectory;
        if( !basePath.endsWith("/")){
            basePath += "/";
        }
    }

    @Override
    public LSInput resolveResource(String type, String namespaceURI, String publicId, String systemId, String baseURI) {
        System.out.println("Resolving: " + type + ", " + namespaceURI + ", " +  publicId  + ", " + systemId + ", " + baseURI + " (basepath:" + basePath + ")");
        String mypath = basePath + systemId;
        InputStream resourceAsStream = getClass().getResourceAsStream(mypath);
        if( resourceAsStream == null){ System.out.println("Ups! Stream is null"); }

        String contents = null;
        byte[] bytes = null;
        try {
            bytes = new byte[resourceAsStream.available()];
            resourceAsStream.read(bytes);
            contents = new String(bytes, Charset.forName("UTF-8"));
        } catch (IOException e) { } 
        finally{
            try { resourceAsStream.close(); } 
            catch (IOException e) { }
        }
        Input xmlInput = new Input(resourceAsStream, type, namespaceURI, publicId, systemId, basePath);    
        xmlInput.setStringData(contents);  // avoid problems with inputstream position
        return xmlInput;
    }
}

И мой ResourceResolver используется следующим образом:

public boolean validate(Document doc, String xsdPath) throws SAXException, IOException, ParserConfigurationException {
    SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
    String rootElmtName = doc.getDocumentElement().getLocalName();
    String resourcePath = "/com/example/xml/" + xsdPath ;
    InputStream topSchema = getClass().getResourceAsStream(xsdPath + "/" + rootElmtName + ".xsd");
    Source schemaSource = new StreamSource(topSchema);
    ResourceResolver resolver = new ResourceResolver(resourcePath);
    schemaFactory.setResourceResolver(resolver);
    Schema schema = schemaFactory.newSchema(schemaSource);
    Validator validator = schema.newValidator();
    validator.setResourceResolver(resolver);
    Source source = new DOMSource(doc);

    ValidationErrorHandler handler = new ValidationErrorHandler();
    validator.setErrorHandler(handler);
    validator.validate(source);
    if(handler.hasErrors()){
        for( ValidationError e : handler.getErrors()){
            log(e);
        }
        return false;
    }
    return true;
}

Тем не менее, это не работает! Он разрешает несколько ресурсов схемы и затем останавливается. Я попытался установить точку останова в Eclipse в моем преобразователе ресурсов, и значение inputtream не является нулевым - оно указывает на нужный файл, содержащий XSD. Поэтому что-то в классах синтаксического анализатора Java XML должно ожидать какого-то другого поведения от моего преобразователя.

Resolving: http://www.w3.org/2001/XMLSchema, http://com/example/xml/schemas/2005/08/07/, null, Letters.xsd, file:///com/example/xml/Schemas/2005/08/07/Message.xsd (basepath:/com/example/xml/Schemas/2005/08/07/)
Resolving: http://www.w3.org/2001/XMLSchema, http://com/example/xml/schemas/2005/08/07/, null, GeneralElements.xsd, file:///com/example/xml/Schemas/2005/08/07/Message.xsd (basepath:/com/example/xml/Schemas/2005/08/07/)
Resolving: http://www.w3.org/2001/XMLSchema, http://com/example/xml/schemas/2005/08/07/, null, GeneralTypes.xsd, file:///com/example/xml/Schemas/2005/08/07/Message.xsd (basepath:/com/example/xml/Schemas/2005/08/07/)
Exception in thread "main" org.xml.sax.SAXParseException: src-resolve: Cannot resolve the name 'Letters' to a(n) 'group' component.
    at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.createSAXParseException(ErrorHandlerWrapper.java:195)
    at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.error(ErrorHandlerWrapper.java:131)
    at com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(XMLErrorReporter.java:384)
    at com.sun.org.apache.xerces.internal.impl.xs.traversers.XSDHandler.reportSchemaErr(XSDHandler.java:2537)
    at com.sun.org.apache.xerces.internal.impl.xs.traversers.XSDHandler.reportSchemaError(XSDHandler.java:2528)
    at com.sun.org.apache.xerces.internal.impl.xs.traversers.XSDHandler.getGlobalDecl(XSDHandler.java:1472)
    at com.sun.org.apache.xerces.internal.impl.xs.traversers.XSDGroupTraverser.traverseLocal(XSDGroupTraverser.java:72)

Содержимое Message.xsd содержит что-то вроде этого:

<xs:include schemaLocation="Letters.xsd"/>
<xs:include schemaLocation="GeneralElements.xsd"/>
<xs:include schemaLocation="GeneralTypes.xsd"/>
<xs:element name="Message"> 

-и Letters.xsd также содержит

<xs:include schemaLocation="GeneralElements.xsd"/>
<xs:include schemaLocation="GeneralTypes.xsd"/>
<xs:group name="Letters">

Краткое описание классов ResourceResolver и Input относится к другому SO сообщению, так что я мог что-то неправильно понять.

Это правильный способ, которым я создал распознаватель ресурсов, или я что-то пропустил полностью?

0 ответов

Другие вопросы по тегам