首页 文章

JAXB:从XML子树解组?

提问于
浏览
0

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

剩下的GPX文件用DOM解析,直到 <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子树解组;如果是的话,我做错了什么?

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

unmarshaling工作,但对象的内容是空的 . 我想知道我是否遇到了一些命名空间问题?

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

@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类的“链接”?

1 回答

  • 0

    我想你在这里有一些问题:

    • 您的 MetadataType 没有 @XmlRootElement . 所以JAXB不知道哪个元素应该匹配它 .

    • 你想要部分解组,但你要解组(我猜)整个文档 .

    你可以试试的:

    • 尝试使用unmarshal(node, class)方法从特定节点解组特定类

    • 从堆栈跟踪中,您尝试解组 gpx:gpx 元素,而不是 metadata 元素 . 你必须更深入

    • 您也必须超越 package-info.java (或者在 MetadataType 中提供名称空间,否则您将缺少名称空间

    • 请参阅有关partial unmarshalling的回答 .

相关问题