JAXB XmlTransient不起作用

时间:2013-10-18 16:53:13

标签: java xml xml-parsing jaxb unmarshalling

我正在尝试使用JAXB解组以下XML:

<artist xmlns="http://www.spotify.com/ns/music/1">
   <name>Basement Jaxx</name>
   <albums>
      <album href="spotify:album:3xOulZzGRe4Ycwm59iCdKg">
         <name>Back 2 the Wild</name>
         <artist href="spotify:artist:4YrKBkKSVeqDamzBPWVnSJ">
            <name>Basement Jaxx</name>
         </artist>          
         <released>2013</released>
         <id type="upc">5055489272702</id>          
      <album>
   </albums>
</artist>

当我在相册中的艺术家上使用@XmlTransient来跳过它时,无论如何都会对其进行解析。

如何才能使JAXB正确处理标记为@XmlTransient的字段?

编辑1 - 文件

测试xml:

<artist>
     <name>Adema</name>
     <albums>
          <album href="spotify:album:07tjJowJIddz8c74x5WOvj">
               <name>Topple the Giants</name>
               <artist href="spotify:artist:3n4ersmDo55xV4fPSCKpXb">
                    <name>Adema</name>
               </artist>
               <released>2013</released>
               <id type="upc">886443922082</id>
               <availability>
                    <territories>AD AT AU BE CA CH DE DK EE ES FI FR GB HK IE IS IT LI LT LU LV MC MX MY NL NO NZ PL PT SE SG US</territories>
               </availability>
          </album>
          <album href="spotify:album:06QaJLqG068uXHQbAcPZKU">
               <name>Kill The Headlights</name>
               <artist href="spotify:artist:3n4ersmDo55xV4fPSCKpXb">
                    <name>Adema</name>
               </artist>
               <released>2007</released>
               <id type="upc">4030816195283</id>
               <availability>
                    <territories>AD AT BE CH DE DK EE ES FI FR GB IE IS IT LI LT LU LV MC NL NO PL PT SE</territories>
               </availability>
          </album>
    </albums>
</artist>

XTest.java:

package dao.spotify;

import dao.spotify.lookup.entities.LookupArtist;
import java.io.File;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;
import javax.xml.bind.helpers.DefaultValidationEventHandler;

public class XTest {

    public XTest() {
        load();
    }

    public void load() {
        try { 
            File file = new File("c:/tmp/test5.xml");
            JAXBContext jc = JAXBContext.newInstance(LookupArtist.class);
            Unmarshaller um = jc.createUnmarshaller();
            um.setEventHandler(new DefaultValidationEventHandler());
            LookupArtist spotifyArtistWrapper = (LookupArtist) um.unmarshal(file);
            System.err.println("Done");
        } catch (JAXBException ex) {
            ex.printStackTrace();
        }
    }

    public static void main(String... args) {
        XTest test = new XTest();
    }
}

LookupArtist.java:

package dao.spotify.lookup.entities;

import java.util.ArrayList;
import java.util.List;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElementWrapper;
import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement(name = "artist")
@XmlAccessorType(XmlAccessType.FIELD)
public class LookupArtist {

    @XmlElement
    private String name;
    @XmlElementWrapper(name = "albums")
    @XmlElement(name = "album")
    private List<LookupInnerAlbum> albums = new ArrayList();

}

LookupInnerAlbum.java:

package dao.spotify.lookup.entities;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlTransient;

@XmlRootElement(name = "album")
@XmlAccessorType(XmlAccessType.FIELD)
public class LookupInnerAlbum {

    @XmlAttribute
    private String href;
    private String name;
    private int released;
    private String id;
    private LookupInnerAvailability availability;
    @XmlTransient
    private LookupInnerArtist artist;

}

LookupInnerAvailability.java:

package dao.spotify.lookup.entities;

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

@XmlRootElement(name = "availability")
@XmlAccessorType(XmlAccessType.FIELD)
public class LookupInnerAvailability {

    @XmlElement
    private String territories;

}

LookupInnerArtist.java:

package dao.spotify.lookup.entities;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlType;

@XmlType(name = "artist")
@XmlAccessorType(XmlAccessType.FIELD)
public class LookupInnerArtist {

    @XmlElement
    private String name;
    @XmlAttribute
    private String href;
}

