Como saber se um documento XML valida contra um DTD ou XSD?
-
20-08-2019 - |
Pergunta
Em Java, eu posso validar um documento XML contra um esquema XSD usando javax.xml.validation.Validator, ou contra um DTD por simplesmente analisar o documento usando org.xml.sax.XMLReader.
O que eu preciso, porém, é uma maneira de determinar programaticamente se o próprio documento valida contra um DTD (ou seja, ele contém uma declaração <!DOCTYPE ...>
) ou um XSD. Idealmente, eu preciso fazer isso sem carregar todo o documento XML na memória. Alguém pode ajudar por favor?
(Alternativamente, se há um única forma de validar um documento XML em Java que funciona para ambos os XSDs e DTDs - e permite costume resolver de recursos - que seria ainda melhor)
Muito obrigado,
A
Solução
Não há 100% infalível processo para determinar a forma de validar um documento XML arbitrário.
Por exemplo, esta versão 2.4 implantação de aplicativos web descritor especifica um W3 esquema para validar o documento:
<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_ID" version="2.4"
xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
No entanto, esta é uma forma igualmente válida de expressar a mesma coisa:
<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_ID" version="2.4"
xmlns="http://java.sun.com/xml/ns/j2ee">
RELAX NG não parece ter um mecanismo que oferece qualquer dicas em o documento que você deve usá-lo. mecanismos de validação são determinados pelos consumidores documento, e não produtores. Se não me engano, este foi um dos ímpetos de condução da mudança do DTD para mecanismos de validação mais modernos.
Na minha opinião, a sua melhor aposta é a de adaptar o detector mecanismo para o conjunto de tipos de documentos que você está processando, lendo informações de cabeçalho e interpretando-a como apropriado. A StAX analisador é bom para isso - porque é um mecanismo de tração, você pode apenas ler o início do arquivo e em seguida, saia a análise sobre o primeiro elemento
.Link para mais do mesmo e amostra de código e outros enfeites.
Outras dicas
Você poderia simplesmente usar comparações de string?
public enum Type {
XSD,
DTD,
UNKNOWN
};
public Type findType(File f) throws FileNotFoundException, IOException {
BufferedReader reader = null;
try {
reader = new BufferedReader(new FileReader(f));
String line;
// may want to cut this loop off after a certain number of lines
while ((line = reader.readLine()) != null) {
line = line.toLowerCase();
if (line.contains("<!doctype"))
return Type.DTD;
else if (line.contains("xsi:schemaLocation"))
return Type.XSD;
}
} finally {
if (reader != null) {
try {
reader.close();
} catch (IOException ex) {}
}
}
return Type.UNKNOWN;
}
talvez você possa postar um exemplo de código de como você validar um xml contra um dado DTD. Parece ser fácil para um esquema, mas eu estou lutando para encontrar a forma de fazê-lo com um DTD.
Muito obrigado,
Denis.
Ok eu achei:
XMLReader reader = XMLReaderFactory.createXMLReader();
// try to activate validation
try {
// Turn on validation
reader.setFeature("http://xml.org/sax/features/validation", true);
// Ensure namespace processing is on (the default)
reader.setFeature("http://xml.org/sax/features/namespaces", true);
} catch (SAXException e) {
System.err.println("Cannot activate validation.");
}
try {
reader.parse("testFiasRequest.xml");
} catch (IOException e) {
System.err.println("I/O exception reading XML document");
} catch (SAXException e) {
System.err.println("XML exception reading document.");
}