Pertanyaan Validasi File XML Melawan Beberapa Definisi Skema


Saya mencoba memvalidasi file XML terhadap sejumlah skema yang berbeda (permintaan maaf untuk contoh yang dibuat):

  • a.xsd
  • b.xsd
  • c.xsd

c.xsd khususnya impor b.xsd dan b.xsd mengimpor a.xsd, menggunakan:

<xs:include schemaLocation="b.xsd"/>

Saya mencoba melakukan ini melalui Xerces dengan cara berikut:

XMLSchemaFactory xmlSchemaFactory = new XMLSchemaFactory();
Schema schema = xmlSchemaFactory.newSchema(new StreamSource[] { new StreamSource(this.getClass().getResourceAsStream("a.xsd"), "a.xsd"),
                                                         new StreamSource(this.getClass().getResourceAsStream("b.xsd"), "b.xsd"),
                                                         new StreamSource(this.getClass().getResourceAsStream("c.xsd"), "c.xsd")});     
Validator validator = schema.newValidator();
validator.validate(new StreamSource(new StringReader(xmlContent)));

tetapi ini gagal untuk mengimpor ketiga skema dengan benar sehingga tidak dapat menyelesaikan nama 'bla' ke komponen (n) 'grup'.

Saya telah memvalidasi ini berhasil menggunakan Python, tetapi memiliki masalah nyata dengan Java 6.0 dan Xerces 2.8.1. Adakah yang bisa menyarankan apa yang salah di sini, atau pendekatan yang lebih mudah untuk memvalidasi dokumen XML saya?


32
2017-07-07 21:09


asal


Jawaban:


Jadi kalau-kalau ada orang lain yang mengalami masalah yang sama di sini, saya perlu memuat skema induk (dan skema anak implisit) dari tes unit - sebagai sumber daya - untuk memvalidasi String XML. Saya menggunakan Xerces XMLSchemFactory untuk melakukan ini bersama dengan validator Java 6.

Untuk memuat skema anak dengan benar melalui penyertaan, saya harus menulis penyelesai sumber khusus. Kode dapat ditemukan di sini:

https://code.google.com/p/xmlsanity/source/browse/src/com/arc90/xmlsanity/validation/ResourceResolver.java

Untuk menggunakan resolver, tentukan di pabrik skema:

xmlSchemaFactory.setResourceResolver(new ResourceResolver());

dan itu akan menggunakannya untuk menyelesaikan sumber daya Anda melalui classpath (dalam kasus saya dari src / main / resources). Ada komentar yang diterima tentang ini ...


17
2017-07-09 19:03



http://www.kdgregory.com/index.php?page=xml.parsing  bagian 'Beberapa skema untuk satu dokumen'

Solusi saya berdasarkan dokumen itu: 

URL xsdUrlA = this.getClass().getResource("a.xsd");
URL xsdUrlB = this.getClass().getResource("b.xsd");
URL xsdUrlC = this.getClass().getResource("c.xsd");

SchemaFactory schemaFactory = schemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
//---
String W3C_XSD_TOP_ELEMENT =
"<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n"
   + "<xs:schema xmlns:xs=\"http://www.w3.org/2001/XMLSchema\" elementFormDefault=\"qualified\">\n"
   + "<xs:include schemaLocation=\"" +xsdUrlA.getPath() +"\"/>\n"
   + "<xs:include schemaLocation=\"" +xsdUrlB.getPath() +"\"/>\n"
   + "<xs:include schemaLocation=\"" +xsdUrlC.getPath() +"\"/>\n"
   +"</xs:schema>";
Schema schema = schemaFactory.newSchema(new StreamSource(new StringReader(W3C_XSD_TOP_ELEMENT), "xsdTop"));

6
2017-09-20 11:35



Dari dokumentasi xerces: http://xerces.apache.org/xerces2-j/faq-xs.html

import javax.xml.transform.Source;
import javax.xml.transform.stream.StreamSource;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;
import javax.xml.validation.Validator;

...

StreamSource[] schemaDocuments = /* created by your application */;
Source instanceDocument = /* created by your application */;

SchemaFactory sf = SchemaFactory.newInstance(
    "http://www.w3.org/XML/XMLSchema/v1.1");
Schema s = sf.newSchema(schemaDocuments);
Validator v = s.newValidator();
v.validate(instanceDocument);

