2009-11-13 6 views
6

Ich versuche, ein ziemlich kompliziertes XML-Schema in ein Schema-Objekt in Java zu parsen, damit ich XML-Nachrichten validieren kann.Schema in Java parsen Mit Importen und Includes?

Mein Code sieht ähnlich wie:

SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); 
Schema schema = factory.newSchema(new StreamSource(new File("schema/schema.xsd"))); 

Mein Schema hat einige Importe:

<?xml version="1.0" encoding="UTF-8"?> 
    <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns="base_1"> 
    <xs:import namespace="base_1" schemaLocation="common/MessageBase.xsd"/> 
</xs:schema>

... etc. Wenn ich versuche, das Schema zu laden, erhalte ich viele Fehler. Basierend auf einer anderen Frage, die damit zusammenhängt, scheint es, dass ich einen Ressourcen-Resolver angeben muss, aber sollte das nicht standardmäßig behandelt werden?

Wenn ja, gibt es ein bestimmtes Verzeichnis, in dem ich das Schema relativ zum Speicherort der Anwendung, die ich schreibe, oder relativ zur Basisschemadatei einfügen muss?

Schließlich, wenn ich das Schema mit XMLSpy oder ähnlichem laden, funktioniert es gut und ich kann XML-Instanzen ohne Problem validieren.

Antwort

8

Ich denke, dass die Verwendung von StreamSource, ohne Angabe des Basisstandortes, die Quelle Ihres Problems ist.

Der Parser hat keine Möglichkeit zu wissen, wo das Hauptschema ist, daher kann common/MessageBase.xml nicht aufgelöst werden.

Verwenden Sie den Konstruktor mit zwei Argumenten und übergeben Sie eine SystemID, bei der es sich um den Pfadnamen handelt, von dem Sie ausgehen.

Siehe das Javadoc für StreamSource.

+0

dies versucht und immer noch die folgende Fehlermeldung erhalten: src-resolve: ‚: StatusWithError_optional Basis‘ zu einem (n) ‚Attributgruppe‘ Komponente kann den Namen nicht auflösen. – magneticMonster

+0

Das ist ein anderes Thema. Es deutet darauf hin, dass Ihr Schema nicht vollständig und in sich abgeschlossen ist. Haben Sie eine Attributgruppe namens StatusWithError_optional? Ist es im richtigen Namensraum? – bmargulies

+0

Ja, es ist in einer separaten Datei auf der gleichen Ebene wie die Basis-Schemadatei definiert. Gleicher Namespace. Soll die SystemID der Pfad zur Root-XSD-Datei oder zum Root-Verzeichnis für das Schema sein? Was ist mit dem anderen Argument des 2-Arg-Konstruktors? – magneticMonster

2

Um die importierten XSDs Sie das Schema ab Werk mit einer Ressource Resolver zuordnen zu lösen haben:

SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); 
factory.setResourceResolver(new MyResourceResolver()); 
Schema schema = factory.newSchema(new StreamSource(new File("schema/schema.xsd"))); 

Weitere Einzelheiten entnehmen Sie in diesem answer aussehen kann.

7

Wenn Sie eine URL anstelle einer StreamSource verwenden, ist kein Ressourcen-Resolver erforderlich.

URL schemaURL = Thread.currentThread().getContextClassLoader().getResource(schemaFileName); 
SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); 
Schema schema = schemaFactory.newSchema(schemaURL); 
+0

+1 für die viel einfachere Lösung! Arbeitete für mich. – AKeefe

+0

es ist einfach, da es nicht Resolver erforderlich ist. – ulab

+2

Ich habe es schon mit einer URL gemacht, aber habe die Ressourcen für mich nicht richtig auflösen können, als es mit Importen zu tun hatte. Ich habe einen ResourceResolver verwendet, der jedoch behoben wurde. Warum es für dich funktioniert, und nicht für mich bleibt die Frage. vielleicht hat es etwas mit der Projektstruktur zu tun. Die Pfade in meinen xsd-Dateien sind relativ zu meinem Java-Klassenpfad. Meine beste Vermutung ist, dass Ihre Pfade relativ zu Ihrem Arbeitsordner sind. – bvdb