2015-10-13 49 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()設置)在前面的回答表明,如果你想被通知多個錯誤或濾除驗證錯誤的是你想容忍。