Was unable to find the solution even after trying many things so posting here hoping to get some workaround or fix for this issue.
Basically, if the
@XmlPath(".") has been used on a `Map` and if there is `XMLAdapter` on it then it fails during the `unmarshalling`. The `marshaling` works perfectly only the `unmarshalling` fails.
In short, I would like to perform the `unmarshalling` [as mentioned here][1] but along with `Map` I will have one more `@XmlElement`. So one field is annotated with `(Map field) @XmlPath(".")` and another String field with `@XmlElement` and then I would like to perform `unmarshalling`.
[1]: http://blog.bdoughan.com/2013/06/moxys-xmlvariablenode-using-maps-key-as.html
[2]: https://stackoverflow.com/q/27765087/7584240
What I have tried:
Following is the `XML` that I am trying to `unmarshal`:
```
<pre lang="XML"><Customer xmlns:google="https://google.com">
<name>Batman</name>
<age>2008</age>
<google:sub1>MyValue-1</google:sub1>
<google:sub2>MyValue-1</google:sub2>
</Customer>
```
Following is the `Customer.class` to which it will be `unmarshalled`:
@XmlRootElement(name = "Customer")
@XmlType(name = "Customer", propOrder = {"name", "age", "userExtensions"})
@XmlAccessorType(XmlAccessType.FIELD)
@NoArgsConstructor
@Getter
@Setter
@AllArgsConstructor
public class Customer extends Person {
private String name;
private String age;
@XmlPath(".")
@XmlJavaTypeAdapter(TestAdapter.class)
@XmlAnyElement
private Map<String, Object> userExtensions = new HashMap<>();
}
Following is the `Main` class which will `unmarshal`:
public class Unmarshalling {
public static void main(String[] args)
throws JAXBException, XMLStreamException, FactoryConfigurationError, IOException, URISyntaxException, ProcessingException {
final InputStream inputStream = Unmarshalling.class.getClassLoader().getResourceAsStream("customer.xml");
final XMLStreamReader xmlStreamReader = XMLInputFactory.newInstance().createXMLStreamReader(inputStream);
final JAXBContext jaxbContext = JAXBContext.newInstance(Customer.class);
final Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
final Customer customer = unmarshaller.unmarshal(xmlStreamReader, Customer.class).getValue();
System.out.println("Read XML : " + customer);
}
}
When I run this code I will get the output as:
Read XML : Person(name=Rise Against, age=2000)
Its not reading the `custom` elements such as `google:sub1` and `google:sub2`.
1. There is one more [issue similar to this][2] but the workaround mentioned there did not work for me.
2. I tried the `@XmlAnyElement(lax=true)` on `MAP` even that did not work for me.
Following is the `TestAdapter` that I am using for `marshalling` and `unmarhsalling` the `Map<string,object>`
public class TestAdapter extends XmlAdapter<Wrapper, Map<String, Object>> {
@Override
public Map<String, Object> unmarshal(Wrapper value) throws Exception {
System.out.println("ADAPTER UNMARSHALLING");
System.out.println(value.getElements());
if (value == null) {
return null;
}
final Map<String, Object> extensions = new HashMap<>();
for (Object obj : value.getElements()) {
Element element = (Element) obj;
final NodeList children = element.getChildNodes();
if (children.getLength() == 1) {
extensions.put(element.getNodeName(), element.getTextContent());
} else {
List<Object> child = new ArrayList<>();
for (int i = 0; i < children.getLength(); i++) {
final Node n = children.item(i);
if (n.getNodeType() == Node.ELEMENT_NODE) {
Wrapper wrapper = new Wrapper();
List childElements = new ArrayList();
childElements.add(n);
wrapper.elements = childElements;
child.add(unmarshal(wrapper));
}
}
extensions.put(element.getNodeName(), child);
}
}
return extensions;
}
@SuppressWarnings("unchecked")
@Override
public Wrapper marshal(Map<String, Object> v) throws Exception {
if (v == null) {
return null;
}
Wrapper wrapper = new Wrapper();
List elements = new ArrayList();
for (Map.Entry<String, Object> property : v.entrySet()) {
if (property.getValue() instanceof Map) {
elements.add(new JAXBElement<Wrapper>(new QName(property.getKey()), Wrapper.class, marshal((Map) property.getValue())));
} else {
elements.add(new JAXBElement<String>(new QName(property.getKey()), String.class, property.getValue().toString()));
}
}
wrapper.elements = elements;
return wrapper;
}
}
class Wrapper {
@XmlAnyElement
List elements;
public List getElements() {
return elements;
}
I tried many things but nothing worked till now. Can someone please have a look at this issue and provide your solution. Happy to provide any more info with regards to this issue as I have spent nearly 10 days looking for answers.
I tried following things:
1. Created one more variable and tried to use it only during unmarshalling but that's also failing.
2. Tried to create one more field then used the `@XmlAnyElement` on it but that's also not working as I expected.
Tried few more things but nothing helped.
Everything is failing. I tried to debug the code from `MOXY` but I am unable to follow many things there. Any help with this issue would be really helpful for me.