运行时,我得到:

DefaultValidationEventHandler: [ERROR]: unexpected element (uri:"", local:"artist"). Expected elements are <{}id>,<{}released>,<{}name>,<{}availability> 
javax.xml.bind.UnmarshalException: unexpected element (uri:"", local:"artist"). Expected elements are <{}id>,<{}released>,<{}name>,<{}availability>
     Location: line 6 of file:/c:/tmp/test5.xml
    at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallingContext.handleEvent(UnmarshallingContext.java:662)
    at com.sun.xml.bind.v2.runtime.unmarshaller.Loader.reportError(Loader.java:258)
    at com.sun.xml.bind.v2.runtime.unmarshaller.Loader.reportError(Loader.java:253)
    at com.sun.xml.bind.v2.runtime.unmarshaller.Loader.reportUnexpectedChildElement(Loader.java:120)
    at com.sun.xml.bind.v2.runtime.unmarshaller.Loader.childElement(Loader.java:105)
    at com.sun.xml.bind.v2.runtime.unmarshaller.StructureLoader.childElement(StructureLoader.java:262)
    at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallingContext._startElement(UnmarshallingContext.java:498)
    at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallingContext.startElement(UnmarshallingContext.java:480)
    at com.sun.xml.bind.v2.runtime.unmarshaller.SAXConnector.startElement(SAXConnector.java:150)
    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:2717)
    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:489)
    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.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal0(UnmarshallerImpl.java:258)
    at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal(UnmarshallerImpl.java:229)
    at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:136)
    at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:141)
    at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:150)
    at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:168)
    at dao.spotify.XTest.load(XTest.java:30)
    at dao.spotify.XTest.<init>(XTest.java:21)
    at dao.spotify.XTest.main(XTest.java:38)

1 个答案:

答案 0 :(得分:1)

当我运行你的例子时,我得到同样的东西。错误消息是正确的unexpected element (uri:"", local:"artist")元素存在于XML中,但您尚未映射到它。您已映射到的<{}id>,<{}released>,<{}name>,<{}availability>元素<{}artist>未显示在那里,因为您已使用@XmlTransient将其排除在外。

DefaultValidationEventHandler: [ERROR]: unexpected element (uri:"", local:"artist"). Expected elements are <{}id>,<{}released>,<{}name>,<{}availability> 
     Location: line 6 of file:/Users/bdoughan/GIT/EclipseLink-Trunk3/Scratch/src/dao/spotify/test5.xml
javax.xml.bind.UnmarshalException: unexpected element (uri:"", local:"artist"). Expected elements are <{}id>,<{}released>,<{}name>,<{}availability>
    at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallingContext.handleEvent(UnmarshallingContext.java:642)

关于DefaultValidationEventHandler的说明。此类表示JAXB 1.0的默认验证事件规则,它们与JAXB 2.0不同。以下内容来自Javadoc(参见:http://docs.oracle.com/javase/7/docs/api/javax/xml/bind/helpers/DefaultValidationEventHandler.html

  

JAXB 1.0仅默认验证事件处理程序。这是默认值   从正在管理的JAXBContext创建的所有对象的处理程序   由JAXB 1.0绑定编译器生成的模式派生代码。

     

此处理程序导致unmarshal和validate操作失败   第一个错误或致命错误。

     

此处理程序不是JAXB映射类的默认处理程序   遵循JAXB 2.0或更高版本。默认验证事件   处理已经改变,并在Unmarshaller和Marshaller中指定。

如果您未将此指定为ValidationEventHandler,那么您的文档将被正确解组。


更新

  

我害怕我不明白;我以为我画了艺术家   指定:私人LookupInnerArtist艺术家;?换的时候   DefaultValidationEventHandler到ValidationEventCollector(正确吗?)   即使我指定了艺术家,一切都很好   @XmlTransient。

由于您已指定@XmlAccessorType(XmlAccessType.FIELD),因此除了使用@XmlTransient注释的字段外,所有字段都将被视为已映射。

  

我在调试时仍然可以看到艺术家,尽管它有一个空值。

即使artist注明了@XmlTransient,它仍然可以在您的课程中使用。由于它现在被认为是未映射的,因此不会被解组操作填充。

了解更多信息