Porównaj ceny domen i usług IT, sprzedawców z całego świata

Jaki jest najlepszy sposób sprawdzenia poprawności pliku XML względem pliku XSD?


Tworzę pliki xml, które muszą pasować do otrzymanego pliku xsd. Jaki jest najlepszy sposób sprawdzenia ich zgodności?
Zaproszony:
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

Biblioteka środowiska wykonawczego Java obsługuje sprawdzanie poprawności. Ostatnim razem, gdy sprawdzałem, był to parser Apache Xerces pod okładką. Powinieneś prawdopodobnie użyć

javax.xml.validation.Validator
http://java.sun.com/j2se/1.5.0 ... .html
.
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("[url=http://host:port/filename.xsd"]http://host:port/filename.xsd"[/url];);
// webapp example xsd:
// URL schemaFile = new URL("[url=http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"]http://java.sun.com/xml/ns/j2e ... 6quot[/url];);
// 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) {}

Stała fabryczna schematu to
[url=http://www.w3.org/2001/XMLSchema]http://www.w3.org/2001/XMLSchema[/url]
, która definiuje pliki XSD. Powyższy kod porównuje deskryptor wdrażania WAR z adresem URL
[url=http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd]http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd[/url]
, ale równie łatwo można to porównać z plik lokalny.
Nie powinieneś używać DOMParser do walidacji dokumentu (chyba że Twoim celem jest i tak utworzenie modelu obiektowego dokumentu). Spowoduje to utworzenie obiektów DOM podczas przetwarzania dokumentu - marnotrawstwo, jeśli nie zamierzasz ich używać.
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

Oto jak to zrobić

Xerces2
http://xerces.apache.org/xerces2-j/... Poradnik do tego

tutaj
http://www.ibm.com/developerwo ... .html
(req. signup).
Oryginalne źródło: bezczelnie skopiowane stąd:
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("[url=http://xml.org/sax/features/validation"]http://xml.org/sax/features/validation"[/url], true);
parser.setProperty( "[url=http://apache.org/xml/properties/schema/external-noNamespaceSchemaLocation"]http://apache.org/xml/properti ... ot%3B[/url],
"memory.xsd");
ErrorChecker errors = new ErrorChecker();
parser.setErrorHandler(errors);
parser.parse("memory.xml");
} catch (Exception e) {
System.out.print("Problem parsing the file.");
}
}
}
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

Budujemy nasz projekt przy użyciu ant, więc możemy użyć zadania schemavalidate do sprawdzenia poprawności naszych plików konfiguracyjnych:
<schemavalidate> 
<fileset dir="${configdir}" includes="**/*.xml"/>
</schemavalidate>

Teraz niegrzeczne pliki konfiguracyjne nie będą w stanie ukończyć naszej kompilacji!
http://ant.apache.org/manual/T ... .html
http://ant.apache.org/manual/T ... .html
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

Ponieważ jest to popularne pytanie, zauważam, że java może również sprawdzić w odniesieniu do xsd, na przykład, jeśli sam plik .xml określa XSD w nagłówku za pomocą
xsi: SchemaLocation
lub
xsi: noNamespaceSchemaLocation
(lub xsi dla określonych przestrzeni nazw)

.
http://www.ibm.com/developerwo ... .html
:
<document xmlns:xsi="[url=http://www.w3.org/2001/XMLSchema-instance"]http://www.w3.org/2001/XMLSchema-instance"[/url]
xsi:noNamespaceSchemaLocation="[url=http://www.example.com/document.xsd">]http://www.example.com/document.xsd">[/url]
...

lub SchemaLocation (zawsze lista mapowań przestrzeni nazw w xsd)
<document xmlns:xsi="[url=http://www.w3.org/2001/XMLSchema-instance"]http://www.w3.org/2001/XMLSchema-instance"[/url]
xsi:SchemaLocation="[url=http://www.example.com/my_namespace]http://www.example.com/my_namespace[/url] [url=http://www.example.com/document.xsd">]http://www.example.com/document.xsd">[/url]
...

Inne odpowiedzi również działają tutaj, ponieważ pliki .xsd „odwzorowują” przestrzenie nazw zadeklarowane w pliku .xml, ponieważ deklarują przestrzeń nazw, a jeśli pasuje ona do przestrzeni nazw w pliku .xml, to dobrze. Ale czasami wygodnie jest mieć własny

solver
https://stackoverflow.com/a/2342859/32453
...
Z javadocs: „jeśli utworzysz schemat bez określania adresu URL, pliku lub źródła, język Java utworzy ten, który przeszukuje sprawdzany dokument w celu znalezienia schematu, którego powinien użyć. Na przykład:”
SchemaFactory factory = SchemaFactory.newInstance("[url=http://www.w3.org/2001/XMLSchema"]http://www.w3.org/2001/XMLSchema"[/url];);
Schema schema = factory.newSchema();

i to działa dla wielu przestrzeni nazw itp.
Problem z tym podejściem polega na tym, że
xmlsns: xsi
jest prawdopodobnie lokalizacją sieciową, więc domyślnie wychodzi i przechodzi do trybu online przy każdym sprawdzeniu, nie zawsze jest to optymalne.
Oto przykład, który sprawdza plik XML pod kątem jakichkolwiek odniesień do XSD (nawet jeśli musi wyciągnąć je z sieci):
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("[url=http://java.sun.com/xml/jaxp/properties/schemaLanguage"]http://java.sun.com/xml/jaxp/p ... ot%3B[/url],
"[url=http://www.w3.org/2001/XMLSchema"]http://www.w3.org/2001/XMLSchema"[/url];);
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);
}
}

