Frage

Ich bin Generierung von xml-Dateien, die Anforderungen zu entsprechen, eine xsd-Datei, die mir geschenkt wurde.Was ist der beste Weg, um zu überprüfen, ob Sie übereinstimmen?

War es hilfreich?

Lösung

Die Java-runtime-Bibliothek unterstützt die Validierung.Letztes mal habe ich überprüft, das war der Apache Xerces parser unter der Decke.Sie sollten wahrscheinlich verwenden Sie einen javax.xml.Validierung.Validator.

import javax.xml.XMLConstants;
import javax.xml.transform.Source;
import javax.xml.transform.stream.StreamSource;
import javax.xml.validation.*;
import java.net.URL;
import org.xml.sax.SAXException;
//import java.io.File; // if you use File
import java.io.IOException;
...
URL schemaFile = new URL("http://host:port/filename.xsd");
// webapp example xsd: 
// URL schemaFile = new URL("http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd");
// local file example:
// File schemaFile = new File("/location/to/localfile.xsd"); // etc.
Source xmlFile = new StreamSource(new File("web.xml"));
SchemaFactory schemaFactory = SchemaFactory
    .newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
try {
  Schema schema = schemaFactory.newSchema(schemaFile);
  Validator validator = schema.newValidator();
  validator.validate(xmlFile);
  System.out.println(xmlFile.getSystemId() + " is valid");
} catch (SAXException e) {
  System.out.println(xmlFile.getSystemId() + " is NOT valid reason:" + e);
} catch (IOException e) {}

Das schema Fabrik constant string http://www.w3.org/2001/XMLSchema die XSDs definiert.Der obige code überprüft, die einen KRIEG deployment-descriptor gegen den URL http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd aber Sie könnten genauso leicht zu überprüfen anhand einer lokalen Datei.

Sie sollten nicht die DOMParser zu validieren eines Dokuments (es sei denn, Ihr Ziel ist zu erstellen ein Dokument-Objekt-Modell sowieso).Dies wird starten Sie die Erstellung von DOM-Objekten, wie es analysiert das Dokument - verschwenderisch, wenn Sie nicht gehen, um Sie zu benutzen.

Andere Tipps

Hier ist, wie man es Xerces2.Ein tutorial für diese, hier (erf.signup).

Original attribution:unverhohlen kopiert von hier:

import org.apache.xerces.parsers.DOMParser;
import java.io.File;
import org.w3c.dom.Document;

public class SchemaTest {
  public static void main (String args[]) {
      File docFile = new File("memory.xml");
      try {
        DOMParser parser = new DOMParser();
        parser.setFeature("http://xml.org/sax/features/validation", true);
        parser.setProperty(
             "http://apache.org/xml/properties/schema/external-noNamespaceSchemaLocation", 
             "memory.xsd");
        ErrorChecker errors = new ErrorChecker();
        parser.setErrorHandler(errors);
        parser.parse("memory.xml");
     } catch (Exception e) {
        System.out.print("Problem parsing the file.");
     }
  }
}

Wir bauen unser Projekt mit ant, so können wir die schemavalidate Aufgabe zu überprüfen unsere config-Dateien:

<schemavalidate> 
    <fileset dir="${configdir}" includes="**/*.xml" />
</schemavalidate>

Jetzt naughty config-Dateien nicht unser bauen!

http://ant.apache.org/manual/Tasks/schemavalidate.html

Da dies eine beliebte Frage, werde ich darauf hinweisen, dass java kann auch die Validierung gegen "im Sinne von" xsd ist, zum Beispiel, wenn die .xml-Datei selbst XSD ist in der Kopfzeile mit xsi:SchemaLocation oder xsi:noNamespaceSchemaLocation (oder xsi für bestimmte namespaces) ex:

<document xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:noNamespaceSchemaLocation="http://www.example.com/document.xsd">
  ...

oder SchemaLocation (immer eine Liste von Namensraum in xsd-Zuordnungen)

<document xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:SchemaLocation="http://www.example.com/my_namespace http://www.example.com/document.xsd">
  ...

Die anderen Antworten hier funktionieren so gut, weil die .xsd-Dateien "Karte", um die namespaces deklariert .xml-Datei, da Sie erklären, dass Sie einen namespace, und wenn übereinstimmungen mit dem namespace in .xml-Datei, du bist gut.Aber manchmal ist es praktisch, in der Lage sein, um eine benutzerdefinierte resolver...

Aus den javadocs:"Wenn Sie ein schema erstellen, ohne Angabe einer URL, Datei oder Quelle, dann die Java-Sprache erstellt eine sieht in dem Dokument wird validiert zu finden, das schema zu verwenden.Zum Beispiel:"

SchemaFactory factory = SchemaFactory.newInstance("http://www.w3.org/2001/XMLSchema");
Schema schema = factory.newSchema();

