Click here to Skip to main content
15,884,353 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
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`:
Java
@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`:
Java
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:
Java
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>`
Java
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;
    }

    //Loop across all elements within ILMD tag
    final Map<String, Object> extensions = new HashMap<>();
    for (Object obj : value.getElements()) {
      Element element = (Element) obj;

      //System.out.println("Node Name : " + element.getNodeName() + " Value : " + element.getTextContent());

      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.
Posted

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900