尝试使用JAXB解组EDMX时出错

时间:2013-02-14 13:30:25

标签: java jaxb

我是JAXB的新手,我正试图解组某个XML XML是:

<edmx:Edmx xmlns:edmx="http://schemas.microsoft.com/ado/2007/06/edmx">
<edmx:DataServices xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" m:DataServiceVersion="3.0">
    <Schema xmlns:cg="http://schemas.microsoft.com/ado/2006/04/codegeneration" xmlns:sap="http://www.sap.com/Protocols/SAPData" xmlns="http://schemas.microsoft.com/ado/2009/11/edm" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices" Namespace="smallApp">         
    </Schema>
</edmx:DataServices>

我已经构建了一个类似于以下类的模式:

Edmx.java

import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement(name = "edmx:Edmx")
public class Edmx {

@XmlElement(name = "edmx:DataServices")
private DataService dataService;

public DataService getDataService() {
    return dataService;
}
}

DataService.java

import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement(name = "edmx:DataServices")
public class DataService {

@XmlElement(name = "Schema")
private Schema schema;

public Schema getSchema() {
    return schema;
}
 }

和Schema.java

import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement(name = "Schema")
public class Schema {

}

然后,我构建了一个示例方法,用Edmx.class解组上述XML:

public class Parser {

public static void main(String[] args) {
    File fXmlFile = new File("somePathToXML");
    try {
        InputStream inputStream = new FileInputStream(fXmlFile);
        Edmx edmx = load(Edmx.class, inputStream);

    } catch (FileNotFoundException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

}

/**
 * loads an object from an xml file
 * @param <T>
 * @param type
 * @param file
 * @return
 */
public static <T> T load(Class<? extends T> type, InputStream stream) {
    try {

        if(stream.available() == 0) {
            return null;
        }

        JAXBContext context = JAXBContext.newInstance(type);
        Unmarshaller um = context.createUnmarshaller();
        @SuppressWarnings("unchecked")
        T obj = (T) um.unmarshal(stream);
        return obj;
    } catch (JAXBException jaxbe) {
        System.out.println("failed to read from InputStream");
        jaxbe.printStackTrace();
        return null;
    } catch (IOException ioe) {
        System.out.println("InputStream is empty");
        return null;
    }

}
 }

我一直遇到的错误是:

javax.xml.bind.UnmarshalException: unexpected element (uri:"http://schemas.microsoft.com/ado/2007/06/edmx", local:"Edmx"). Expected elements are <{}Schema>,<{}edmx:DataServices>,<{}edmx:Edmx>
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext.handleEvent(Unknown Source)
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.Loader.reportError(Unknown Source)
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.Loader.reportError(Unknown Source)
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.Loader.reportUnexpectedChildElement(Unknown Source)
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext$DefaultRootLoader.childElement(Unknown Source)
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext._startElement(Unknown Source)
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext.startElement(Unknown Source)
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.SAXConnector.startElement(Unknown Source)
at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.startElement(Unknown Source)
at com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.scanStartElement(Unknown Source)
at com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl$NSContentDriver.scanRootElementHook(Unknown Source)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl$FragmentContentDriver.next(Unknown Source)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl$PrologDriver.next(Unknown Source)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next(Unknown Source)
at com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.next(Unknown Source)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(Unknown Source)
at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(Unknown Source)
at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(Unknown Source)
at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(Unknown Source)
at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(Unknown Source)
at com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl$JAXPSAXParser.parse(Unknown Source)
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal0(Unknown Source)
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal(Unknown Source)
at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(Unknown Source)
at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(Unknown Source)

这很奇怪,因为我没有任何不期望的元素:(

有人有想法吗?

1 个答案:

答案 0 :(得分:0)

您可以执行以下操作:

<强>包信息

您可以使用包级别@XmlSchema注释来指定模型的命名空间限定。下面我已经指定,除非另有说明,否则所有元素都将由http://schemas.microsoft.com/ado/2007/06/edmx命名空间限定。我还指定该命名空间的首选前缀是edmx,http://schemas.microsoft.com/ado/2007/06/edmx应该是默认命名空间。

@XmlSchema(
        namespace="http://schemas.microsoft.com/ado/2007/06/edmx",
        elementFormDefault=XmlNsForm.QUALIFIED,
        xmlns={
                @XmlNs(prefix="edmx", namespaceURI="http://schemas.microsoft.com/ado/2007/06/edmx"),
                @XmlNs(prefix="", namespaceURI="http://schemas.microsoft.com/ado/2009/11/edm")
        }
)
@XmlAccessorType(XmlAccessType.FIELD)
package forum14875956;

import javax.xml.bind.annotation.*;

<强> EDMX

现在不需要在Edmx类上指定名称空间信息。

package forum14875956;

import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement(name = "Edmx")
public class Edmx {

    @XmlElement(name = "DataServices")
    private DataService dataService;

    public DataService getDataService() {
        return dataService;
    }

}

<强>的DataService

DataService类中,我们将在schema属性的映射上指定命名空间。

package forum14875956;

import javax.xml.bind.annotation.*;

public class DataService {

    @XmlElement(name = "Schema", namespace = "http://schemas.microsoft.com/ado/2009/11/edm")
    private Schema schema;

    public Schema getSchema() {
        return schema;
    }

}

<强>模式

您可以使用Schema注释覆盖@XmlType类上的属性的名称空间限定。

package forum14875956;

import javax.xml.bind.annotation.XmlType;

@XmlType(namespace="http://schemas.microsoft.com/ado/2009/11/edm")
public class Schema {

}

<强>演示

package forum14875956;

import java.io.File;
import javax.xml.bind.*;

public class Demo {

    public static void main(String[] args) throws Exception {
        JAXBContext jc = JAXBContext.newInstance(Edmx.class);

        Unmarshaller unmarshaller = jc.createUnmarshaller();
        File xml = new File("src/forum14875956/input.xml");
        Edmx edmx = (Edmx) unmarshaller.unmarshal(xml);

        Marshaller marshaller = jc.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        marshaller.marshal(edmx, System.out);
    }

}

<强> input.xml中/输出

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<edmx:Edmx xmlns:edmx="http://schemas.microsoft.com/ado/2007/06/edmx" xmlns="http://schemas.microsoft.com/ado/2009/11/edm">
    <edmx:DataServices>
        <Schema/>
    </edmx:DataServices>
</edmx:Edmx>

了解更多信息