2

xsd ファイルと xml ファイルがあり、次のコードを使用して xsd ファイルに対して xml ファイルを検証しています。

DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        factory.setValidating(true);
        factory.setAttribute(
                "http://java.sun.com/xml/jaxp/properties/schemaLanguage",
                "http://www.w3.org/2001/XMLSchema");
        factory.setAttribute(
                "http://java.sun.com/xml/jaxp/properties/schemaSource",
                new InputSource(new StringReader(xsd)));
        Document doc = null;
        try {
            DocumentBuilder parser = factory.newDocumentBuilder();
            MyErrorHandler errorHandler = new MyErrorHandler();
            parser.setErrorHandler(errorHandler);
            doc = parser.parse(new InputSource(new StringReader(xml))); 
            return true;
        } catch (ParserConfigurationException e) {
            System.out.println("Parser not configured: " + e.getMessage());
        } catch (SAXException e) {
            System.out.print("Parsing XML failed due to a "
                    + e.getClass().getName() + ":");
            System.out.println(e.getMessage());
        } catch (IOException e) {
            System.out.println("IOException thrown");
            e.printStackTrace();
        }
        return false;

MyErrorHander は

private static class MyErrorHandler implements ErrorHandler {
        public void warning(SAXParseException spe) throws SAXException {
            System.out.println("Warning: " + spe.getMessage() + " getColumnNumber is " + spe.getColumnNumber() + " getLineNumber " + spe.getLineNumber() + " getPublicId " + spe.getPublicId() + " getSystemId " + spe.getSystemId());
        }

        public void error(SAXParseException spe) throws SAXException {
            System.out.println("Error: " + spe.getMessage() + " getColumnNumber is " + spe.getColumnNumber() + " getLineNumber " + spe.getLineNumber() + " getPublicId " + spe.getPublicId() + " getSystemId " + spe.getSystemId());
            throw new SAXException("Error: " + spe.getMessage());
        }

        public void fatalError(SAXParseException spe) throws SAXException {
            System.out.println("Fatal Error:  " + spe.getMessage() + " getColumnNumber is " + spe.getColumnNumber() + " getLineNumber " + spe.getLineNumber() + " getPublicId " + spe.getPublicId() + " getSystemId " + spe.getSystemId());
            throw new SAXException("Fatal Error: " + spe.getMessage());
        }
    }

XMLがxsdに準拠していない場合、例外が発生します..しかし、この例外には、このエラーが発生したxsd要素の名前がありません..メッセージは次のようになります

org.xml.sax.SAXException:Error: cvc-minLength-valid: Value '' with length = '0' is not facet-valid for minLength '1' for type 'null'. が原因で、XML の解析に失敗しました。

xsd 要素の名前を出力する代わりに、エラー メッセージには '' だけが表示されます。このため、エラーの原因となっている正確な要素を見つけて (ユーザーに) 表示することができません。

私のxsd要素は次のようになります

<xs:element name="FullName_FirstName">
    <xs:annotation>
        <xs:appinfo>
            <ie:label>First Name</ie:label>
            <ie:html_element>0</ie:html_element>
        </xs:appinfo>
    </xs:annotation>
    <xs:simpleType>
        <xs:restriction base="xs:string">
            <xs:minLength value="1"/>
        </xs:restriction>
    </xs:simpleType>
</xs:element>

前もって感謝します

4

1 に答える 1

5

まず、いくつかのアドバイス。検証を行うためだけに DOM ドキュメントを作成する必要はありません。これにより、大量のメモリ オーバーヘッドが発生し、大きな入力 XML ドキュメントで不足することさえあります。を使用できますSAXParser。Java 1.5 以降を使用している場合は、その必要さえありません。そのバージョン以降、XML 検証 API が Java SE に組み込まれました。詳細については、パッケージjavax.xml.validationを確認してください。アイデアは、最初にオブジェクトを構築し、次に検証に使用できるオブジェクトからSchemaを取得するというものです。入力用の実装をValidator受け入れます。Sourceバリデーターも指定できるErrorHandlersため、クラスを再利用できます。もちろん、実際に DOM が必要になる可能性もありますが、その場合でも、DOM を作成する方がよいでしょう。Schemaインスタンスを作成し、それを に登録しますDocumentBuilderFactory