Możesz uniknąć pobierania plików XSD, do których istnieją odwołania, z sieci WWW, nawet jeśli do plików xml znajdują się odwołania do adresów URL, określając xsd ręcznie (zobacz inne odpowiedzi tutaj) lub używając

rozpoznawanie stylu
https://coderoad.ru/25698764/
„Katalog XML”. Podobno wiosna też

może przechwycić
https://stackoverflow.com/a/10768972/32453
prośby o url dotyczące serwowania plików lokalnych do sprawdzenia. Lub możesz zainstalować własne za pośrednictwem

setResourceResolver
https://docs.oracle.com/javase ... olver(org.w3c.dom.ls.LSResourceResolver)
, 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
// [url=https://stackoverflow.com/a/2342859/32453]https://stackoverflow.com/a/2342859/32453[/url]
}
});
validator.validate(xmlFile);

Zobacz też

tutaj
https://docs.oracle.com/javase ... .html
kolejny samouczek.
Uważam, że domyślnym jest parsowanie DOM, możesz zrobić coś takiego z parserem SAX, który

również
https://blog.frankel.ch/use-lo ... -xml/
sprawdza
saxReader.setEntityResolver (your_resolver_here);
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

Używając Java 7 możesz postępować zgodnie z dokumentacją podaną w

opis pakietu
http://docs.oracle.com/javase/ ... .html
.

// 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!
}
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

Inna odpowiedź: skoro powiedziałeś, że musisz sprawdzić pliki

Stwórz

(napisz), możesz sprawdzić zawartość podczas pisania, zamiast najpierw pisać, a potem czytać, aby sprawdzić. Prawdopodobnie możesz to zrobić za pomocą JDK API, aby zweryfikować XML, jeśli używasz programu zapisującego opartego na SAX: jeśli tak, po prostu połącz walidator z wywołaniem `` Validator.validate (źródło, wynik) '', gdzie źródło pochodzi z twojego writer., a wynik jest tam, gdzie dane wyjściowe powinny być.
Ponadto, jeśli używasz Stax do pisania treści (lub biblioteki, która używa lub może używać stax), Woodstox

również
https://github.com/FasterXML/woodstox
może bezpośrednio obsługiwać walidację podczas korzystania z XMLStreamWriter. Tutaj

post na blogu
http://www.cowtowncoder.com/bl ... .html
pokazując, jak to się robi:
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

Jeśli masz komputer z systemem Linux, możesz skorzystać z bezpłatnego narzędzia wiersza poleceń SAXCount. Uznałem to za bardzo pomocne.
SAXCount -f -s -n my.xml

Sprawdza przed dtd i xsd.
5s dla pliku o wielkości 50 MB.
W debian squeeze znajduje się w pakiecie „libxerces-c-samples”.
Definicja dtd i xsd musi być w formacie xml! Nie można ich dostosowywać oddzielnie.
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

Jeśli tworzysz pliki XML programowo, możesz zajrzeć do biblioteki

XMLBeans
http://xmlbeans.apache.org/... Korzystając z narzędzia wiersza poleceń, XMLBeans automatycznie utworzy i zapakuje zestaw obiektów Java opartych na XSD. Obiekty te można następnie wykorzystać do zbudowania dokumentu XML na podstawie tego schematu.
Posiada wbudowaną obsługę walidacji schematów i może konwertować obiekty Java na dokument XML i odwrotnie.
Castor
http://www.castor.org/
i

JAXB
http://java.sun.com/developer/ ... jaxb/
to inne biblioteki Java, które służą temu samemu celowi co XMLBeans.
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

Z JAXB możesz użyć następującego kodu:
@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
}
}
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

Szukasz narzędzia lub biblioteki?
Jeśli chodzi o biblioteki, Xerces2 jest de facto standardem.

,
http://xerces.apache.org
który ma obie wersje

C++
http://xerces.apache.org/xerces-c/
i

Java
http://xerces.apache.org/xerces2-j/
.
Pamiętaj jednak, że jest to kłopotliwa decyzja. Ale znowu, walidacja XML względem plików XSD jest dość trudnym problemem.
Jeśli chodzi o narzędzie, które zrobi to za Ciebie,

XMLFox
http://www.xmlfox.com/xml_editor.htm
wydaje się przyzwoitym darmowym rozwiązaniem, ale bez korzystania z niego osobiście nie mogę powiedzieć na pewno.
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:


Sprawdzanie według schematów sieciowych

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


Sprawdzenie schematu lokalnego

Walidacja XML w trybie offline za pomocą Java Baeldung
https://stackoverflow.com/a/48447453/1485527
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

Za pomocą

Woodstox
https://github.com/FasterXML/woodstox, skonfiguruj parser StAX, aby sprawdzał poprawność schematu i analizował XML.
Jeśli wyjątki zostaną przechwycone, XML nie jest prawidłowy, w przeciwnym razie jest prawidłowy:
// 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();
}


Uwaga
: Jeśli chcesz zweryfikować wiele plików, powinieneś spróbować ponownie użyć
XMLInputFactory
i
XMLValidationSchema
, aby zmaksymalizować wydajność.
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

Musiałem tylko raz zweryfikować XML pod kątem XSD, więc wypróbowałem XMLFox. Wydało mi się to bardzo zagmatwane i dziwne. Wydaje się, że instrukcje referencyjne nie pasują do interfejsu.
Skończyło się na tym, że korzystałem z LiquidXML Studio 2008 (v6), które było dużo łatwiejsze w użyciu i od razu znajome (interfejs użytkownika jest bardzo podobny do Visual Basic 2008 Express, z którego często korzystam). Wada: w darmowej wersji nie ma opcji walidacji, więc musiałem skorzystać z 30-dniowej wersji próbnej.

Aby odpowiedzieć na pytania, Zaloguj się lub Zarejestruj się