Original Question: So I've got a big excel sheet that has a bunch of labels with values attached to them, think Party_Name being the label with "IBM" being the value in that specific cell. I've read them all into a HashMap, with the key being the label and the value being the value of the cell (both of type String). Thing is, I want to be able to bind each as a XML tag so that it'll display in a web browser when I point it to the specific path of a Party. Is it possible to set these xml element dynamically because it'd a pain to statically make the 100+ tags?
Update: I've been able read all the labels/values of an excel sheet into a HashMap and then convert that to an AdaptedMap that allows one to display the values/keys for each of the entries in the hashpmap dynamically. Thing is it's ugly, the format is currently like so
<Party>
<entry>
<key> PARTY_NAME> </key>
<value> IBM </value>
</entry>
<entry>
<key> id </key>
<value> 123456 </value>
...etc
I'd like to format it so that is more like so
<Party>
<entry>
<PARTY_NAME> IBM </PARTY_NAME>
</entry>
<entry>
<id> 123456 </id>
etc...
Or even get rid of the "entry" tags. Anyone know a way to do so? Here's my relevant code:
package pojo;
import java.util.HashMap;
import java.util.Map;
import java.io.File;
import javax.xml.bind.*;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlRootElement;
import org.eclipse.persistence.jaxb.MarshallerProperties;
@XmlRootElement(name="Party")
@XmlAccessorType(XmlAccessType.FIELD)
public class Party {
HashMap <String,String> partyInfo = new HashMap<String,String>();
public HashMap<String,String> getPartyInfo() throws Exception
{
MapAdapter adapter = new MapAdapter();
adapter.marshal(partyInfo);
return partyInfo;
}
And here's the class that I took from my previous question involving the same problem (link at bottom of page)
package pojo;
import java.util.*;
import java.util.Map.Entry;
import javax.xml.bind.annotation.*;
import javax.xml.bind.annotation.adapters.XmlAdapter;
import org.eclipse.persistence.oxm.annotations.XmlVariableNode;
public class MapAdapter extends XmlAdapter<MapAdapter.AdaptedMap, Map<String, String>>{
public static class AdaptedMap
{
@XmlVariableNode("key")
List<AdaptedEntry> entries = new ArrayList<AdaptedEntry>();
}
public static class AdaptedEntry
{
@XmlTransient
public String key;
@XmlValue
public String value;
}
@Override
public AdaptedMap marshal(Map<String,String> map) throws Exception
{
AdaptedMap adaptedMap = new AdaptedMap();
for(Entry<String, String> entry : map.entrySet())
{
AdaptedEntry adaptedEntry = new AdaptedEntry();
adaptedEntry.key= entry.getKey();
adaptedEntry.value=entry.getValue();
adaptedMap.entries.add(adaptedEntry);
}
return adaptedMap;
}
Note: I'm new here so I'm not sure about the etiquette when following up a previous question. In any case here's the link for the original question
How to set xml annotations dynamically?
Note 2: I'm pretty nooby with xml annotations so if anything is glaringly wrong it's because some of it I've been copying rather than understanding logically. I've tried reading the javadocs on it but it's not entirely clear, might stem from my lack of experience with xml as well
Below is the corrected example.
Java Model (Party)
The @XmlJavaTypeAdapter
annotation is used to reference the XmlAdapter
implementation class. We will also use MOXy's @XmlPath
annotation to eliminate a parent element being required (see: http://blog.bdoughan.com/2010/07/xpath-based-mapping.html).
package pojo;
import java.util.HashMap;
import javax.xml.bind.annotation.*;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
import org.eclipse.persistence.oxm.annotations.XmlPath;
@XmlRootElement(name = "Party")
@XmlAccessorType(XmlAccessType.FIELD)
public class Party {
@XmlPath(".")
@XmlJavaTypeAdapter(MapAdapter.class)
HashMap<String, String> partyInfo = new HashMap<String, String>();
}
XmlAdapter (MapAdapter)
An XmlAdapter
lets you convert an object to a different type for the purposes of marshalling/unmarshalling. In this example we will use it to convert a Map
to an object structure that is able to leverage MOXy's @XmlVariableNode
extension (see: http://blog.bdoughan.com/2013/06/moxys-xmlvariablenode-using-maps-key-as.html). @XmlVariableNode
enables you to derive the node name from a field/property on the object.
package pojo;
import java.util.*;
import java.util.Map.Entry;
import javax.xml.bind.annotation.*;
import javax.xml.bind.annotation.adapters.XmlAdapter;
import org.eclipse.persistence.oxm.annotations.XmlVariableNode;
public class MapAdapter extends
XmlAdapter<MapAdapter.AdaptedMap, Map<String, String>> {
public static class AdaptedMap {
@XmlVariableNode("key")
List<AdaptedEntry> entries = new ArrayList<AdaptedEntry>();
}
public static class AdaptedEntry {
@XmlTransient
public String key;
@XmlValue
public String value;
}
@Override
public AdaptedMap marshal(Map<String, String> map) throws Exception {
AdaptedMap adaptedMap = new AdaptedMap();
for (Entry<String, String> entry : map.entrySet()) {
AdaptedEntry adaptedEntry = new AdaptedEntry();
adaptedEntry.key = entry.getKey();
adaptedEntry.value = entry.getValue();
adaptedMap.entries.add(adaptedEntry);
}
return adaptedMap;
}
@Override
public Map<String, String> unmarshal(AdaptedMap adaptedMap)
throws Exception {
List<AdaptedEntry> adaptedEntries = adaptedMap.entries;
Map<String, String> map = new HashMap<String, String>(
adaptedEntries.size());
for (AdaptedEntry adaptedEntry : adaptedEntries) {
map.put(adaptedEntry.key, adaptedEntry.value);
}
return map;
}
}
jaxb.properties
To specify MOXy as your JAXB provider you need to include a file called jaxb.properties
in the same package as your domain model with the following entry (see: http://blog.bdoughan.com/2011/05/specifying-eclipselink-moxy-as-your.html).
javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory
Demo
package pojo;
import java.io.File;
import javax.xml.bind.*;
public class Demo {
public static void main(String[] args) throws Exception {
JAXBContext jc = JAXBContext.newInstance(Party.class);
Unmarshaller unmarshaller = jc.createUnmarshaller();
File xml = new File("src/pojo/input.xml");
Party party = (Party) unmarshaller.unmarshal(xml);
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(party, System.out);
}
}
input.xml/Output
Below is the input to and output from running the demo code.
<?xml version="1.0" encoding="UTF-8"?>
<Party>
<id> 123456 </id>
<PARTY_NAME> IBM </PARTY_NAME>
</Party>
For More Information