Проверка XML на XSD в Java / Получение схемы доступа - PullRequest
5 голосов
/ 01 февраля 2012

Как можно проверить XML-файл, используя XSD в Java?Мы не знаем схему заранее.Я хотел бы иметь возможность получить schemaLocation, загрузить XSD, кэшировать его и затем выполнить фактическую проверку.

Проблема в том, что с javax.xml.parsers.DocumentBuilder / DocumentBuilderFactory классами я не могу заранее овладеть schemaLocation.Какой трюк для этого?Какие классы мне следует изучить?

Возможно, есть более подходящий API, который я могу использовать?Вся проблема в том, что нам нужно проверять динамически, без (обязательно) локального наличия XSD.

Как можно получить URL-адрес schemaLocation, определенный в файле XSD?

Я знаю, что вы можете установить функции / атрибуты, но это совсем другое.Мне нужно сначала получить schemaLocation из XSD.

Пожалуйста, сообщите!

1 Ответ

4 голосов
/ 01 февраля 2012

Учитывая, что вы используете Xerces (или JDK по умолчанию), вы пытались установить для этой функции значение true на заводе: http://apache.org/xml/features/validation/schema. Существуют и другие функции, которые вы можете использовать в отношении схем: http://xerces.apache.org/xerces2-j/features.html

ОБНОВЛЕНИЕ 2 (для кэширования):

Реализуйте org.w3c.dom.ls.LSResourceResolver и установите его на SchemaFactory, используя метод setResourceResolver.Этот распознаватель будет либо получать схему из кэша, либо извлекать ее из любого места, к которому относится местоположение.

ОБНОВЛЕНИЕ 3:

Пример LSResourceresolver (который, я думаю, будет хорошей отправной точкой для вас):

/**
 * Resolves resources from a base URL
 */
public class URLBasedResourceResolver implements LSResourceResolver {

private static final Logger log = LoggerFactory
        .getLogger(URLBasedResourceResolver.class);

private final URI base;

private final Map<URI, String> nsmap;

public URLBasedResourceResolver(URL base, Map<URI, String> nsmap)
        throws URISyntaxException {
    super();
    this.base = base.toURI();
    this.nsmap = nsmap;
}

@Override
public LSInput resolveResource(String type, String namespaceURI,
        String publicId, String systemId, String baseURI) {
    if (log.isDebugEnabled()) {
        String msg = String
                .format("Resolve: type=%s, ns=%s, publicId=%s, systemId=%s, baseUri=%s.",
                        type, namespaceURI, publicId, systemId, baseURI);
        log.debug(msg);
    }
    if (type.equals(XMLConstants.W3C_XML_SCHEMA_NS_URI)) {
        if (namespaceURI != null) {
            try {
                URI ns = new URI(namespaceURI);
                if (nsmap.containsKey(ns))
                    return new MyLSInput(base.resolve(nsmap.get(ns)));
            } catch (URISyntaxException e) {
                // ok
            }
        }
    }
    return null;
}

}

Реализация MyLSInput действительно скучна:

class MyLSInput implements LSInput {

private final URI url;

public MyLSInput(URI url) {
    super();
    this.url = url;
}

@Override
public Reader getCharacterStream() {
    return null;
}

@Override
public void setCharacterStream(Reader characterStream) {

}

@Override
public InputStream getByteStream() {
    return null;
}

@Override
public void setByteStream(InputStream byteStream) {

}

@Override
public String getStringData() {
    return null;
}

@Override
public void setStringData(String stringData) {

}

@Override
public String getSystemId() {
    return url.toASCIIString();
}

@Override
public void setSystemId(String systemId) {
}

@Override
public String getPublicId() {
    return null;
}

@Override
public void setPublicId(String publicId) {
}

@Override
public String getBaseURI() {
    return null;
}

@Override
public void setBaseURI(String baseURI) {

}

@Override
public String getEncoding() {
    return null;
}

@Override
public void setEncoding(String encoding) {

}

@Override
public boolean getCertifiedText() {
    return false;
}

@Override
public void setCertifiedText(boolean certifiedText) {

}

}
...