简体   繁体   中英

How to add dynamic attribute to dynamic element in JAXB

Trying to create any element with attributes dynamically and
now able to create dynamic element without attributes, need help on add attributes to dynamically created element.

Dynamic element created bellow

  public class CustomElement {


        private  List<JAXBElement<String>> Elements;


        @XmlAnyElement
        public List<JAXBElement<String>> getElements() {
            return Elements;
        }

        public void setElements(List<JAXBElement<String>> elements) {
            Elements = elements;
        }


        public void setElements(Map<String, String>  myElements, String namespaceURI) {

               List<JAXBElement<String>> elements = new ArrayList<JAXBElement<String>>();
                for (Map.Entry<String, String> mapElement: myElements.entrySet()) 
                {               
                    JAXBElement jAXBElement=new JAXBElement(new QName(namespaceURI,mapElement.getKey()), 
                            String.class, mapElement.getValue());

                    elements.add(jAXBElement);
                }
            Elements = elements;
        }

//not working attr added to parent element not to current element
     private Map<QName, String> attr;

        @XmlAnyAttribute
        public Map<QName, String> getAttr() {
            return attr;
        }

        public void setAttr(Map<QName, String> attr) {
            this.attr = attr;
        }

    }

Setting values

 Map<String, String> myElements =new HashMap<String,String>();  

             myElements.put("connectmrf ","");  
                setElements(myElements,"www.xxxxx.xxx/xxx/vmas");

             Map<QName, String> attr=new HashMap<QName,String>();   
                attr.put(new QName("Name"),"Amit");  
                attr.put(new QName("age"),"10");  

                setAttr(attr);

Current Result :

     <state  age="10" Name="Amit">
            <vmas:connectmrf ></vmas:connectmrf >
      </state>

Expected Result : please suggest

     <state>
            <vmas:connectmrf  age="10" Name="Amit" ></vmas:connectmrf >
      </state>

Warning!: this is only a quick and dirty way for marshaling

You need to create a wrapper-class with @XmlAnyAttribute .
For example:

public class AnyXmlElement {
    @XmlAnyAttribute
    private Map<QName, String> attributes;
    @XmlAnyElement
    private List<Object> elements;

    public AnyXmlElement() {
        attributes = new LinkedHashMap<QName, String>();
        elements = new ArrayList<Object>();
    }

    public void addAttribute(QName name, String value) {
        attributes.put(name, value);
    }

    public void addElement(Object element) {
        elements.add(element);
    }
}

Ensure the dynamic name by wrapping AnyXmlElement in a JAXBElement

public static JAXBElement<AnyXmlElement> toJAXBElement(QName qName, AnyXmlElement any) {
    return new JAXBElement<AnyXmlElement>(qName, AnyXmlElement.class, any);
}

For testing we create a simple root-class

@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public static class Root {
    @XmlAnyElement
    public List<Object> any;
}

and the program

public static void main(String[] args) throws Exception {
    AnyXmlElement any = new AnyXmlElement();
    any.addAttribute(new QName("bar"), "hello");

    Root root = new Root();
    root.any = Arrays.asList(toJAXBElement(new QName("foo"), any));
    // It's important to add AnyXmlElement.class here
    JAXBContext jc = JAXBContext.newInstance(Root.class, AnyXmlElement.class);
    Marshaller m = jc.createMarshaller();
    m.marshal(root, System.out);
}

This is the generated xml:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?><root><foo bar="hello world"/></root>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM