Эта статья является продолжение статьи - Проверка XML XSD с помощью Java XML. В данной статье речь пойдет о том как получить доступ к XSD файлам, которые включают в себя други xsd файлы, которые находятся в jar файлах.

Для того чтобы корректно читать содержимое директории META-INF из jar файла необходимо будет реализовать свой ResourceResolver, с помощью своего резолвера мы сможем читать файлы из jar.

Все достаточно просто, создаем класс ResourcesResolver, который наследует org.w3c.dom.ls.LSResourceResolver и реализуем методы.

package ru.durdyev.xmlutils;
 
import java.io.InputStream;
 
import org.w3c.dom.ls.LSInput;
import org.w3c.dom.ls.LSResourceResolver;
 
public class ResourcesResolver implements LSResourceResolver {
 
    private String path;
     
    public ResourcesResolver(String path) {
        this.path = path;
    }
     
    @Override
    public LSInput resolveResource(String type, String namespaceURI,
            String publicId, String systemId, String baseURI) {
        InputStream resourceAsStream = this.getClass().getClassLoader().getResourceAsStream(path + systemId);
        return new Input(publicId, systemId, resourceAsStream);
    }
}

Метод resolveResource осуществляет поиск ресурса и возвращает нам объект класса org.w3c.dom.ls.LSInput. В моей реализации ResourcesResolver осуществляет поиск по такому пути META-INF/xsd/XSDName.xsd. Далее нам необходимо реализовать org.w3c.dom.ls.LSInput. Создаем класс Input и реализуем методы. Листинг ниже:

package ru.durdyev.xmlutils;
 
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.Reader;
 
import org.w3c.dom.ls.LSInput;
 
public class Input implements LSInput {
 
    private String publicId;
 
    private String systemId;
     
    private BufferedInputStream inputStream;
     
    public Input(String publicId, String sysId, InputStream input) {
        this.publicId = publicId;
        this.systemId = sysId;
        this.inputStream = new BufferedInputStream(input);
    }
 
    public String getPublicId() {
        return publicId;
    }
 
    public void setPublicId(String publicId) {
        this.publicId = publicId;
    }
 
    public String getBaseURI() {
        return null;
    }
 
    public InputStream getByteStream() {
        return null;
    }
 
    public boolean getCertifiedText() {
        return false;
    }
 
    public Reader getCharacterStream() {
        return null;
    }
 
    public String getEncoding() {
        return null;
    }
 
    public String getStringData() {
        synchronized (inputStream) {
            try {
                byte[] input = new byte[inputStream.available()];
                inputStream.read(input);
                String contents = new String(input);
                return contents;
            } catch (IOException e) {
                e.printStackTrace();
                System.out.println("Exception " + e);
                return null;
            }
        }
    }
 
    public void setBaseURI(String baseURI) {
    }
 
    public void setByteStream(InputStream byteStream) {
    }
 
    public void setCertifiedText(boolean certifiedText) {
    }
 
    public void setCharacterStream(Reader characterStream) {
    }
 
    public void setEncoding(String encoding) {
    }
 
    public void setStringData(String stringData) {
    }
 
    public String getSystemId() {
        return systemId;
    }
 
    public void setSystemId(String systemId) {
        this.systemId = systemId;
    }
 
    public BufferedInputStream getInputStream() {
        return inputStream;
    }
 
    public void setInputStream(BufferedInputStream inputStream) {
        this.inputStream = inputStream;
    }
 
}

И далее мы можем использовать ResourceResolver для проверки XML файлов по XSD, которые находятся в jar файлах. Пример кода ниже:

public static boolean validateXMLByXSD(String XML, String path, String XSD)
{
  try {
      SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
      schemaFactory.setResourceResolver(new ResourcesResolver(path));
      Validator xmlValidator = schemaFactory.newSchema(new StreamSource(getClass().
              getClassLoader().getResourceAsStream(path + XSD))).newValidator();
      xmlValidator.validate(new StreamSource(new StringReader(XML)));
  } catch (SAXException e) {
        return false;
  } catch (IOException e) {
        return false;
  }
  return true;
}