3
2018-03-28 08:31



Hal-hal skema di Xerces adalah (a) sangat, sangat bertele-tele, dan (b) memberikan pesan kesalahan sama sekali tidak berguna ketika tidak suka apa yang ditemukannya. Ini kombinasi yang membuat frustrasi.

Hal-hal skema di python mungkin jauh lebih memaafkan, dan membiarkan kesalahan kecil dalam skema melewati tidak dilaporkan.

Sekarang jika, seperti yang Anda katakan, c.xsd termasuk b.xsd, dan b.xsd menyertakan a.xsd, maka tidak perlu memuat ketiganya ke dalam pabrik skema. Tidak hanya itu tidak perlu, itu mungkin akan membingungkan Xerces dan menghasilkan kesalahan, jadi ini mungkin masalah Anda. Hanya meneruskan c.xsd ke pabrik, dan biarkan menyelesaikan b.xsd dan a.xsd itu sendiri, yang harus dilakukan relatif terhadap c.xsd.


2
2017-07-07 21:27



Saya akhirnya menggunakan ini:

import org.apache.xerces.parsers.SAXParser;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
import org.xml.sax.helpers.DefaultHandler;
import java.io.IOException;
 .
 .
 .
 try {
        SAXParser parser = new SAXParser();
        parser.setFeature("http://xml.org/sax/features/validation", true);
        parser.setFeature("http://apache.org/xml/features/validation/schema", true);
        parser.setFeature("http://apache.org/xml/features/validation/schema-full-checking", true);
        parser.setProperty("http://apache.org/xml/properties/schema/external-noNamespaceSchemaLocation", "http://your_url_schema_location");

        Validator handler = new Validator();
        parser.setErrorHandler(handler);
        parser.parse("file:///" + "/home/user/myfile.xml");

 } catch (SAXException e) {
    e.printStackTrace();
 } catch (IOException ex) {
    e.printStackTrace();
 }


class Validator extends DefaultHandler {
    public boolean validationError = false;
    public SAXParseException saxParseException = null;

    public void error(SAXParseException exception)
            throws SAXException {
        validationError = true;
        saxParseException = exception;
    }

    public void fatalError(SAXParseException exception)
            throws SAXException {
        validationError = true;
        saxParseException = exception;
    }

    public void warning(SAXParseException exception)
            throws SAXException {
    }
}

Ingat untuk berubah:

1) Parameter "http: // your_url_schema_location" untuk Anda lokasi file xsd.

2) String "/home/user/myfile.xml" untuk orang yang menunjuk ke file xml Anda.

Saya tidak perlu mengatur variabel: -Djavax.xml.validation.SchemaFactory:http://www.w3.org/2001/XMLSchema=org.apache.xerces.jaxp.validation.XMLSchemaFactory 


1
2017-09-21 13:41



Saya menghadapi masalah yang sama dan setelah menyelidiki menemukan solusi ini. Ini bekerja untukku.

Enum untuk mengatur yang berbeda XSDs:

public enum XsdFile {
    // @formatter:off
    A("a.xsd"),
    B("b.xsd"),
    C("c.xsd");
    // @formatter:on

    private final String value;

    private XsdFile(String value) {
        this.value = value;
    }

    public String getValue() {
        return this.value;
    }
}

Metode untuk memvalidasi:

public static void validateXmlAgainstManyXsds() {
    final SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);

    String xmlFile;
    xmlFile = "example.xml";

    // Use of Enum class in order to get the different XSDs
    Source[] sources = new Source[XsdFile.class.getEnumConstants().length];
    for (XsdFile xsdFile : XsdFile.class.getEnumConstants()) {
        sources[xsdFile.ordinal()] = new StreamSource(xsdFile.getValue());
    }

    try {
        final Schema schema = schemaFactory.newSchema(sources);
        final Validator validator = schema.newValidator();
        System.out.println("Validating " + xmlFile + " against XSDs " + Arrays.toString(sources));
        validator.validate(new StreamSource(new File(xmlFile)));
    } catch (Exception exception) {
        System.out.println("ERROR: Unable to validate " + xmlFile + " against XSDs " + Arrays.toString(sources)
                + " - " + exception);
    }
    System.out.println("Validation process completed.");
}

0
2017-11-02 12:19