1

I am using Retrofit and SimpleXMLConverter to get and deserialize an XML file. I am converting an attribute to type long. It would work fine if the attribute wasn´t sometimes "", aka empty.

I tried using

@Attribute(empty="-1")

for the cases this attribute should be empty, so it should return "-1" but it does not do so. Is the usage of this empty attribute correct?

IMSoP
  • 89,526
  • 13
  • 117
  • 169
vandus
  • 3,248
  • 3
  • 30
  • 44

2 Answers2

1

It would work fine if the attribute wasn´t sometimes "", aka empty.

This is not correct here: The attributes value - seen as string - is not empty in the meaning of missing or "nothing", it's an empty string.

Here's an example:

XML:

<root value=""></root>

Java class:

@Root(name = "root")
public class Example
{
    @Attribute(name = "value", empty = "-1", required = false)
    private long value;


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

This throws - and that's reasonable - a NumberFormatException. If you replace the type of value with String you wont catch an exception, value is set as an empty string (""). On the other hand, keeping string type but removing the attribute in XML will set "-1" as value (that's why required = false is used). Now the Serializer can't find any value and therefore sets the default one.

You could handle this in your class internally, like let the corresponding getter-method return -1 in case of an empty string:

public long getValue()
{
    if( value == null || value.isEmpty() == true )
    {
        return -1;
    }

    return Long.valueOf(value);
}

(Don't forget to change your code according this - in my example you have to change toString()-method)

But there's a better solution: Simple allows you to implement custom Transformer for any types (don't mix with Converter!). With these you can implement type -> String (write) and String -> type (read) as you need.

Based on my example above, here's an implementation:

public class LongTransformer implements Transform<Long>
{
    // Default value which is set if no / empty input is available
    private final long defaultValue;


    public LongTransformer(long defaultValue)
    {
        this.defaultValue = defaultValue;
    }

    public LongTransformer()
    {
        this(-1); // Just in case you always have -1 as default
    }



    @Override
    public Long read(String value) throws Exception
    {
        // If there's no or an empty String the default value is returned
        if( value == null || value.isEmpty() == true )
        {
            return defaultValue; // 
        }

        return Long.valueOf(value); // Return the value
    }


    @Override
    public String write(Long value) throws Exception
    {
        /*
         * Nothing special here. In case you you need a empty string if
         * value = -1, you can do it here.
         */
        return value.toString();
    }
}

And finally a example how to use. The key parts are between the two lines:

final String xml = "<root value=\"\">\n"
                 + "</root>";

// ---------------------------------------------------------------------
final LongTransformer numberTransformer = new LongTransformer(-1);

RegistryMatcher m = new RegistryMatcher();
m.bind(long.class, numberTransformer);

Serializer ser = new Persister(m);
// ---------------------------------------------------------------------

Example root = ser.read(Example.class, xml);
System.out.println(root);

Output:

Example{value=-1}
ollo
  • 24,797
  • 14
  • 106
  • 155
  • What if it was test Hou would you get the "test" string? – edoardotognoni Jan 27 '15 at 08:36
  • You can use the [`@Text`](http://simple.sourceforge.net/download/stream/doc/javadoc/); see [here](http://simple.sourceforge.net/download/stream/doc/tutorial/tutorial.php#text) for an example. – ollo Jan 27 '15 at 16:33
0

@vandus, here is what I did so far: I created an adapter in the Main onCreate class, the Model that I pass in as a List is the root node of the XML file:http://www.w3schools.com//xml/simple.xml

      RestAdapter restAdapter = new RestAdapter.Builder()
                .setEndpoint("http://www.w3schools.com")
                .setConverter(new SimpleXMLConverter())
                .build();

            GitHubService foodService = restAdapter.create(GitHubService.class);
            List<BreakfastMenu> repos = foodService.getFile();
            repos.toString();



public interface GitHubService
  {
    @GET("/xml/simple.xml")
    List<BreakfastMenu> getFile();
  }
greenspand
  • 749
  • 2
  • 8
  • 15
  • Could you please create a new, separate, question for your problem? The original question is not related to your problem. I'll answer you there. Just add a comment here about where I can find it. – vandus Aug 19 '14 at 12:13
  • Hi. The question is here: http://stackoverflow.com/questions/25380280/how-to-use-retrofit-and-simlpexml-together-in-parsing-and-downloading-an-xml-fil – greenspand Aug 19 '14 at 12:36