JAXB Unmarshalling和继承

时间:2014-03-20 09:44:52

标签: java xml jaxb xsd jaxb2

场合
对于一个项目,我们必须处理大量的XSD。很多这些模式都是GML,或者以某种方式与GML相关。我们使用JAXB2为我们提供Java类并将XML映射到Java对象。这令人沮丧,但对于像OGC Bindings项目这样的项目,我们已经走了很长的路。

问题
解组我们当前的数据时,似乎在JAXB2中存在继承问题。当我们解组一个集合时,这个集合没有被填充。所以我使用ValidationEventCollector作为处理程序来检查代码。虽然没有Exception被抛出,ValidationEventCollector仍然会给我错误:unexpected element ...

相关代码
我们正在使用带有recommended bindings的GML 3.1.1和带有以下绑定的CityGML: bindings.xjb

<jaxb:bindings version="1.0" xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
    xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc"
    xmlns:inheritance="http://jaxb2-commons.dev.java.net/basic/inheritance"
    xmlns:annox="http://annox.dev.java.net" jaxb:extensionBindingPrefixes="xjc inheritance">

    <jaxb:globalBindings
        fixedAttributeAsConstantProperty="false" typesafeEnumBase="xs:string"
        typesafeEnumMemberName="generateName" generateIsSetMethod="true">
        <xjc:noValidator />
        <xjc:noValidatingUnmarshaller />
    </jaxb:globalBindings>

    <jaxb:bindings schemaLocation="citygml-2.0/2.0/cityGMLBase.xsd"
        node="/xs:schema">
        <jaxb:schemaBindings>
            <jaxb:package name="net.opengis.citygml.v_2_0" />
        </jaxb:schemaBindings>
        <jaxb:bindings node="xs:complexType[@name='CityModelType']">
            <annox:annotate>
                <annox:annotate annox:class="javax.xml.bind.annotation.XmlRootElement"
                    name="CityModel"
                    namespace="http://www.opengis.net/citygml/2.0" />
            </annox:annotate>
        </jaxb:bindings>
    </jaxb:bindings>

</jaxb:bindings>

我们也试过<xjc:simple />,但这并没有什么不同。除了绑定之外,我们还有一个有效的目录(关于其他模式),并且在编译之前会删除重复的ObjectFactory类。

以下(部分)XML用于解组

<?xml version="1.0" encoding="UTF-8"?>
<cit:CityModel xmlns:gml="http://www.opengis.net/gml" xmlns:cit="http://www.opengis.net/citygml/2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" gml:id="example">
    <gml:boundedBy>
        <gml:Envelope srsName="http://www.opengis.net/def/crs/EPSG/0/28992">
            <gml:lowerCorner>144280.193 414155.258</gml:lowerCorner>
            <gml:upperCorner>147300.873 416928.884</gml:upperCorner>
        </gml:Envelope>
    </gml:boundedBy>
    <cit:cityObjectMember>
        ...
    </cit:cityObjectMember>
    <cit:cityObjectMember>
        ...
    </cit:cityObjectMember>
    <cit:cityObjectMember>
        ...
    </cit:cityObjectMember>
</cit:CityModel>

cityObjectMember中的ObjectFactory类中net.opengis.citygml.v_2_0(问题所在的位置)代码

@XmlElementDecl(namespace = "http://www.opengis.net/citygml/2.0", name = "cityObjectMember", substitutionHeadNamespace = "http://www.opengis.net/gml", substitutionHeadName = "featureMember")
public JAXBElement<FeaturePropertyType> createCityObjectMember(FeaturePropertyType value) {
    return new JAXBElement<FeaturePropertyType>(_CityObjectMember_QNAME, FeaturePropertyType.class, null, value);
}

使用相应的解组编码

Unmarshaller um = JAXBContext.newInstance("net.opengis.citygml.v_2_0:net.opengis.gml").createUnmarshaller();

JAXB2ValidationEventCollector vec = new JAXB2ValidationEventCollector();
um.setEventHandler(vec);

Object unmarshalled = um.unmarshal(this.getFile());

// Check for errors, when there are (validation) errors, throw them to System.err.
if (vec.hasEvents()) {
    for (ValidationEvent ve : vec.getEvents()) {
        System.err.println(String.format("[Line: %d Column: %d] %s", ve.getLocator().getLineNumber(), 
                ve.getLocator().getColumnNumber(), ve.getMessage()));
    }
}

并作为ValidationEventCollector:

import javax.xml.bind.ValidationEvent;
import javax.xml.bind.util.ValidationEventCollector;

class JAXB2ValidationEventCollector extends ValidationEventCollector {

    @Override
    public boolean handleEvent(ValidationEvent event) {
        super.handleEvent(event);
        return true;
    }
}

问题!
首先,就像我已经提到的那样,cityObjectMember没有得到解析。这是问题的根源。这就是我将eventHandler添加到unmarshaller的原因。这导致以下错误:

[Line: 56 Column: 27] unexpected element (uri:"http://www.opengis.net/citygml/2.0", local:"cityObjectMember"). Expected elements are <{http://www.opengis.net/gml}ellipsoidName>,<{http://www.opengis.net/gml}meridianName>,<{http://www.opengis.net/gml}featureMember>,<{http://www.opengis.net/citygml/2.0}_GenericApplicationPropertyOfCityModel>,<{http://www.opengis.net/gml}parameterName>,<{http://www.opengis.net/gml}groupName>,<{http://www.opengis.net/gml}srsName>,<{http://www.opengis.net/gml}metaDataProperty>,<{http://www.opengis.net/gml}priorityLocation>,<{http://www.opengis.net/gml}location>,<{http://www.opengis.net/gml}coordinateOperationName>,<{http://www.opengis.net/gml}datumName>,<{http://www.opengis.net/gml}featureMembers>,<{http://www.opengis.net/gml}methodName>,<{http://www.opengis.net/gml}boundedBy>,<{http://www.opengis.net/gml}csName>,<{http://www.opengis.net/gml}description>,<{http://www.opengis.net/gml}name>
老实说......我现在已经陷入困境了。我不知道如何继续下去。所以,如果有人知道答案或问题的根源,那将是非常好的。谢谢:)。

1 个答案:

答案 0 :(得分:2)

我是“OGC架构和工具项目”的作者。 你的绑定似乎是正确的,对象工厂看起来很好,它应该工作。 您遇到的核心问题是gml:featureMember由于某种原因未被cit:cityObjectMember取代。很难说为什么。我试图分析JAXB为您的类创建的运行时模型来解决这个问题。不知怎的,@XmlElementDecl createCityObjectMember被忽略了。

我对这类事情的处理方法通常是采取一些不起作用的东西,然后尝试减少差距,从而找出本质上是一个问题的前沿。

在这种情况下,我将获取代码并构建一个替换有效的最小示例。然后我会尝试减少你不工作的例子,剥去它不相关的属性等等。最后,你将获得优势,这将为你提供一个错误的线索。

我的猜测,没有更深入的是范围。也许gml:featureMemeber的替换在某种程度上是有限的,你的替换与“限制”不匹配。很难说没有调试。

随时联系我(valxov at gmx net),提供你的映射(或整个项目),我会尽力帮助你。