2

我正在尝试使用 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)
4

1 回答 1

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 2.0 不同的 JAXB 1.0 的默认验证事件规则。以下来自 Javadoc(参见:http ://docs.oracle.com/javase/7/docs/api/javax/xml/bind/helpers/DefaultValidationEventHandler.html )

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

此处理程序导致解组和验证操作在第一个错误或致命错误时失败。

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

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


更新

恐怕我不明白;我以为我在指定时映射了艺术家:私人 LookupInnerArtist 艺术家;?将 DefaultValidationEventHandler 更改为 ValidationEventCollector(正确吗?)时一切正常,即使我已将艺术家指定为 @XmlTransient。

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

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

即使artist带有注释,@XmlTransient您的班级仍然可以使用它。因为它现在被认为是未映射的,所以它不会被 unmarshal 操作填充。

了解更多信息

于 2013-10-18T18:36:46.443 回答