2012-02-01 19 views
5

¿Cómo se puede validar un archivo XML utilizando un XSD en Java? No conocemos el esquema de antemano. Me gustaría poder obtener el schemaLocation, descargar el XSD, almacenarlo en caché y luego realizar la validación real.Validar un XML contra un XSD en Java/Obtener un control del schemaLocation

El problema es que con las clases javax.xml.parsers.DocumentBuilder/DocumentBuilderFactory parece que no puedo conseguir el schemaLocation con antelación. ¿Cuál es el truco para esto? ¿A qué clases debo mirar?

Quizás haya una API más adecuada que pueda usar? Todo el problema es que tenemos que validar dinámicamente, sin (necesariamente) tener los XSD localmente.

¿Cómo podría uno obtener la URL de schemaLocation definida en el archivo XSD?

Sé que puede establecer características/atributos, pero eso es algo diferente. Primero necesito obtener el schemaLocation del XSD.

Por favor, asesóran!

Respuesta

4

Dado que está utilizando Xerces (o valor predeterminado de JDK), ¿ha intentado establecer esta característica en true en la fábrica: http://apache.org/xml/features/validation/schema. Hay otras características que se pueden jugar con respecto a los esquemas: http://xerces.apache.org/xerces2-j/features.html

Update 2 (para el almacenamiento en caché):

Implementar un org.w3c.dom.ls.LSResourceResolver y establecer esto en el SchemaFactory utilizando el método setResourceResolver. Esta resolución obtendría el esquema de la memoria caché o lo buscaría a donde se refiere la ubicación.

Actualización 3:

LSResourceresolver ejemplo (que creo que será un buen punto de partida para usted):

/** 
* 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; 
} 

} 

La implementación de MyLSInput es muy aburrido:

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) { 

} 

} 
+0

En cuanto a la primer enlace: estoy usando xerces: 2.10.0 como una dependencia de Maven independiente fuera del JDK. El segundo enlace no funciona. No me importa usar otra API todos juntos. – carlspring

+0

@carlspring. Ver actualización –

+0

Sí, aunque esto es cierto, todavía no tengo la ubicación del esquema, por lo tanto, no puedo almacenarlo en caché y necesito implementar el almacenamiento en caché. Por lo tanto, realmente necesito obtener el 'schemaLocation' primero. – carlspring

Cuestiones relacionadas