【问题标题】:JAXB: unmarshal from XML subtree?JAXB:从 XML 子树解组?
【发布时间】:2014-03-30 01:51:58
【问题描述】:

我的 JAVA 程序使用类似于 GPX 1.1 的内部类层次结构,但并不完全相同。因为重写它以使 1:1 符合 GPX 是一项巨大的工作,所以我想一点一点地改变它,即将<metadata> 子树读入 MetadataType 类,就像使用来自 the XSD file 的 xjc 生成的一样。

用 DOM 解析剩余的 GPX 文件,直到出现 <metadata>

private void parseMetadata(MetadataType metadata, Element element) throws JAXBException {
    try {
        System.out.println(element.getNodeName()); // output: metadata
        JAXBContext context = JAXBContext.newInstance(MetadataType.class);

        javax.xml.bind.Unmarshaller u = context.createUnmarshaller();

        JAXBElement<MetadataType> meta = u.unmarshal(element, MetadataType.class);
        metadata = meta.getValue();

        } catch (Exception e) { 
            e.printStackTrace();
        }
    System.out.println(metadata.getName()); // NULL
    System.out.println(metadata.getAuthor().getName()); // NULL
}

投掷 javax.xml.bind.UnmarshalException: unexpected element (uri:"", local:"metadata"). Expected elements are <{http://www.topografix.com/GPX/1/1}gpx> at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext.handleEvent(UnmarshallingContext.java:647)

这个类看起来像这样:

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "metadataType", propOrder = {
"name",
"desc",
"author",
"copyright",
"link",
"time",
"keywords",
"bounds",
"extensions"
})
@XmlRootElement(name = "metadata")
public class MetadataType {

protected String name = "";
protected String desc = "";
protected PersonType author;
protected CopyrightType copyright = new CopyrightType();
protected List<LinkType> link = new ArrayList<LinkType>();
@XmlSchemaType(name = "Date")
protected Date time;
protected String keywords = "";
protected BoundsType bounds = new BoundsType();
protected ExtensionsType extensions = new ExtensionsType();
[...]
}

是否可以从 XML 子树中解组;如果是,我做错了什么?

更新/1: 感谢 lexicore,我更进一步:element 肯定包含 metadata 节点,@XmlRootElement 已设置,现在使用 unmarshal(element, MetadataType.class) 解组。

解组工作,但对象的内容是空的。我想知道我是否在这里遇到了一些命名空间问题?

com.topografix.gpx._1._1包含一个package-info.java,由xjc生成:

@javax.xml.bind.annotation.XmlSchema(namespace = "http://www.topografix.com/GPX/1/1", elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED)
package com.topografix.gpx._1._1;

这是其中一个测试文件:

<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<gpx xmlns="http://www.topografix.com/GPX/1/1" 
xmlns:gpxx="http://www.garmin.com/xmlschemas/GpxExtensions/v3" 
xmlns:wptx1="http://www.garmin.com/xmlschemas/WaypointExtension/v1" 
xmlns:gpxtpx="http://www.garmin.com/xmlschemas/TrackPointExtension/v1" 
creator="GPSMAP 62s" version="1.1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xsi:schemaLocation="http://www.topografix.com/GPX/1/1 
http://www.topografix.com/GPX/1/1/gpx.xsd http://www.garmin.com/xmlschemas /GpxExtensions/v3 
http://www8.garmin.com/xmlschemas/GpxExtensionsv3.xsd http://www.garmin.com/xmlschemas/WaypointExtension/v1 
http://www8.garmin.com/xmlschemas/WaypointExtensionv1.xsd http://www.garmin.com/xmlschemas/TrackPointExtension/v1 
http://www.garmin.com/xmlschemas/TrackPointExtensionv1.xsd">
<metadata>
<link href="http://www.garmin.com">
<text>Garmin International</text>
</link>
<time>2014-01-01T22:26:49Z</time>
</metadata>
[...]

UPDATE/2:命名空间/包名是正确的。如果命名空间设置为(即)“foobar”,则会引发以下异常: javax.xml.bind.JAXBException: Provider com.sun.xml.internal.bind.v2.ContextFactory could not be instantiated: javax.xml.bind.JAXBException: "foobar" doesnt contain ObjectFactory.class or jaxb.index

像之前一样初始化,没有抛出异常,说明命名空间正确,找到了ObjectFactory.class。

String contextPath = MetadataType.class.getPackage().getName(); JAXBContext context = JAXBContext.newInstance(contextPath);

所以,命名空间是正确的,但不知何故缺少指向 MetadataType 类的“链接”?

【问题讨论】:

    标签: java jaxb gpx


    【解决方案1】:

    我猜你这里有几个问题:

    • 您的MetadataType 没有@XmlRootElement。所以 JAXB 不知道应该与哪个元素匹配。
    • 您想要部分解组,但您正在解组(我猜)整个文档。

    你可以尝试什么:

    • 尝试使用unmarshal(node, class) 方法从特定节点解组特定类
    • 从堆栈跟踪中,您尝试解组 gpx:gpx 元素,而不是 metadata 元素。你必须更深入
    • 您还必须超越 package-info.java(或在您的 MetadataType 中提供命名空间,否则您将缺少命名空间
    • 请参阅有关partial unmarshalling 的答案。

    【讨论】:

    • 感谢您的回答,我现在更进一步了。在这方面更新了问题。
    • 是的,好像是 ns 问题。尝试使用包名而不是单个类来构建上下文。 IE。 JAXBContext.newInstance(MetadatatType.class.getPackage().getName())。
    • 命名空间似乎是正确的,但可能没有“找到”类的“链接”? @XmlRootElement 仅为 MetadataType.class 设置
    • unmarshal(node, class) 方法,为我工作!
    猜你喜欢
    • 1970-01-01
    • 2013-11-15
    • 1970-01-01
    • 2013-01-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多