validar restricciones que para opcional elemento con como atributos archivo java xml validation dtd

restricciones - Validar un archivo XML contra un archivo DTD local con Java



xs element atributos (3)

¿Cómo puedo validar un archivo XML contra una DTD que se almacena localmente como un archivo? El archivo XML no tiene ninguna declaración DOCTYPE (o puede tener una que debe ser anulada). Eché un vistazo a este hilo, pero además de que están usando .NET, dudo que esta sea una buena solución.

Cualquier entrada apreciada!


En un mundo ideal, podrías 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 soporte para crear una instancia de Schema a partir de una DTD. Es posible que pueda rastrear una implementación de terceros.

Su mejor opción puede ser alterar el documento para incluir la DTD antes de analizar usando algún otro mecanismo.

Puede usar 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 reemplazar una declaración de DTD existente.

Este lector de eventos 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; } }

Enviará una declaración de DTD determinada justo después de que se inicie el documento y descartará cualquiera del documento anterior.

Uso de 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 XMLEventReader podría formar la fuente de algún otro mecanismo de transformación que realizó la validación.

Sería mucho más fácil validar usando un esquema W3 si tiene esa opción.


Estoy bastante seguro de que las cosas antes mencionadas funcionarán ...

Gracias por su ayuda, pero ¿y si no se ha especificado DOCTYPE en absoluto? El EntityResolver no me ayudaría en ese caso, ¿verdad? - Simon Jul 8 ''09 a las 6:34

@Bluegene: ¿En qué estás validando si no hay DOCTYPE? - J-16 SDiZ Jul 8 ''09 a las 7:12

Contra mi propia DTD. Solo quiero asegurarme de que el XML que recibo se ajusta a mi DTD, no a cualquier DTD que especifique el remitente. - Simon Jul 8 ''09 a las 23:09

Si el problema es que desea que se valide contra su dtd en lugar de los autores, debe asegurarse de que haya documentación clara que detalla el doctype y lo que debe estar en el archivo xml.


EntityResolver implementar el EntityResolver , consulte este ejemplo .