views:

30

answers:

2

I have a class that resembles something like this:

class foo {
    List<String> bar;
    ...
}

I add four Strings to the list bar:

bar.add("1");
bar.add("2");
bar.add("3");
bar.add("4");

Using xstream, I've managed to get output that looks like this:

<foo>
  <bar>
     <blah>1</blah>
     <blah>2</blah>
     <blah>3</blah>
     <blah>4</blah>
  </bar>
</foo>

However, I need XML that looks like this:

<foo>
  <bar>
     <blah id="1"/>
     <blah id="2"/>
     <blah id="3"/>
     <blah id="4"/>
     ...
  </bar>
</foo>

Can anybody help me with this?

A: 

In case this isn't supported by XStream, it can be done using MOXy JAXB. You will need to use the @XmlPath annotation:

import java.util.List;
import javax.xml.bind.annotation.*;
import org.eclipse.persistence.oxm.annotations.XmlPath;

@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
class Foo {
    @XmlPath("bar/blah/@id")
    List<String> bar; 
}

You can produce the following XML:

<?xml version="1.0" encoding="UTF-8"?>
<foo>
   <bar>
      <blah id="1"/>
      <blah id="2"/>
      <blah id="3"/>
      <blah id="4"/>
   </bar>
</foo>

With this demo code:

import java.util.ArrayList;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;

public class Demo {

    public static void main(String[] args) throws Exception {
        JAXBContext jc = JAXBContext.newInstance(Foo.class);

        Foo foo = new Foo();
        foo.bar = new ArrayList<String>();
        foo.bar.add("1"); 
        foo.bar.add("2"); 
        foo.bar.add("3"); 
        foo.bar.add("4"); 

        Marshaller marshaller = jc.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        marshaller.marshal(foo, System.out);
    }
}

For more information see:

Blaise Doughan
Thanks for your answer. I did manage to get my desired output with the XStream `CollectionConverter`.
pingping
+1  A: 

You can get the output you want by doing the following:

1: Create the Blah class, unless you want all Strings to behave show as attributes.

@XStreamAlias("blah")
public class Blah {
    @XStreamAsAttribute
    String id;

    Blah(){};

    Blah(String s) {
    this.id = s;
    }
}

2: Your foo has a collection of blahs

@XStreamAlias("foo")
public class Foo {
    List<Blah> bar = new ArrayList<Blah>();
} 

3: Tell XStream to process the annotations

XStream xstream = new XStream();
xstream.processAnnotations(Foo.class);
xstream.processAnnotations(Blah.class);
System.out.println(xstream.toXML(f));

4: That's the output:

<foo>
  <bar>
    <blah id="1"/>
    <blah id="2"/>
    <blah id="3"/>
    <blah id="4"/>
  </bar>
</foo>
pablosaraiva
Thank you for showing me this way of processing xstream. I wasn't aware of its support for annotations. I'll try this way out too.
pingping
You're welcome!
pablosaraiva