JAXB没有检测到元素

时间:2017-06-28 21:30:09

标签: java xml youtube jaxb rss

我正在尝试利用JAXB将从youtube rss feed获得的xml元素转换为对象。我似乎遵循了我见过的大多数示例的结构,但仍然无法使其工作,因为它总是看起来Feed中的列表始终是空的。有谁知道如何解决这一问题? 以下是我的课程供参考:

饲料类:

import java.util.List;
import javax.xml.bind.annotation.*;
import javax.xml.*;

@XmlRootElement(
    name = "feed",
    namespace = "http://www.w3.org/2005/Atom"
    )
    @XmlAccessorType (XmlAccessType.FIELD)
    public class feed {

    @XmlElement(name = "entry")
    private List<entry> entries;
    public List<entry> getEntry() {
        return this.entries;
    }
    public void setEntry(List<entry> entries) {
        this.entries = entries;
    }
}

入门级:

import javax.xml.bind.annotation.*;
import java.util.List;

@XmlRootElement(name = "entry")
@XmlAccessorType(XmlAccessType.FIELD)
public class entry {
private String title, name, id, published;


public void settitle(String title){this.title = title;}
public String gettitle(){return title;}

public void setname(String name){this.name = name;};
public String getname() {
    return name;
}

public void setid(String id){this.id = id;}
public String getid() {
    return id;
}

public void setpublished(String published){this.published = published;}
public String getpublished() {return published;}


public void PrintVideoInfo(){
    System.out.println(gettitle());
    System.out.println(getname());
    System.out.println(getid());
    System.out.println(getpublished());
    System.out.println("-----------");
}
}

解组课程:

import java.io.File;
import java.util.List;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;

public class XMLtoObject {
public static void main(String[] args) {

    try {

        File file = new File("videos.xml");
        JAXBContext jaxbContext = JAXBContext.newInstance(feed.class);

        Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
        feed que= (feed) jaxbUnmarshaller.unmarshal(file);

        for(entry ent:que.getEntry())
            ent.PrintVideoInfo();

    } catch (JAXBException e) {
        e.printStackTrace();
    }

}
}

https://www.youtube.com/feeds/videos.xml?channel_id=UCBcRF18a7Qf58cCRy5xuWwQ这是正在使用的xml。它保存为videos.xml,文件路径正确,在上面的代码段中没有完全包含隐私。任何帮助将不胜感激。

1 个答案:

答案 0 :(得分:2)

  1. 请使您的类名遵循Pascal符号 - 这样更容易阅读和理解,尤其是当有大量代码时。或许,您应该更多地处理您的代码风格。

  2. 您的feed类已正确注释,但为了让JAXB将XML解组为条目entry,还应正确注释类。另请注意,您的字段名称与提供的xml文件中的标记名称不匹配(<name>无法在<feed>内直接访问)。 因此,添加注释和类以匹配xml文件结构。

  3. 更新1

    我意识到我不太了解xml文档,所以我做了一些调查。

    如果您完全熟悉xml命名空间,则可以跳过此部分到“序列化”部分。否则,请继续阅读。

    命名空间是一种将xml节点划分为非交叉集的机制。想象一下,在xml中有一个<address>标签,标签定义了很多次。例如,它可以引用网址或街道地址,因此根据上下文具有完全不同的含义。为了避免混淆,您可以添加一个名称空间前缀:<web:address> <street:address>来分隔它们,并将引用同一名称空间的其他元素分组。您可以在某个根标记中更早地定义它们:

    <root xmlns:web="Web"> 
        <web:address> ... </web:address>
    </root>
    

    此外,还有一个特殊的命名空间 - 默认命名空间 - 定义如下:<feed xmlns="Name">。拥有默认命名空间允许您在每次定义xml元素时省略写入命名空间前缀。

    让我们用你的xml示例清楚这一点:它为<feed>元素(yt,media和默认命名空间)指出了三个命名空间

    <feed xmlns:yt="http://www.youtube.com/xml/schemas/2015" 
          xmlns:media="http://search.yahoo.com/mrss/" 
          xmlns="http://www.w3.org/2005/Atom">
    

    这意味着 <feed>中的每个元素都隐含地以默认命名空间为前缀。

    Intro to XML namespaces

    Atom namespace explained

    <强>序列化

    我下载了您提供的xml文件并进行了一些测试。事实证明,JAXB只是“没有看到”实体标签,因为它们隐藏在默认的namspace之后,我们从未对JAXB说过,除了<feed>元素之外,根本没有命名空间。 / p>

    因此,解决方案是使用命名空间注释要反序列化的元素,以便JAXB可以理解。

    更新2

    看起来上面提供的解决方案太乱了:必须用命名空间注释每个其他元素才真正违反了DRY原则。幸运的是,有一种解决方案可以在一行中添加默认命名空间。

    创建一个名为 package-info.java 的文件,并在其中添加以下内容并将package替换为您的文件:

    @XmlSchema(
            namespace = "http://www.w3.org/2005/Atom",
            elementFormDefault = XmlNsForm.QUALIFIED
    )
    package package;
    
    import javax.xml.bind.annotation.XmlNsForm;
    import javax.xml.bind.annotation.XmlSchema;
    

    它所做的就是为我们要解析的文档定义一个xml架构。您现在可以删除所有namespace = "..."行并完成代码 如果您不熟悉xml架构,请查看它,因为这是控制xml文档结构的好方法。

    更新2之后的代码:

    Feed类

    import javax.xml.bind.annotation.*;
    import java.util.List;
    
    @XmlRootElement(name = "feed")
    @XmlAccessorType(XmlAccessType.FIELD)
      public class Feed {
    
        @XmlElement(name = "entry")
        private List<Entry> entries;
    
        public List<Entry> getEntries() {
            return this.entries;
        }
    
    }
    

    入门级

    import javax.xml.bind.annotation.*;
    import java.util.Date;
    
    @XmlRootElement(name = "entry")
    @XmlAccessorType(XmlAccessType.FIELD)
    public class Entry {
    
        @XmlElement(name = "title")
        private String title;
    
        @XmlElement(name = "id")
        private String id;
    
        @XmlElement(name = "published")
        private Date datePublished;
    
        @XmlElement(name = "author")
        private Author author;
    
        public String toString(){
            return String.format("Id: %s, Title: %s, Author: %s, Published: %s",
                   id,
                   title,
                   author.toString(),
                   datePublished.toString());
            }
    
    }
    

    作者类

    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 = "author")
    @XmlAccessorType(XmlAccessType.FIELD)
    public class Author {
    
        @XmlElement(name = "name")
        private String name;
    
        @XmlElement(name = "url")
        private String url;
    
        public String getName() {
            return name;
        }
    
        public String getUrl() {
            return url;
        }
    
        @Override
        public String toString() {
            return getName();
        }
    
    }
    

    主要

    import javax.xml.bind.JAXBContext;
    import javax.xml.bind.JAXBException;
    import java.io.File;
    
    public class Main {
    
        public static void main(String[] args) throws JAXBException {
            Feed feed = (Feed) JAXBContext
                    .newInstance(Feed.class)
                    .createUnmarshaller()
                    .unmarshal(new File("youtube_feed.xml"));
    
            for (Entry entry : feed.getEntries()) {
                System.out.println(entry.toString());
            }
    
        }
    }
    

    阅读理解

    JAXB and XML namespaces

    Oracle JAXB annotations reference