Mark W
Mark W

Reputation: 2803

Dynamically assign attribute name in SimpleXML (java)

I have the following class:

import org.simpleframework.xml.Attribute;
import org.simpleframework.xml.Root;

@Root(name="PickLineXtra")
public class PickXtra {
    private final String key;   
    @Attribute(name=this.key)
    private String value;

    public PickXtra(String key, String value) {
        this.key = key;
        this.value = value;
    }
}

This code does not compile. Specifically I'm trying to assign the name of the XML attribute dynamically, but annotations require constant expressions for assignment of their properties. Is there a way to accomplish this in simple XML?

Upvotes: 3

Views: 1092

Answers (1)

ollo
ollo

Reputation: 25370

Is there a way to accomplish this in simple XML?

yes, and not a difficult one: implement a Converter.

PickXtra class incl. it's Converter

@Root(name = "PickLineXtra")
@Convert(PickXtra.PickXtraConverter.class)
public class PickXtra
{
    private final String key;
    private String value;

    public PickXtra(String key, String value)
    {
        this.key = key;
        this.value = value;
    }


    public String getKey()
    {
        return key;
    }

    public String getValue()
    {
        return value;
    }

    @Override
    public String toString()
    {
        return "PickXtra{" + "key=" + key + ", value=" + value + '}';
    }


    /* 
     * !===> This is the actual part <===!
     */
    static class PickXtraConverter implements Converter<PickXtra>
    {
        @Override
        public PickXtra read(InputNode node) throws Exception
        {
            /*
             * Get the right attribute here - for testing the first one is used.
             */
            final String attrKey = node.getAttributes().iterator().next();
            final String attrValue = node.getAttribute(attrKey).getValue();

            return new PickXtra(attrKey, attrValue);
        }

        @Override
        public void write(OutputNode node, PickXtra value) throws Exception
        {
            node.setAttribute(value.key, value.getValue());
        }
    }
}

I've added getter and toString() for testing purposes. The actual parts are:

  1. @Convert(PickXtra.PickXtraConverter.class) - set the converter
  2. static class PickXtraConverter implements Converter<PickXtra> { ... } - the implementation

Testing

/* Please note the 'new AnnotationStrategy()' - it's important! */
final Serializer ser = new Persister(new AnnotationStrategy());

/* Serialize */
PickXtra px = new PickXtra("ExampleKEY", "ExampleVALUE");
ser.write(px, System.out);

System.out.println("\n");

/* Deserialize */
final String xml = "<PickLineXtra ExampleKEY=\"ExampleVALUE\"/>";
PickXtra px2 = ser.read(PickXtra.class, xml);

System.out.println(px2);

Result

<PickLineXtra ExampleKEY="ExampleVALUE"/>

PickXtra{key=ExampleKEY, value=ExampleVALUE}

Upvotes: 2

Related Questions