37

いくつかの異なるスキーマに対してXMLファイルを検証しようとしています(不自然な例についてはお詫びします)。

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

特にc.xsdはb.xsdをインポートし、b.xsdはa.xsdをインポートします。

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

私は次の方法でXercesを介してこれを行おうとしています:

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

しかし、これは3つのスキーマすべてを正しくインポートできず、名前'blah'をa(n)'group'コンポーネントに解決できません。

Pythonを使用してこれを正常に検証しましたが、Java6.0とXerces2.8.1で実際の問題が発生しています。ここで何が問題になっているのか、またはXMLドキュメントを検証するためのより簡単なアプローチを誰かが提案できますか?

4

8 に答える 8

18

したがって、他の誰かがここで同じ問題に遭遇した場合に備えて、XML文字列を検証するために単体テストから親スキーマ(および暗黙の子スキーマ)をリソースとしてロードする必要がありました。Xerces XMLSchemFactoryを使用して、Java6バリデーターとともにこれを実行しました。

インクルードを介して子スキーマを正しくロードするには、カスタムリソースリゾルバーを作成する必要がありました。コードはここにあります:

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

リゾルバーを使用するには、スキーマファクトリでリゾルバーを指定します。

xmlSchemaFactory.setResourceResolver(new ResourceResolver());

そしてそれを使用して、クラスパス(私の場合はsrc / main / resourcesから)を介してリソースを解決します。これについてのコメントは大歓迎です...

于 2009-07-09T19:03:52.410 に答える
7

http://www.kdgregory.com/index.php?page=xml.parsingsection '単一のドキュメントの複数のスキーマ'

そのドキュメントに基づく私の解決策:

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"));
于 2010-09-20T11:35:40.383 に答える
2

Xercesのスキーマは、(a)非常に衒学的であり、(b)検出されたものが気に入らない場合は、まったく役に立たないエラーメッセージを表示します。それは苛立たしい組み合わせです。

Pythonのスキーマはもっと寛容で、スキーマの小さなエラーが報告されないままになるのを許していたのかもしれません。

あなたが言うように、c.xsdにb.xsdが含まれ、b.xsdにa.xsdが含まれている場合、3つすべてをスキーマファクトリにロードする必要はありません。不要なだけでなく、Xercesを混乱させてエラーを発生させる可能性があるため、これが問題になる可能性があります。c.xsdをファクトリに渡して、b.xsdとa.xsd自体を解決させます。これは、c.xsdに対して実行する必要があります。

于 2009-07-07T21:27:41.670 に答える
2

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);
于 2012-03-28T08:31:06.137 に答える
2

私は同じ問題に直面し、調査した後、この解決策を見つけました。わたしにはできる。

Enum別のセットアップするには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;
    }
}

検証する方法:

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.");
}
于 2015-11-02T12:19:27.433 に答える
1

私はこれを使用することになりました:

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 {
    }
}

変更することを忘れないでください:

1)xsdファイルの場所のパラメーター「http://your_url_schema_location」 。

2)xmlファイルを指す文字列「/home/user/myfile.xml」 。

変数を設定する必要はありませんでした:-Djavax.xml.validation.SchemaFactory:http://www.w3.org/2001/XMLSchema=org.apache.xerces.jaxp.validation.XMLSchemaFactory

于 2012-09-21T13:41:15.410 に答える
1

念のため、複数のXSDに対してxmlまたはオブジェクトを検証するための解決策を見つけるためにまだ誰かがここに来ています、私はここでそれについて言及しています

//Using **URL** is the most important here. With URL, the relative paths are resolved for include, import inside the xsd file. Just get the parent level xsd here (not all included xsds).

URL xsdUrl = getClass().getClassLoader().getResource("my/parent/schema.xsd");

SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
Schema schema = schemaFactory.newSchema(xsdUrl);

JAXBContext jaxbContext = JAXBContext.newInstance(MyClass.class);
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
unmarshaller.setSchema(schema);

/* If you need to validate object against xsd, uncomment this
ObjectFactory objectFactory = new ObjectFactory();
JAXBElement<MyClass> wrappedObject = objectFactory.createMyClassObject(myClassObject); 
marshaller.marshal(wrappedShipmentMessage, new DefaultHandler());
*/

unmarshaller.unmarshal(getClass().getClassLoader().getResource("your/xml/file.xml"));
于 2020-01-09T14:35:52.420 に答える
0

すべてのXSDが同じ名前空間に属している場合は、新しいXSDを作成し、他のXSDをインポートします。次に、Javaで新しいXSDを使用してスキーマを作成します。

Schema schema = xmlSchemaFactory.newSchema(
    new StreamSource(this.getClass().getResourceAsStream("/path/to/all_in_one.xsd"));

all_in_one.xsd:

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
 xmlns:ex="http://example.org/schema/" 
 targetNamespace="http://example.org/schema/" 
 elementFormDefault="unqualified"
 attributeFormDefault="unqualified">

    <xs:include schemaLocation="relative/path/to/a.xsd"></xs:include>
    <xs:include schemaLocation="relative/path/to/b.xsd"></xs:include>
    <xs:include schemaLocation="relative/path/to/c.xsd"></xs:include>

</xs:schema>
于 2020-06-14T15:27:06.133 に答える