2015-10-13 31 views
2

我正在使用Jaxb将XML解组为Java对象。我需要知道XML中的新属性/元素何时失效。但是,默认情况下,解组器会忽略新的元素/属性。当Jaxb解组时,希望发现未知属性错误

当POJO中没有指定的XML中存在新的属性/元素时,是否可以设置配置失败?

我的POJO:

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

@XmlRootElement(name = "ROOT") 
public class Model { 

    private A a; 

    public A getA() { 
     return a; 
    } 

    @XmlElement(name = "A") 
    public void setA(A a) { 
     this.a = a; 
    } 

    static class A { 

     String country; 

     public String getCountry() { 
      return country; 
     } 

     @XmlAttribute(name = "Country") 
     public void setCountry(String country) { 
      this.country = country; 
     } 
    } 
} 

代码来解组​​:

JAXBContext jaxbContext = JAXBContext.newInstance(Model.class); 
Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller(); 

String sample = "<ROOT>" + 
        "<A Country=\"0\" NewAttribute=\"0\"></A>" + 
        "<NEWELEMENT> </NEWELEMENT>" + 
       "</ROOT>"; 
InputStream stream = new ByteArrayInputStream(sample.getBytes(StandardCharsets.UTF_8)); 

Object unmarshal = jaxbUnmarshaller.unmarshal(stream); 

回答

4

需要调用Unmarshaller.setEventHandler()使无效的XML内容失败。

+1

谢谢。你知道哪个事件处理程序需要在新属性上出错吗?新元素的DefaultValidationEventHandler错误,但不包含属性。我查看了ValidationEventCollector,但似乎没有收集任何我感兴趣的事件。 – n00b

+0

尝试创建您自己的并在所有事件(FATAL_ERROR,ERROR,WARNING)上失败。 – Andreas

2

您可以通过在Unmarshaller上启用XML模式验证来阻止意外的内容。如果您的POJO还没有XML Schema,则可以在运行时从JAXBContext生成一个,构建一个Schema对象,然后将其设置在Unmarshaller上。默认情况下,如果XML文档对于模式无效,则Unmarshaller将引发异常。

下面是如何做到这一点的例子:

JAXBContext jaxbContext = JAXBContext.newInstance(Model.class); 

// Generate XML Schema from the JAXBContext 
final List<ByteArrayOutputStream> schemaDocs = new ArrayList<ByteArrayOutputStream>(); 
jaxbContext.generateSchema(new SchemaOutputResolver() { 
    @Override 
    public Result createOutput(String namespaceUri, String suggestedFileName) 
     throws IOException { 
      ByteArrayOutputStream baos = new ByteArrayOutputStream(); 
      StreamResult sr = new StreamResult(baos); 
      schemaDocs.add(baos); 
      sr.setSystemId(suggestedFileName); 
      return sr; 
     } 
    }); 
SchemaFactory sf = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); 
int size = schemaDocs.size(); 
Source[] schemaSources = new Source[size]; 
for (int i = 0; i < size; ++i) { 
    schemaSources[i] = new StreamSource(
     new ByteArrayInputStream(schemaDocs.get(i).toByteArray())); 
} 
Schema s = sf.newSchema(schemaSources); 

// Set the JAXP Schema object on your Unmarshaller. 
Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller(); 
jaxbUnmarshaller.setSchema(s); 

String sample = "<ROOT>" + 
        "<A Country=\"0\" NewAttribute=\"0\"></A>" + 
        "<NEWELEMENT> </NEWELEMENT>" + 
       "</ROOT>"; 
InputStream stream = new ByteArrayInputStream(sample.getBytes("UTF-8")); 

Object unmarshal = jaxbUnmarshaller.unmarshal(stream); 

兼备这个ValidationEventHandler(通过Unmarshaller.setEventHandler()设置)在前面的回答表明,如果你想被通知多个错误或滤除验证错误的是你想容忍。