und das funktioniert für mehrere namespaces, etc.Das problem bei diesem Ansatz ist, dass der xmlsns:xsi ist wahrscheinlich ein Speicherort im Netzwerk, so wird es standardmäßig gehen und traf das Netz, und das bei jedem Validierung, nicht immer optimal.

Hier ist ein Beispiel, die Bestätigung einer XML-Datei gegen jede XSD ist es verweist (auch wenn es nur ziehen Sie Sie aus dem Netzwerk):

  public static void verifyValidatesInternalXsd(String filename) throws Exception {
    InputStream xmlStream = new new FileInputStream(filename);
    DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
    factory.setValidating(true);
    factory.setNamespaceAware(true);
    factory.setAttribute("http://java.sun.com/xml/jaxp/properties/schemaLanguage",
                 "http://www.w3.org/2001/XMLSchema");
    DocumentBuilder builder = factory.newDocumentBuilder();
    builder.setErrorHandler(new RaiseOnErrorHandler());
    builder.parse(new InputSource(xmlStream));
    xmlStream.close();
  }

  public static class RaiseOnErrorHandler implements ErrorHandler {
    public void warning(SAXParseException e) throws SAXException {
      throw new RuntimeException(e);
    }
    public void error(SAXParseException e) throws SAXException {
      throw new RuntimeException(e);
    }
    public void fatalError(SAXParseException e) throws SAXException {
      throw new RuntimeException(e);
    }
  }

Sie können vermeiden, ziehen referenzierten XSD aus dem Netzwerk, auch wenn die xml-Dateien, die Referenz-url, indem Sie die xsd manuell (siehe einigen anderen Antworten hier) oder indem Sie einen "XML-Katalog" Stil-resolver.Der Frühling anscheinend auch abfangen können die URL-Anfragen zu dienen, lokale Dateien für Validierungen.Oder Sie können Ihre eigenen über setResourceResolver, ex:

Source xmlFile = new StreamSource(xmlFileLocation);
SchemaFactory schemaFactory = SchemaFactory
                                .newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
Schema schema = schemaFactory.newSchema();
Validator validator = schema.newValidator();
validator.setResourceResolver(new LSResourceResolver() {
  @Override
  public LSInput resolveResource(String type, String namespaceURI,
                                 String publicId, String systemId, String baseURI) {
    InputSource is = new InputSource(
                           getClass().getResourceAsStream(
                          "some_local_file_in_the_jar.xsd"));
                          // or lookup by URI, etc...
    return new Input(is); // for class Input see 
                          // https://stackoverflow.com/a/2342859/32453
  }
});
validator.validate(xmlFile);

Siehe auch hier für ein weiteres tutorial.

Ich glaube, der Standard ist die Verwendung von DOM-parsing, Sie können tun, etwas ähnliches mit SAX-parser überprüft wird sowie saxReader.setEntityResolver(your_resolver_here);

Mit Java 7 können Sie die Dokumentation im Paket Beschreibung.

// parse an XML document into a DOM tree
DocumentBuilder parser = DocumentBuilderFactory.newInstance().newDocumentBuilder();
Document document = parser.parse(new File("instance.xml"));

// create a SchemaFactory capable of understanding WXS schemas
SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);

// load a WXS schema, represented by a Schema instance
Source schemaFile = new StreamSource(new File("mySchema.xsd"));
Schema schema = factory.newSchema(schemaFile);

// create a Validator instance, which can be used to validate an instance document
Validator validator = schema.newValidator();

// validate the DOM tree
try {
    validator.validate(new DOMSource(document));
} catch (SAXException e) {
    // instance document is invalid!
}

Wenn Sie eine Linux-Maschine können Sie mit der kostenlosen Kommandozeilen-tool SAXCount.Ich fand das sehr nützlich.

SAXCount -f -s -n my.xml

Es bestätigt, gegen die dtd und xsd.5s für eine 50 MB-Datei.

In debian squeeze es befindet sich im Paket "libxerces-c-samples".

Die definition der dtd-und xsd in xml!Sie können nicht config Ihnen getrennt.

Eine weitere Antwort:da du gesagt, Sie müssen überprüfen Sie Dateien, die Sie sind Erzeugung (das schreiben), die Sie möglicherweise überprüfen möchten Inhalte, während Sie schreiben, anstatt zuerst schreiben, dann Lesen wieder für die Validierung.Sie können sich wahrscheinlich machen, dass mit dem JDK-API für die Xml-Validierung, wenn Sie SAX-basierten Autor:wenn ja, link validator durch Aufruf von 'Validator.validate(source, result)', wo die Quelle kommt aus dem Autor, und das Ergebnis ist wo die Produktion gehen muss.

Alternativ, wenn Sie verwenden Stax für das schreiben von Inhalten (oder eine Bibliothek, die verwendet oder verwenden kann, stax), Woodstox kann auch direkt unterstützen Validierung bei der Verwendung XMLStreamWriter.Hier ist eine blog-Eintrag zeigt, wie das getan wird:

