views:

87

answers:

3

I want to be able to alias the root list element depending upon what type of objects are contained in the list. For example, this is my current output:

<list>
<coin>Gold</coin>
<coin>Silver</coin>
<coin>Bronze</coin>
</list>

And this is what I want it to look like:

<coins>
<coin>Gold</coin>
<coin>Silver</coin>
<coin>Bronze</coin>
</coins>

I can do this at a global level by saying all lists should be aliased to coins, but I have a lot of different lists and this won't work. Any ideas on how to do this? Seems like it should be simple, but of course, it isn't.

EDIT: I should specify, I am trying to serialize objects to xml. I am using Spring 3 MVC as my web framework.

A: 

You could use XMLTask for ant. Using this you can rename a list that you identify with an XPath like this:

<rename path="list[coin]" to="coins"/>
tangens
Ant is a build tool, this wouldn't be appropriate. Also, doing something like this would prevent xStream from being able to deserialize from the modified file
gregcase
+1  A: 

This isn't an ideal solution, as it requires a separate wrapper class, but you could do something like this:

public class CoinResponse {

   private List<Coin> coinList;

   public CoinResponse(List<Coin> coinList) {
      this.coinList = coinList;
   }

   public List<Coin> getCoins() {
      return this.coinList;
   }
}

And here's the ugly part:

List<Coin> coins = Arrays.asList( new Coin(), new Coin(), new Coin());
CoinResponse response = new CoinResponse(coins);

XStream xstream = new XStream();
xstream.alias( "coins", CoinResponse.class );
xstream.addImplicitCollection( CoinResponse.class, "coinList" );

System.out.println(xstream.toXML(response));

Basically, this is telling Xstream to use "coins" when converting the CoinResponse, and then don't use any name at all for the list itself.

gregcase
I just noticed something. If you use Arrays.asList() as I did above, my approach won't work. Instead, you need to always pass in an ArrayList, or the CoinResponse constructor should wrap the list parameter into a new ArrayList().
gregcase
+2  A: 

Let's say you have a Coin class with a type attribute, as follows:

@XStreamAlias("coin")
public class Coin {
    String type;
}

And you have a Coins class that constains a List of Coin:

@XStreamAlias("coins")
public class Coins{

    @XStreamImplicit
    List<Coin> coins = new ArrayList<Coin>();
}

Pay attention to the annotations. The List is Implicit and the Coins class will be shown as "coins".

The output will be:

<coins>
  <coin>
    <type>Gold</type>
  </coin>
  <coin>
    <type>Silver</type>
  </coin>
  <coin>
    <type>Bronze</type>
  </coin>
</coins>

It's not the same you asked for, but there is a reason.

At first, coin have only one attribute, but we are not sure if all objects you want to show do have only one attribute too. So, we need to tell which object attribute we are talking about.

You can also show the Coin attributes as XML Attributes, not fields. As follows:

@XStreamAlias("coin")
public class Coin {
    @XStreamAsAttribute
    String type;

    Coin(String type) {
        this.type = type;
    }
}

Here is the output:

<coins>
  <coin type="Gold"/>
  <coin type="Silver"/>
  <coin type="Bronze"/>
</coins>

Hope it helps.

pablosaraiva