Yanıtlar:
Java çalışma zamanı kitaplığı doğrulamayı destekler. Son kontrol ettiğimde kapakların altında Apache Xerces ayrıştırıcısı vardı. Muhtemelen bir javax.xml.validation.Validator kullanmalısınız .
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) {}
Şema fabrika sabiti, http://www.w3.org/2001/XMLSchema
XSD'leri tanımlayan dizedir . Yukarıdaki kod, bir WAR dağıtım tanımlayıcısını URL'ye göre http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd
doğrular, ancak yerel bir dosyaya karşı kolayca doğrulama yapabilirsiniz.
DOMParser'ı bir belgeyi doğrulamak için kullanmamalısınız (hedefiniz zaten bir belge nesnesi modeli oluşturmak değilse). Bu, belgeyi ayrıştırdığı için DOM nesneleri oluşturmaya başlayacaktır - bunları kullanmayacaksanız savurgan olur.
Xerces2'yi kullanarak bunu nasıl yapacağınız aşağıda açıklanmıştır . Bunun için bir öğretici, burada (gerekli kayıt).
Orijinal atıf: buradan açıkça kopyalandı :
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.");
}
}
}
Projemizi karınca kullanarak oluşturuyoruz, böylece yapılandırma dosyalarımızı kontrol etmek için schemavalidate görevini kullanabiliriz:
<schemavalidate>
<fileset dir="${configdir}" includes="**/*.xml" />
</schemavalidate>
Şimdi yaramaz yapılandırma dosyaları bizim yapı başarısız olacak!
Bu popüler bir sorudur bu yana .xml dosyası kendisi XSD en kullanarak, başlıkta belirtirse, ben de validate karşı örneğin Xsd yönettiği "atıfta" anlamına java işaret eder xsi:SchemaLocation
ya da xsi:noNamespaceSchemaLocation
(ya da belirli ad alanları için xsi) ex :
<document xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://www.example.com/document.xsd">
...
veya SchemaLocation (her zaman xsd eşlemeleri için bir ad alanı listesi)
<document xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:SchemaLocation="http://www.example.com/my_namespace http://www.example.com/document.xsd">
...
Diğer yanıtlar da burada çalışır, çünkü .xsd dosyaları .xml dosyasında bildirilen ad alanlarıyla "eşleşir", çünkü bir ad alanı bildirir ve .xml dosyasındaki ad alanıyla eşleşirse, iyidir. Ancak bazen özel bir çözümleyiciye sahip olmak uygun olur ...
Javadocs'tan: "Bir URL, dosya veya kaynak belirtmeden bir şema oluşturursanız, Java dili, kullanması gereken şemayı bulmak için onaylanan belgede görünen bir şema oluşturur. Örneğin:"
SchemaFactory factory = SchemaFactory.newInstance("http://www.w3.org/2001/XMLSchema");
Schema schema = factory.newSchema();
ve bu, birden çok ad alanı, vb. için çalışır. Bu yaklaşımla ilgili sorun xmlsns:xsi
, muhtemelen bir ağ konumu olmasıdır, bu nedenle varsayılan olarak dışarı çıkıp her zaman her doğrulamayla ağa çarpar, her zaman en uygun değildir.
XML dosyasını başvurduğu herhangi bir XSD'ye göre doğrulayan bir örnek (ağdan çekmek zorunda olsa bile):
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);
}
}
Xml dosyaları url'lere başvursa da, xsd'yi manuel olarak belirterek (burada diğer yanıtlara bakın) veya "XML kataloğu" stil çözümleyici kullanarak başvurulan XSD'leri ağdan çekmekten kaçınabilirsiniz . Spring, görünüşe göre doğrulama için yerel dosyalara sunmak için URL isteklerini de engelleyebilir . Veya setResourceResolver aracılığıyla kendiniz ayarlayabilirsiniz , örn:
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);
Başka bir eğitim için buraya da bakınız .
Ben, sen doğruluyor SAX ayrıştırıcı ile benzer bir şey yapabilirsiniz varsayılan DOM ayrıştırmayı kullanmaktır inanıyoruz yanı saxReader.setEntityResolver(your_resolver_here);
setResourceResolver
ancak bunun ötesinde, belki de yeni bir soru açın ...
Java 7'yi kullanarak paket açıklamasında sağlanan belgeleri takip edebilirsiniz .
// 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 StreamSource(new File("instance.xml")); } catch (SAXException e) { // instance document is invalid! }
parser.parse(new File("instance.xml"))
. validator
Bir kabul Source
, böylece şunları yapabilirsiniz: validator.validate(new StreamSource(new File("instance.xml")))
.
ErrorHandler
doğrulama yapmanız gerekiyorsa bir sağlamak gerekir.
Bir Linux Makineniz varsa, ücretsiz komut satırı aracı SAXCount'u kullanabilirsiniz. Bunu çok faydalı buldum.
SAXCount -f -s -n my.xml
Dtd ve xsd'ye göre geçer. 50MB dosya için 5s.
Debian squeeze "libxerces-c-samples" paketinde bulunur.
Dtd ve xsd tanımı xml olmalıdır! Bunları ayrı ayrı yapılandıramazsınız.
xmllint --schema phone.xsd phone.xml
(13ren cevap)
Bir daha cevap: Eğer validate Sizin dosyaları ihtiyacım olduğunu söyledi beri üreten (yazma), sonra yerine ilk yazı yazma doğrulama için geri okurken, sen doğrulamak içeriği isteyebilirsiniz. Bunu muhtemelen Xml doğrulaması için JDK API ile yapabilirsiniz, eğer SAX tabanlı bir yazar kullanıyorsanız: eğer öyleyse, kaynaktan yazarınızdan gelen ve sonuçların olduğu 'Validator.validate (kaynak, sonuç)' öğesini çağırarak doğrulayıcıya bağlanmanız yeterlidir. çıktının gitmesi gereken yer.
Alternatif olarak, içerik yazmak için Stax kullanıyorsanız (veya stax kullanan veya kullanabilen bir kütüphane), Woodstox XMLStreamWriter kullanırken doğrulamayı doğrudan destekleyebilir. İşte bunun nasıl yapıldığını gösteren bir blog girişi :
XML dosyalarını programlı olarak oluşturuyorsanız, XMLBeans kütüphanesine bakmak isteyebilirsiniz . Bir komut satırı aracı kullanarak, XMLBeans otomatik olarak bir XSD tabanlı bir dizi Java nesnesi oluşturur ve paketler. Daha sonra bu nesneleri, bu şemaya dayalı bir XML belgesi oluşturmak için kullanabilirsiniz.
Şema doğrulaması için yerleşik bir desteğe sahiptir ve Java nesnelerini bir XML belgesine veya tersine dönüştürebilir.
Castor ve JAXB , XMLBeans'e benzer bir amaca hizmet eden diğer Java kütüphaneleridir.
JAXB ile aşağıdaki kodu kullanabilirsiniz:
@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
}
}
Bir araç veya kütüphane mi arıyorsunuz?
Bildiğim kadarıyla kütüphaneler giderse, hemen hemen de-facto standart Xerces2 hem sahiptir C ++ ve Java sürümleri.
Dikkat edin, ağır bir çözümdür. Fakat yine de, XML'i XSD dosyalarına karşı doğrulamak oldukça ağır bir sorundur.
Bunu sizin için yapacak bir araca gelince, XMLFox iyi bir ücretsiz çözüm gibi görünüyor, ancak kişisel olarak kullanmadım emin diyemem.
Çevrimiçi şemalara karşı doğrulama
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);
Yerel şemalara karşı doğrulama
Woodstox kullanarak , StAX ayrıştırıcısını şemanıza göre doğrulayacak ve XML'yi ayrıştıracak şekilde yapılandırın.
İstisnalar yakalanırsa XML geçerli değildir, aksi takdirde geçerlidir:
// create the XSD schema from your schema file
XMLValidationSchemaFactory schemaFactory = XMLValidationSchemaFactory.newInstance(XMLValidationSchema.SCHEMA_ID_W3C_SCHEMA);
XMLValidationSchema validationSchema = schemaFactory.createSchema(schemaInputStream);
// create the XML reader for your XML file
WstxInputFactory inputFactory = new WstxInputFactory();
XMLStreamReader2 xmlReader = (XMLStreamReader2) inputFactory.createXMLStreamReader(xmlInputStream);
try {
// configure the reader to validate against the schema
xmlReader.validateAgainst(validationSchema);
// parse the XML
while (xmlReader.hasNext()) {
xmlReader.next();
}
// no exceptions, the XML is valid
} catch (XMLStreamException e) {
// exceptions, the XML is not valid
} finally {
xmlReader.close();
}
Not : Birden fazla dosyayı doğrulamanız gerekiyorsa , performansınızı en üst düzeye çıkarmak için XMLInputFactory
ve dosyalarınızı yeniden kullanmaya çalışmalısınız XMLValidationSchema
.
Ben sadece bir kez XSD bir XML doğrulamak zorunda kaldı, bu yüzden XMLFox denedim. Çok kafa karıştırıcı ve garip buldum. Yardım talimatları arayüzle eşleşmiyor gibi görünüyor.
Kullanımı çok daha kolay ve hemen tanıdık olan LiquidXML Studio 2008'i (v6) kullandım (kullanıcı arayüzü sık kullandığım Visual Basic 2008 Express'e çok benziyor). Dezavantajı: doğrulama yeteneği ücretsiz sürümünde değil, bu yüzden 30 günlük deneme kullanmak zorunda kaldı.