java - JAXB - 解码 XML 文件

标签 java xml jaxb

我尝试使用以下结构解码 xml 文件:

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="map">
    <xs:complexType>
        <xs:sequence>
            <xs:element name="country" maxOccurs="unbounded">
                <xs:complexType>
                    <xs:sequence>
                        <xs:element name="name" type="xs:string" />
                        <xs:element name="x" type="xs:integer" />
                        <xs:element name="y" type="xs:integer" />
                    </xs:sequence>
                </xs:complexType>
            </xs:element>
        </xs:sequence>
        <xs:attribute name="name" type="xs:string" use="required" />
    </xs:complexType>
</xs:element>

一个例子是:

<?xml version="1.0" encoding="UTF-8"?>

<map name="usa" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="field.xsd">
<country>
    <name>Test1</name>
    <x>110</x>
    <y>20</y>
</country>
<country>
    <name>Test2</name>
    <x>200</x>
    <y>30</y>
</country>
<country>
    <name>Test3</name>
    <x>350</x>
    <y>80</y>
</country>
</map>

我创建了以下类来执行此操作:

package game.view.gui;

public class ObjectFactory {

    public ObjectFactory() {
    }

    public Map createMap() {
        return new Map();
    }
}

package game.view.gui;

import java.util.ArrayList;
import java.util.List;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;

@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement( name = "map" )
public class Map {
@XmlAttribute
private String name;
private List<Country> countries = new ArrayList<Country>();

@XmlElement( name = "country" )
public List<Country> getCountries() {
    return countries;
}

public void setCountries( List<Country> countries ) {
    this.countries = countries;
}
}

package game.view.gui;

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

@XmlRootElement(name = "country")
public class Country {
    @XmlElement(required = true)
    private String name;
    @XmlElement(required = true)
    private int x;
    @XmlElement(required = true)
    private int y;

    public String getName() {
        return name;
    }

    public int getX() {
        return x;
    }

    public int getY() {
        return y;
    }
}

我总是遇到异常,其中 xml 似乎不适合创建的 pojo。我尝试按照我读过的教程进行同样的操作。异常出现在这行代码中:

 Map map = (Map) unmarsh.unmarshal(file);

你能告诉我需要在 pojo 中进行哪些更改才能一切正常吗?

编辑1: 异常(exception):

javax.xml.bind.UnmarshalException: unexpected element (uri:"", local:"map"). Expected elements are (none)
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)
at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(Unknown Source)
at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(Unknown Source)

最佳答案

当您创建 JAXBContext (用于创建编码器和解码器实例)时,您需要传递架构的根类 - 通常它们会被标记为 @ XmlType 和/或 @XmlRootElement — 以便上下文知道它正在使用哪些类。它不会做的是扫描类路径上的所有类,以防它们可能有相关的内容要说;那会非常昂贵!

实际上,改变:

JAXBContext.newInstance();

至:

JAXBContext.newInstance(Map.class);

您可能还需要在注释中显式指定 namespace 映射(到空 namespace )(例如,通过 @XmlRootElement 注释的 namespace 字段),我发现调试 JAXB 上下文的最简单方法通常是生成它们通过 generateSchema 方法编码的模式(使用虚拟输出解析器,这只会导致它们转储到 System.出...)

关于java - JAXB - 解码 XML 文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20314046/

相关文章:

java - Servlet 和映射名称

java - 匹配具有相同名称但不同子值的标签

java - 当属性名称为 ="value"时,将 xsd 转换为 java pojo 时出现问题

java - 无法解码 SOAP 错误

namespaces - java 6 中的 JAXB 未在编码的 XML 文件中添加正确的命名空间前缀

java - 在 Guice 中为 Map 注入(inject)编写单元测试

java - jpopupmenu menuitem actionperformed 未触发

java - Android xml 属性以编程方式

java - 在 Spring 框架中,从数据库中获取保存的实体以与修改后的未保存实体进行比较

java - 我可以存储和读取 STOMP 队列/主题中的消息吗?