parse online jaxbcontext bean java xml jaxb

online - parse xml java jaxb



Java/JAXB: Unmarshall atributos de XML a atributos de objeto Java específicos (2)

Hay un archivo XML feo que tiene que ser improvisado:

<?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>

Los objetos de Java resultantes deben ser:

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

La respuesta de esta pregunta es muy cercana, pero no puedo encontrar la solución final.


¿Qué tal si?

Presente una súper clase común llamada Opciones:

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; } }

Luego, en su clase con la lista de opciones (Configuración en este ejemplo), especifique un @XmlJavaTypeAdapter en esa propiedad:

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; } }

El XmlAdapter se verá algo así:

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 se ve como:

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; } }


Puede crear una clase separada para representar la estructura de su 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; }

y luego use un XmlAdapter para realizar la conversión:

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 { ... }