首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >Java/JAXB:将XML属性解组为特定的Java对象属性

Java/JAXB:将XML属性解组为特定的Java对象属性
EN

Stack Overflow用户
提问于 2010-07-20 04:28:18
回答 2查看 28.9K关注 0票数 22

有一个丑陋的XML文件必须被解组:

<?xml version="1.0" ?>
<configuration>
    <section name="default_options">
        <value name="default_port">8081</value>
        <value name="log_level">WARNING</value>
    </section>
    <section name="custom_options">
        <value name="memory">64M</value>
        <value name="compatibility">yes</value>
    </section>
</configuration>

生成的Java对象应为:

public class DefaultOptions {
    private int defaultPort;
    private String logLevel;
    // etc...
}

public class CustomOptions {
    private String memory;
    private String compatibility;
    // etc...
}

This问题的答案非常接近,但我想不出最终的解决方案。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2010-07-20 22:10:31

怎么样?

引入一个名为Options的通用超类:

import javax.xml.bind.annotation.XmlAttribute;

public abstract class Options {

    private String name;

    @XmlAttribute
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

}

然后,在具有选项列表(本例中为Configuration)的类上,在该属性上指定一个@XmlJavaTypeAdapter:

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

import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;

@XmlRootElement
public class Configuration {

    private List<Options> section = new ArrayList<Options>();

    @XmlJavaTypeAdapter(OptionsAdapter.class)
    public List<Options> getSection() {
        return section;
    }

    public void setSection(List<Options> section) {
        this.section = section;
    }

}

XmlAdapter将如下所示:

import javax.xml.bind.annotation.adapters.XmlAdapter;

public class OptionsAdapter extends XmlAdapter<AdaptedOptions, Options> {

    @Override
    public Options unmarshal(AdaptedOptions v) throws Exception {
        if("default_options".equals(v.name)) {
            DefaultOptions options = new DefaultOptions();
            options.setName(v.getName());
            options.setDefaultPort(Integer.valueOf(v.map.get("default_port")));
            options.setLogLevel(v.map.get("log_level"));
            return options;
        } else {
            CustomOptions options = new CustomOptions();
            options.setName(v.getName());
            options.setCompatibility(v.map.get("compatibility"));
            options.setMemory(v.map.get("memory"));
            return options;
        }
    }

    @Override
    public AdaptedOptions marshal(Options v) throws Exception {
        AdaptedOptions adaptedOptions = new AdaptedOptions();
        adaptedOptions.setName(v.getName());
        if(DefaultOptions.class == v.getClass()) {
            DefaultOptions options = (DefaultOptions) v;
            adaptedOptions.map.put("default_port", String.valueOf(options.getDefaultPort()));
            adaptedOptions.map.put("log_level", options.getLogLevel());
        } else {
            CustomOptions options = (CustomOptions) v;
            adaptedOptions.map.put("compatibility", options.getCompatibility());
            adaptedOptions.map.put("memory", options.getMemory());
        }
        return adaptedOptions;
    }

}

AdaptedOptions看起来像这样:

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlValue;

public class AdaptedOptions extends Options {

    @XmlAttribute String name;
    @XmlElement List<Value> value = new ArrayList<Value>();
    Map<String, String> map = new HashMap<String, String>();

    public void beforeMarshal(Marshaller marshaller) {
        for(Entry<String, String> entry : map.entrySet()) {
            Value aValue = new Value();
            aValue.name = entry.getKey();
            aValue.value = entry.getValue();
            value.add(aValue);
        }
    }

    public void afterUnmarshal(Unmarshaller unmarshaller, Object parent) {
        for(Value aValue : value) {
            map.put(aValue.name, aValue.value);
        }
    }

    private static class Value {
        @XmlAttribute String name;
        @XmlValue String value;
    }

}
票数 21
EN

Stack Overflow用户

发布于 2010-07-20 05:53:54

您可以创建一个单独的类来表示XML的结构:

public class Section {
    @XmlAttribute
    public String name;
    @XmlElement(name = "value")
    public List<Value> values;
}

public class Value {
    @XmlAttribute
    public String name;
    @XmlValue
    public String value;
}

然后使用XmlAdapter执行转换:

public class OptionsAdapter extends XmlAdapter<Section, Options> {
    public Options unmarshal(Section s) {
        if ("default_options".equals(s.name)) {
            ...
        } else if (...) {
            ...
        }
        ...
    }
    ...
}

@XmlElement
public class Configuration {
    @XmlElement(name = "section")
    @XmlJavaTypeAdapter(OptionsAdapter.class)
    public List<Options> options;
}

public class DefaultOptions extends Options { ... }
public class CustomOptions extends Options { ... }
票数 8
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/3284786

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档