2009-07-07 15 views
32

私は異なるスキーマ(不自然な例について謝罪)の数に対してXMLファイルを検証しようとしています: 検証複数のスキーマ定義に対するXMLファイル

  • をb.xsd

    • a.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つすべてをインポートするために失敗しています( n) 'グループ'コンポーネント。

    私はこれが正常にPythonのを使用しますが、のJava 6.0のXerces 2.8.1との本当の問題を抱えて検証しました。誰でもここで何がうまくいかないのか、XML文書を検証するための簡単なアプローチを提案できますか?

    答えて

    17

    他の誰かが同じ問題を抱えている場合に備えて、単体テスト(リソースとして)から親スキーマ(および暗黙的な子スキーマ)をロードしてXML文字列を検証する必要がありました。私はXerces XMLSchemFactoryを使ってJava 6バリデーターと一緒にこれを行いました。

    インクルードを介して子スキーマを正しく読み込むために、カスタムリソースリゾルバを作成する必要がありました。

    xmlSchemaFactory.setResourceResolver(new ResourceResolver()); 
    

    し、それから、私の場合には(クラスパスを経由して、あなたのリソースを解決するためにそれを使用します。

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

    スキーマの工場でそれを指定するリゾルバを使用するには、次のコードはここで見つけることができますsrc/main/resources)を参照してください。すべてのコメントはこれを歓迎しています...

    +3

    カスタムリソースリゾルバがこれをどのように動作させるかについて、少し詳しく説明します。ありがとう。 – Casey

    +0

    次のようなものを追加する必要があることを付け加えることができます: ' '親XSDで' new StreamSource(this.getClass()。getResourceAsStream( "parent.xsd") ' –

    +1

    がロードされています)他のすべてのものをインポートした"人為的 "親スキーマを作成しましたか? – zedoo

    2

    Xercesのスキーマは、(a)非常にペダンティックであり、(b)見つけたものが嫌いなときは全く役に立たないエラーメッセージを出します。それはイライラする組み合わせです。

    Pythonのスキーマは、もっと寛大であり、スキーマ内の小さなエラーを過去に報告されないようにしていました。

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

    +0

    うん、これはあまりにも同じエラーが発生しているようです。私は、スキーマファイルのインポート宣言が問題を引き起こしているのかどうか疑問に思っています...それは2つのスキーマにターゲット名前空間がないことに役立ちません... gargh – Jon

    +0

    これを解決する方法の1つは、 ResourceResolevrを作成し、スキーマファクトリに設定してください。 – Jon

    +4

    インポートを混ぜて含めないでください。彼らは2つの異なることを意味し、混同すべきではありません。 a、b、cは異なる名前空間にありますか?もしそうなら、それらは輸入されるべきであり、輸入されるべきではない。同じ名前空間にある場合は、それらを含める必要があります。 – skaffman

    6

    http://www.kdgregory.com/index.php?page=xml.parsing セクション

    その文書に基づいて、私のソリューション '単一のドキュメントため複数のスキーマ':Xercesのドキュメントから

    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")); 
    
    +0

    私のために働いた。インクルードスキーマに異なるターゲットネームスペースがある場合にインポートを使用することを忘れないでください –

    3

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

    あなたの答えは複数のスキーマの検証を処理しますか?それを表現するためにループを追加する必要があります。 –

    +1

    ここでは、スキーマの順序が重要であると述べるほど価値があります。 AがBをインポートする場合は、スキーマの作成に使用する配列にBより前のAが必要です。 – Hedley

    +0

    この回答はシンプルなXSDであり、多くはない – Weslor

    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)パラメータ"のhttp:// your_url_schema_location"あなたXSDファイルの場所。

    2)xmlファイルを参照する文字列"/home/user/myfile.xml"

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

    0

    私は同じ問題に直面し、この解決策を見つけた調査後。わたしにはできる。セットアップ異なるXSDs

    Enum

    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."); 
    } 
    
    関連する問題