Відповіді:
Бібліотека виконання Java підтримує перевірку. Минулого разу я перевіряв, що це аналізатор Apache Xerces під обкладинками. Ймовірно, ви повинні використовувати javax.xml.validation.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) {}
http://www.w3.org/2001/XMLSchema
Фабрична константа схеми - це рядок, який визначає XSD. Вищенаведений код підтверджує дескриптор розгортання WAR щодо URL-адреси, http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd
але ви можете так само легко перевірити місцевий файл.
Не слід використовувати DOMParser для перевірки документа (якщо ваша мета все-таки не є створенням об'єктної моделі документа). Це почне створювати об'єкти DOM під час аналізу документа - марно, якщо ви не збираєтесь їх використовувати.
Ось як це зробити за допомогою Xerces2 . Навчальний посібник для цього, тут (реєстрація по запиту).
Оригінальна атрибуція: явно скопійована звідси :
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.");
}
}
}
Ми будуємо наш проект за допомогою мурашника, тому ми можемо використовувати завдання schemavalidate для перевірки наших конфігураційних файлів:
<schemavalidate>
<fileset dir="${configdir}" includes="**/*.xml" />
</schemavalidate>
Тепер неслухняні конфігураційні файли не зможуть побудувати!
Оскільки це популярне питання, я зазначу, що java також може перевірити "посилання на" xsd, наприклад, якщо файл .xml сам визначає XSD у заголовку, використовуючи xsi:SchemaLocation
або xsi:noNamespaceSchemaLocation
(або xsi для конкретних просторів імен), наприклад :
<document xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://www.example.com/document.xsd">
...
або SchemaLocation (завжди список простору імен для відображення xsd)
<document xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:SchemaLocation="http://www.example.com/my_namespace http://www.example.com/document.xsd">
...
Інші відповіді також працюють тут, тому що .xsd файли "відображають" на простори імен, оголошені у файлі .xml, оскільки вони оголошують простір імен, і якщо вони збігаються з простором імен у файлі .xml, ви добре. Але іноді зручно мати спеціальний резолютор ...
З javadocs: "Якщо ви створюєте схему, не вказуючи URL, файл чи джерело, мова Java створює таку, яка виглядає в документі, перевіреному, щоб знайти схему, яку він повинен використовувати. Наприклад:"
SchemaFactory factory = SchemaFactory.newInstance("http://www.w3.org/2001/XMLSchema");
Schema schema = factory.newSchema();
і це працює для декількох просторів імен і т. д. Проблема такого підходу полягає в тому, що xmlsns:xsi
це, ймовірно, мережеве розташування, тому воно за замовчуванням виходить і потрапляє в мережу з кожною валідацією, не завжди оптимальною.
Ось приклад, який перевіряє XML-файл щодо будь-яких посилань XSD на нього (навіть якщо він повинен витягувати їх з мережі):
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);
}
}
Ви можете уникнути витягування посилань на XSD з мережі, навіть незважаючи на те, що файли xml посилаються на URL-адреси, вказуючи xsd вручну (див. Тут інші відповіді) або використовуючи розв'язник стилю "Каталог XML" . Весна, очевидно, також може перехопити запити URL-адреси для обслуговування локальних файлів для перевірки. Або ви можете встановити свій власний за допомогою setResourceResolver , наприклад:
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);
Дивіться також тут ще один підручник.
Я вважаю , що за замовчуванням використовувати DOM синтаксичний, ви можете зробити що - щось подібне з SAX парсер , який перевіряє , а також saxReader.setEntityResolver(your_resolver_here);
setResourceResolver
але поза цим, можливо, відкрийте нове запитання ...
За допомогою Java 7 ви можете дотримуватися документації, наданої в описі пакета .
// 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
Приймає Source
, так що ви можете: validator.validate(new StreamSource(new File("instance.xml")))
.
ErrorHandler
якщо вам потрібно зробити перевірку.
Якщо у вас є Linux-машина, ви можете використовувати безкоштовний інструмент командного рядка SAXCount. Я вважав це дуже корисним.
SAXCount -f -s -n my.xml
Він підтверджує проти dtd та xsd. 5s для файлу 50MB.
У дебіанському стисканні він знаходиться в пакеті "libxerces-c-sample".
Визначення dtd та xsd має бути у xml! Ви не можете їх конфігурувати окремо.
xmllint --schema phone.xsd phone.xml
(з відповіді 13рен)
Ще одна відповідь: оскільки ви сказали, що вам потрібно перевірити файли, які ви створюєте (пишете), ви можете перевірити вміст під час написання, замість того, щоб спочатку писати, а потім читати назад для перевірки. Ви можете, ймовірно, зробити це за допомогою JDK API для перевірки Xml, якщо ви використовуєте письменник на основі SAX: якщо так, просто зв’яжіть у валідаторі, зателефонувавши "Validator.validate (джерело, результат)", де джерело надходить від вашого автора, а результат - куди потрібно йти вихід.
Якщо ви використовуєте Stax для написання вмісту (або бібліотеки, яка використовує або може використовувати stax), Woodstox також може безпосередньо підтримувати перевірку при використанні XMLStreamWriter. Ось запис у блозі, який показує, як це робиться:
Якщо ви генеруєте XML-файли програмно, можливо, захочете переглянути бібліотеку XMLBeans . Використовуючи інструмент командного рядка, XMLBeans автоматично генерує та пакує набір об’єктів Java на основі XSD. Потім ви можете використовувати ці об’єкти для створення XML-документа на основі цієї схеми.
Він має вбудовану підтримку перевірки схеми і може конвертувати об'єкти Java в XML-документ і навпаки.
Castor і JAXB - це інші бібліотеки Java, які служать аналогічним для XMLBeans.
З JAXB ви можете використовувати код нижче:
@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
}
}
Шукаєте інструмент чи бібліотеку?
Що стосується бібліотек, то майже де-факто стандартом є Xerces2, який має як версії C ++, так і Java .
Попереджуйте, що це важке рішення. Але знову ж таки, перевірка XML щодо XSD-файлів - досить важка проблема.
Що стосується інструменту зробити це для вас, XMLFox здається гідним безкоштовним рішенням, але не використовуючи його особисто, я не можу сказати точно.
Обгрунтовуйте схеми в Інтернеті
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);
Підтвердити місцеві схеми
За допомогою Woodstox налаштуйте аналізатор StAX для перевірки вашої схеми та розбору XML.
Якщо винятки вилучені, XML недійсний, інакше він дійсний:
// 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();
}
Примітка . Якщо вам потрібно перевірити декілька файлів, вам слід спробувати повторно використати свої файли XMLInputFactory
та XMLValidationSchema
з метою максимальної ефективності.
Мені довелося лише один раз перевірити XML проти XSD, тому я спробував XMLFox. Я вважав це дуже заплутаним і дивним. Інструкції довідки, схоже, не відповідають інтерфейсу.
У кінцевому підсумку я скористався LiquidXML Studio 2008 (v6), який був набагато простішим у використанні та більш відомим (інтерфейс користувача дуже схожий на Visual Basic 2008 Express, яким я користуюсь часто). Недолік: можливість перевірки відсутня у безкоштовній версії, тому мені довелося використовувати 30-денний пробний період.