Wenn Sie die Generierung von XML-Dateien programmgesteuert, möchten Sie vielleicht zu schauen, die XMLBeans Bibliothek.Über ein Kommandozeilen-tool, XMLBeans wird automatisch generiert und Verpacken, die eine Reihe von Java-Objekten basierend auf einem XSD -.Dann können Sie verwenden diese Objekte zum erstellen einer XML-Dokument basierend auf diesem schema.

Es verfügt über eine integrierte Unterstützung für die schema-Validierung, kann und konvertieren von Java-Objekten als XML-Dokument und Umgekehrt.

Castor und JAXB andere Java-Bibliotheken dienen einem ähnlichen Zweck zu XMLBeans.

Sind Sie auf der Suche nach einem tool oder eine Bibliothek?

Soweit Bibliotheken geht, so ziemlich der de-facto-standard ist Xerces2 die beiden C++ und Java Versionen.

Sein fore Sie gewarnt, aber es ist ein schweres Gewicht Lösung.Aber dann wieder, validieren von XML gegen XSD-Dateien ist ein ziemlich schweres problem.

Als ein Instrument, um dies für Sie tun, XMLFox scheint eine anständige freeware-Lösung, aber nicht, dass Sie es nicht persönlich, ich kann nicht sicher sagen.

Mit JAXB, Sie könnten den folgenden code verwenden:

    @Test
public void testCheckXmlIsValidAgainstSchema() {
    logger.info("Validating an XML file against the latest schema...");

    MyValidationEventCollector vec = new MyValidationEventCollector();

    validateXmlAgainstSchema(vec, inputXmlFileName, inputXmlSchemaName, inputXmlRootClass);

    assertThat(vec.getValidationErrors().isEmpty(), is(expectedValidationResult));
}

private void validateXmlAgainstSchema(final MyValidationEventCollector vec, final String xmlFileName, final String xsdSchemaName, final Class<?> rootClass) {
    try (InputStream xmlFileIs = Thread.currentThread().getContextClassLoader().getResourceAsStream(xmlFileName);) {
        final JAXBContext jContext = JAXBContext.newInstance(rootClass);
        // Unmarshal the data from InputStream
        final Unmarshaller unmarshaller = jContext.createUnmarshaller();

        final SchemaFactory sf = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
        final InputStream schemaAsStream = Thread.currentThread().getContextClassLoader().getResourceAsStream(xsdSchemaName);
        unmarshaller.setSchema(sf.newSchema(new StreamSource(schemaAsStream)));

        unmarshaller.setEventHandler(vec);

        unmarshaller.unmarshal(new StreamSource(xmlFileIs), rootClass).getValue(); // The Document class is the root object in the XML file you want to validate

        for (String validationError : vec.getValidationErrors()) {
            logger.trace(validationError);
        }
    } catch (final Exception e) {
        logger.error("The validation of the XML file " + xmlFileName + " failed: ", e);
    }
}

class MyValidationEventCollector implements ValidationEventHandler {
    private final List<String> validationErrors;

    public MyValidationEventCollector() {
        validationErrors = new ArrayList<>();
    }

    public List<String> getValidationErrors() {
        return Collections.unmodifiableList(validationErrors);
    }

    @Override
    public boolean handleEvent(final ValidationEvent event) {
        String pattern = "line {0}, column {1}, error message {2}";
        String errorMessage = MessageFormat.format(pattern, event.getLocator().getLineNumber(), event.getLocator().getColumnNumber(),
                event.getMessage());
        if (event.getSeverity() == ValidationEvent.FATAL_ERROR) {
            validationErrors.add(errorMessage);
        }
        return true; // you collect the validation errors in a List and handle them later
    }
}

Validieren gegen online-schemas

Source xmlFile = new StreamSource(Thread.currentThread().getContextClassLoader().getResourceAsStream("your.xml"));
SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
Schema schema = factory.newSchema(Thread.currentThread().getContextClassLoader().getResource("your.xsd"));
Validator validator = schema.newValidator();
validator.validate(xmlFile);

Validieren gegen die lokalen schemas

Offline-XML-Validierung mit Java

Ich hatte zu validieren XML gegen XSD-nur ein mal, also habe ich versucht XMLFox.Ich fand es sehr verwirrend und seltsam.Die Hilfe-Anweisungen scheinen nicht zu passen die Oberfläche.

Ich landete mit LiquidXML Studio 2008 (v6), das war viel einfacher zu bedienen und mehr sofort vertraut ist (die Benutzeroberfläche ist sehr ähnlich zu Visual Basic 2008 Express, die ich Häufig verwende).Der Nachteil:die Validierung Funktionen nicht in der kostenlosen version, so hatte ich die Verwendung der 30-Tage-Testversion.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top