さて、実際の問題です。SAXParseExceptionはあまりコンテキスト情報を提供しないため、これは完全に簡単ではありません。あなたの最善の策は、ContentHandlerどこかに接続して、現在の要素やその他の位置情報を追跡することです。その後、必要に応じてそれをエラー ハンドラに渡すことができます。クラスDefaultHandlerorDefaultHandler2は、エラー処理とコンテンツ処理の両方を組み合わせる便利な方法です。これらのクラスはパッケージ org.xml.sax.ext にあります。

以下に投稿するテストをまとめました。現在、予想されたものではなく、2 行の出力が得られます。これがスキーマを使用しているからなのか、例外をスローせずに処理を続けているからなのかはわかりません。2 行目には要素の名前が含まれているので、それで十分かもしれません。例外をスローして解析を終了する代わりに、エラーにフラグを設定することができます。

package jaxb.test;

import java.io.StringReader;
import javax.xml.XMLConstants;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import javax.xml.transform.Source;
import javax.xml.transform.stream.StreamSource;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;
import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
import org.xml.sax.helpers.DefaultHandler;

public class ValidationTest {

    public static void main(String[] args) throws Exception {

        //Test XML and schema
        final String xml = "<?xml version=\"1.0\"?><test><test2></test2></test>";
        final String schemaString =
            "<?xml version=\"1.0\"?>"
            + "<xsd:schema xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" elementFormDefault=\"unqualified\" attributeFormDefault=\"unqualified\">"
            + "<xsd:element name=\"test\" type=\"Test\"/>"
            + "<xsd:element name=\"test2\" type=\"Test2\"/>"
            + "<xsd:complexType name=\"Test\">"
            + "<xsd:sequence>"
            + "<xsd:element ref=\"test2\" minOccurs=\"1\" maxOccurs=\"unbounded\"/>"
            + "</xsd:sequence>"
            + "</xsd:complexType>"
            + "<xsd:simpleType name=\"Test2\">"
            + "<xsd:restriction base=\"xsd:string\"><xsd:minLength value=\"1\"/></xsd:restriction>"
            + "</xsd:simpleType>"
            + "</xsd:schema>";

        //Building a Schema instance
        final Source schemaSource =
            new StreamSource(new StringReader(schemaString));
        final Schema schema =
            SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI).newSchema(schemaSource);

        //Creating a SAXParser for our input XML
        //First the factory
        final SAXParserFactory factory = SAXParserFactory.newInstance();
        //Must be namespace aware to receive element names
        factory.setNamespaceAware(true);
        //Setting the Schema for validation
        factory.setSchema(schema);
        //Now the parser itself
        final SAXParser parser = factory.newSAXParser();

        //Creating an instance of our special handler
        final MyContentHandler handler = new MyContentHandler();

        //Parsing
        parser.parse(new InputSource(new StringReader(xml)), handler);

    }

    private static class MyContentHandler extends DefaultHandler {

        private String element = "";

        @Override
        public void startElement(String uri, String localName, String qName,
                Attributes attributes) throws SAXException {

            if(localName != null && !localName.isEmpty())
                element = localName;
            else
                element = qName;

        }

        @Override
        public void warning(SAXParseException exception) throws SAXException {
            System.out.println(element + ": " + exception.getMessage());
        }

        @Override
        public void error(SAXParseException exception) throws SAXException {
            System.out.println(element + ": " + exception.getMessage());
        }

        @Override
        public void fatalError(SAXParseException exception) throws SAXException {
            System.out.println(element + ": " + exception.getMessage());
        }

        public String getElement() {
            return element;
        }

    }

}

少し大雑把ですが、これから作業を進めて必要なものを取得できます。

于 2011-08-18T21:21:51.920 に答える