2012-05-23 15 views
7

Sto cercando di fare il contrario di: JAXB - Ignore elementFai errore JAXB su elementi non mappato

che è sto cercando di analizzare XML con JAXB ad un POJO e voglio JAXB a fallire se lo fa NON trova una proprietà Java corrispondente per un dato elemento. So che probabilmente potrei fare la convalida dello schema, ma preferirei non farlo.

Esempio:

@XmlRootElement(name="Dog") 
public class Dog { 
    private String name; 
    public String getName() {return name;} 
    public String setName(String name) {this.name = name}; 
} 

Questo XML fallirebbe:

<Dog> 
<id>blah</id> 
<name>Stuff</name> 
</Dog> 

Poiché non v'è alcuna proprietà id Java

+0

Non so se si può ottenere che l'utilizzo di JAXB. Tuttavia, questo è il comportamento predefinito di XStream. – tibtof

+0

E 'più per scopi di test unitari. Probabilmente dovrò semplicemente usare XmlUnit, unmarshal dell'XML e poi rimetterlo in discussione e confrontare quale è ciò che ho fatto in passato. –

risposta

0

L'unico modo sono stato in grado di convalidare mancante proprietà Java (w/o schema) è quello di unmarshal XML al mio POJO, quindi remarshal a XML utilizzando lo stesso POJO e confrontare.

Di seguito è riportato un esempio utilizzando XMLUnit che consente di ignorare problemi di ordine e spazi bianchi.

@Test 
public void testSerialization() throws Exception { 
    XMLUnit.setIgnoreWhitespace(true); 

    EventSearchResults r = 
      JAXB.unmarshal(getClass().getResourceAsStream("/EventSearchResults.xml"), 
        EventSearchResults.class); 
    StringWriter sw = new StringWriter(); 
    JAXB.marshal(r, sw); 
    String expected = 
      IOUtils.toString(getClass().getResourceAsStream("/EventSearchResults.xml"), "UTF-8"); 
    String actual = sw.toString(); 
    //System.out.println(expected); 
    System.out.println(actual); 
    assertXMLEqual(expected, actual); 
} 

Questo non è l'ideale ma per la maggior parte funziona per Test unità.

3

È possibile utilizzare un ValidationEventHandler per ottenere il comportamento desiderato. Un elemento inatteso viene considerato come un avviso che viene ignorato per impostazione predefinita. Per supportare il tuo caso d'uso puoi fornire un ValdidationEventHandler che non funziona sugli avvisi (vedi sotto).

Demo

package forum10721257; 

import java.io.File; 
import javax.xml.bind.*; 

public class Demo { 

    public static void main(String[] args) throws Exception { 
     JAXBContext jc = JAXBContext.newInstance(Dog.class); 

     File xml = new File("src/forum10721257/input.xml"); 
     Unmarshaller unmarshaller = jc.createUnmarshaller(); 
     unmarshaller.setEventHandler(new ValidationEventHandler() { 

      @Override 
      public boolean handleEvent(ValidationEvent event) { 
       return false; 
      } 

     }); 
     Dog dog = (Dog) unmarshaller.unmarshal(xml); 
    } 

} 

JAXB RI Eccezione

Exception in thread "main" javax.xml.bind.UnmarshalException: unexpected element (uri:"", local:"id"). Expected elements are <{}name> 
    at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext.handleEvent(UnmarshallingContext.java:647) 
    at com.sun.xml.internal.bind.v2.runtime.unmarshaller.Loader.reportError(Loader.java:243) 
    at com.sun.xml.internal.bind.v2.runtime.unmarshaller.Loader.reportError(Loader.java:238) 
    at com.sun.xml.internal.bind.v2.runtime.unmarshaller.Loader.reportUnexpectedChildElement(Loader.java:105) 
    at com.sun.xml.internal.bind.v2.runtime.unmarshaller.Loader.childElement(Loader.java:90) 
    at com.sun.xml.internal.bind.v2.runtime.unmarshaller.StructureLoader.childElement(StructureLoader.java:236) 
    at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext._startElement(UnmarshallingContext.java:483) 
    at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext.startElement(UnmarshallingContext.java:465) 
    at com.sun.xml.internal.bind.v2.runtime.unmarshaller.SAXConnector.startElement(SAXConnector.java:135) 
    at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.startElement(AbstractSAXParser.java:506) 
    at com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.scanStartElement(XMLNSDocumentScannerImpl.java:376) 
    at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl$FragmentContentDriver.next(XMLDocumentFragmentScannerImpl.java:2715) 
    at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next(XMLDocumentScannerImpl.java:607) 
    at com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.next(XMLNSDocumentScannerImpl.java:116) 
    at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(XMLDocumentFragmentScannerImpl.java:488) 
    at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:835) 
    at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:764) 
    at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(XMLParser.java:123) 
    at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(AbstractSAXParser.java:1210) 
    at com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl$JAXPSAXParser.parse(SAXParserImpl.java:568) 
    at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal0(UnmarshallerImpl.java:202) 
    at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal(UnmarshallerImpl.java:174) 
    at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:157) 
    at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:162) 
    at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:171) 
    at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:189) 
    at forum10721257.Demo.main(Demo.java:26) 

EclipseLink JAXB (moxy)

Recentemente abbiamo aggiunto questo comportamento per moxy. È necessario utilizzare EclipseLink 2.4.0 o 2.3.3. Un nightly build può essere ottenuto dal seguente percorso:


UPDATE

avevo bisogno di modificare la classe Dog dalla tua domanda. Di seguito è quello che ho usato.

Dog

package forum10721257; 

import javax.xml.bind.annotation.XmlRootElement; 

@XmlRootElement(name="Dog") 
public class Dog { 
    private String name; 
    public String getName() {return name;} 
    public void setName(String name) {this.name = name;} 
} 
+1

Hmm L'ho provato e non ha funzionato (ammesso che non fosse MOXy).Dovrò provare di nuovo. BTW Ho appena usato il tuo trucco per elementi XML dinamici: http://blog.bdoughan.com/2012/02/xmlanyelement-and-xmladapter.html. Si va in giro quando si tratta di JAXB :) –

+0

Ho eseguito questo codice esatto in JDK 1.7.0 (per Mac) per ottenere l'eccezione che ho postato. Quale versione del JDK stai usando? –

+0

JDK 1.6 Proverò di nuovo a breve. Penso che sia stato il modo in cui stavo facendo il contesto. –

Problemi correlati