可以使用Jaxb2自定义验证消息吗?

时间:2011-04-26 19:09:13

标签: validation jaxb unmarshalling jaxb2

任何人都知道如何使用JaxB 2.x进行自定义验证消息?我需要知道哪个标签或对象属性导致错误。 我已经有一个自定义的ValidationEventHandler,但handleEvent方法的ValidationEvent事件参数不会带来Node信息,只是与XML文档中的错误相关的行和列。 我的目的是使用更友好的用户自定义解组错误消息。有办法做到这一点吗?

谢谢!

1 个答案:

答案 0 :(得分:1)

javax.xml.bind.ValidationEventLocator提供了有关问题原因的一些信息。

元帅行动

在编组操作期间报告ValidationEvent时,应通过以下方式提供与错误相关的对象:

validationEvent.getLocator().getObject();

Unmarshal Operation

在解组操作期间报告ValidationEvent时,如果可用,则可以返回相应的DOM节点(当从DOM节点以外的源解组时,此属性上不会出现任何内容)。

validationEvent.getLocator().getNode();      

了解更多信息


<强>更新

您可以执行以下操作:

<强>演示

import java.io.File;
import java.io.FileReader;

import javax.xml.XMLConstants;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Unmarshaller;
import javax.xml.bind.UnmarshallerHandler;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;

import org.xml.sax.InputSource;
import org.xml.sax.XMLReader;

public class Demo {

    public static void main(String[] args) throws Exception {
        SAXParserFactory spf = SAXParserFactory.newInstance();
        spf.setNamespaceAware(true);

        SchemaFactory sf = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); 
        Schema schema = sf.newSchema(new File("customer.xsd"));
        spf.setSchema(schema);

        JAXBContext jc = JAXBContext.newInstance(Customer.class);
        Unmarshaller unmarshaller = jc.createUnmarshaller();
        UnmarshallerHandler unmarshallerHandler = unmarshaller.getUnmarshallerHandler();

        SAXParser sp = spf.newSAXParser();
        XMLReader xr = sp.getXMLReader();
        ContentAndErrorHandler contentErrorHandler = new ContentAndErrorHandler(unmarshallerHandler);
        xr.setErrorHandler(contentErrorHandler);
        xr.setContentHandler(contentErrorHandler);

        InputSource xml = new InputSource(new FileReader("input.xml"));
        xr.parse(xml);
    }

}

<强> ContentAndErrorHandler

此类充当ContentHandler和ErrorHandler。这样就可以存储错误发生时的当前节点名称。

import org.xml.sax.Attributes;
import org.xml.sax.ContentHandler;
import org.xml.sax.ErrorHandler;
import org.xml.sax.Locator;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;

public class ContentAndErrorHandler implements ContentHandler, ErrorHandler {

    private ContentHandler contentHandler;
    private String qname;
    private String namespaceURI;

    public ContentAndErrorHandler(ContentHandler contentHandler) {
        this.contentHandler = contentHandler;
    }

    public void characters(char[] arg0, int arg1, int arg2) throws SAXException {
        contentHandler.characters(arg0, arg1, arg2);
    }

    public void endDocument() throws SAXException {
        contentHandler.endDocument();
    }

    public void endElement(String arg0, String arg1, String arg2)
            throws SAXException {
        qname = arg2;
        namespaceURI = arg0;
        contentHandler.endElement(arg0, arg1, arg2);
    }

    public void endPrefixMapping(String arg0) throws SAXException {
        contentHandler.endPrefixMapping(arg0);
    }

    public void ignorableWhitespace(char[] arg0, int arg1, int arg2)
            throws SAXException {
        contentHandler.ignorableWhitespace(arg0, arg1, arg2);
    }

    public void processingInstruction(String arg0, String arg1)
            throws SAXException {
        contentHandler.processingInstruction(arg0, arg1);
    }

    public void setDocumentLocator(Locator arg0) {
        contentHandler.setDocumentLocator(arg0);
    }

    public void skippedEntity(String arg0) throws SAXException {
        contentHandler.skippedEntity(arg0);
    }

    public void startDocument() throws SAXException {
        contentHandler.startDocument();
    }

    public void startElement(String arg0, String arg1, String arg2,
            Attributes arg3) throws SAXException {
        qname = arg2;
        namespaceURI = arg0;
        contentHandler.startElement(arg0, arg1, arg2, arg3);
    }

    public void startPrefixMapping(String arg0, String arg1)
            throws SAXException {
        contentHandler.startPrefixMapping(arg0, arg1);
    }

    public void error(SAXParseException arg0) throws SAXException {
        System.out.println("{" + namespaceURI + "}" + qname);
        arg0.printStackTrace(System.out);
    }

    public void fatalError(SAXParseException arg0) throws SAXException {
        System.out.println("{" + namespaceURI + "}" + qname);
        arg0.printStackTrace(System.out);
    }

