En un mundo ideal, usted podría validar usando un Validator. Algo como esto:
SchemaFactory schemaFactory = SchemaFactory
.newInstance(XMLConstants.XML_DTD_NS_URI);
Schema schema = schemaFactory.newSchema(new File(
"xmlValidate.dtd"));
Validator validator = schema.newValidator();
validator.validate(new StreamSource("xmlValidate.xml"));
Desafortunadamente, la implementación de Sun (al menos, a partir de Java 6) No incluye el apoyo para la creación de una instancia de esquema de una DTD. Es posible que pueda rastrear una implementación de terceros.
Lo mejor que puede hacer es modificar el documento para incluir el DTD antes de realizar el análisis utilizando algún otro mecanismo.
Puede utilizar un transformer para insertar una declaración DTD:
TransformerFactory tf = TransformerFactory
.newInstance();
Transformer transformer = tf.newTransformer();
transformer.setOutputProperty(
OutputKeys.DOCTYPE_SYSTEM, "xmlValidate.dtd");
transformer.transform(new StreamSource(
"xmlValidate.xml"), new StreamResult(System.out));
... pero esto no parece para reemplazar una declaración DTD existente.
Este lector caso StAX puede hacer el trabajo:
public static class DTDReplacer extends
EventReaderDelegate {
private final XMLEvent dtd;
private boolean sendDtd = false;
public DTDReplacer(XMLEventReader reader, XMLEvent dtd) {
super(reader);
if (dtd.getEventType() != XMLEvent.DTD) {
throw new IllegalArgumentException("" + dtd);
}
this.dtd = dtd;
}
@Override
public XMLEvent nextEvent() throws XMLStreamException {
if (sendDtd) {
sendDtd = false;
return dtd;
}
XMLEvent evt = super.nextEvent();
if (evt.getEventType() == XMLEvent.START_DOCUMENT) {
sendDtd = true;
} else if (evt.getEventType() == XMLEvent.DTD) {
// discard old DTD
return super.nextEvent();
}
return evt;
}
}
Se enviará una declaración DTD dado justo después del inicio del documento y descartar cualquier edad desde el documento.
uso Demostración:
XMLEventFactory eventFactory = XMLEventFactory.newInstance();
XMLEvent dtd = eventFactory
.createDTD("<!DOCTYPE Employee SYSTEM \"xmlValidate.dtd\">");
XMLInputFactory inFactory = XMLInputFactory.newInstance();
XMLOutputFactory outFactory = XMLOutputFactory.newInstance();
XMLEventReader reader = inFactory
.createXMLEventReader(new StreamSource(
"xmlValidate.xml"));
reader = new DTDReplacer(reader, dtd);
XMLEventWriter writer = outFactory.createXMLEventWriter(System.out);
writer.add(reader);
writer.flush();
// TODO error and proper stream handling
Tenga en cuenta que la XMLEventReader podría ser la fuente de algún otro mecanismo de transformación que lleva a cabo la validación.
Sería mucho más fácil de validar utilizando un esquema W3 si tiene esa opción.
Muchas gracias por su amplia respuesta, eso realmente me ayuda mucho. Echaré un vistazo para convertir el DTD a un esquema W3, ya que puedo usar el Validator of Sun. – Simon
mi archivo XML no tiene ninguna declaración DOCTYPE. y estoy analizando archivos usando SAXParser en Android. DTD generado por mí mismo. ¿Cómo puedo validar un archivo XML usando mi DTD, en el análisis SAX? –
@Khushbu - sería mejor si hiciera una nueva pregunta. – McDowell