    public void warning(SAXParseException arg0) throws SAXException {
        System.out.println("{" + namespaceURI + "}" + qname);
        arg0.printStackTrace(System.out);
    }

}

<强>客户

import java.util.ArrayList;
import java.util.List;

import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement
public class Customer {

    private String name;
    private List<PhoneNumber> phoneNumbers = new ArrayList<PhoneNumber>();

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @XmlElement(name="phone-number")
    public List<PhoneNumber> getPhoneNumbers() {
        return phoneNumbers;
    }

    public void setPhoneNumbers(List<PhoneNumber> phoneNumbers) {
        this.phoneNumbers = phoneNumbers;
    }

}

<强> ******中国

public class PhoneNumber {

}

<强> customer.xsd

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

    <xs:element name="customer">
        <xs:complexType>
            <xs:sequence>
                <xs:element name="name" type="stringWithMaxSize5" />
                <xs:element ref="phone-number" maxOccurs="2" />
             </xs:sequence>
        </xs:complexType>
    </xs:element>

    <xs:element name="phone-number">
        <xs:complexType />
    </xs:element>

    <xs:simpleType name="stringWithMaxSize5">
        <xs:restriction base="xs:string">
            <xs:maxLength value="5"/>
        </xs:restriction>
    </xs:simpleType>

</xs:schema>

<强> input.xml中

<?xml version="1.0" encoding="UTF-8"?>
<customer>
   <name>Jane Doe</name>
   <phone-number/>
   <phone-number/>
   <phone-number/>
</customer>

<强>输出

{}name
org.xml.sax.SAXParseException: cvc-maxLength-valid: Value 'Jane Doe' with length = '8' is not facet-valid with respect to maxLength '5' for type 'stringWithMaxSize5'.
    at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.createSAXParseException(Unknown Source)
    at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.error(Unknown Source)
    at com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(Unknown Source)
    at com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(Unknown Source)
    at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator$XSIErrorReporter.reportError(Unknown Source)
    at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator.reportSchemaError(Unknown Source)
    at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator.elementLocallyValidType(Unknown Source)
    at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator.processElementContent(Unknown Source)
    at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator.handleEndElement(Unknown Source)
    at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator.endElement(Unknown Source)
    at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanEndElement(Unknown Source)
    at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl$FragmentContentDriver.next(Unknown Source)
    at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next(Unknown Source)
    at com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.next(Unknown Source)
    at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(Unknown Source)
    at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(Unknown Source)
    at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(Unknown Source)
    at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(Unknown Source)
    at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(Unknown Source)
    at com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl$JAXPSAXParser.parse(Unknown Source)
    at example.Demo.main(Demo.java:39)
{}name
org.xml.sax.SAXParseException: cvc-type.3.1.3: The value 'Jane Doe' of element 'name' is not valid.
    at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.createSAXParseException(Unknown Source)
    at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.error(Unknown Source)
    at com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(Unknown Source)
    at com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(Unknown Source)
    at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator$XSIErrorReporter.reportError(Unknown Source)
    at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator.reportSchemaError(Unknown Source)
    at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator.elementLocallyValidType(Unknown Source)
    at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator.processElementContent(Unknown Source)
    at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator.handleEndElement(Unknown Source)
    at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator.endElement(Unknown Source)
    at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanEndElement(Unknown Source)
    at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl$FragmentContentDriver.next(Unknown Source)
    at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next(Unknown Source)
    at com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.next(Unknown Source)
    at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(Unknown Source)
    at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(Unknown Source)
    at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(Unknown Source)
    at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(Unknown Source)
    at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(Unknown Source)
    at com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl$JAXPSAXParser.parse(Unknown Source)
    at example.Demo.main(Demo.java:39)
{}phone-number
org.xml.sax.SAXParseException: cvc-complex-type.2.4.d: Invalid content was found starting with element 'customer'. No child element '{phone-number}' is expected at this point.
    at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.createSAXParseException(Unknown Source)
    at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.error(Unknown Source)
    at com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(Unknown Source)
    at com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(Unknown Source)
    at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator$XSIErrorReporter.reportError(Unknown Source)
    at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator.reportSchemaError(Unknown Source)
    at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator.elementLocallyValidComplexType(Unknown Source)
    at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator.elementLocallyValidType(Unknown Source)
    at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator.processElementContent(Unknown Source)
    at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator.handleEndElement(Unknown Source)
    at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator.endElement(Unknown Source)
    at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanEndElement(Unknown Source)
    at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl$FragmentContentDriver.next(Unknown Source)
    at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next(Unknown Source)
    at com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.next(Unknown Source)
    at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(Unknown Source)
    at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(Unknown Source)
    at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(Unknown Source)
    at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(Unknown Source)
    at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(Unknown Source)
    at com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl$JAXPSAXParser.parse(Unknown Source)
    at example.Demo.main(Demo.java:39)