java 我如何在不创建包装类的情况下编组 Jaxb 元素列表?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/35444507/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-03 00:09:43  来源:igfitidea点击:

How would I marshal a List of Jaxb Elements without making a wrapper class?

javaxmljaxb

提问by mike

Short of actually making up a writer and appending each element onto the string. Is there a way to get the JAXB marshaller to marshall a list of objects where I can just give it the name of the top element?

没有实际组成一个作家并将每个元素附加到字符串上。有没有办法让 JAXB 编组器编组对象列表,我可以在其中给它指定顶部元素的名称?

I feel like I'm close with this

我觉得我很接近这个

//http://blog.bdoughan.com/2012/07/jaxb-no-annotations-required.html
public <T> String jaxb(Collection<T> o, Class<T> clazz, String plural){
    try {
        ArrayList<T> al = new ArrayList<T>(o.size());
        al.addAll(o);
        JAXBContext jc = JAXBContext.newInstance(ArrayList.class);
        JAXBElement<ArrayList> amenity = new JAXBElement(new QName(plural), ArrayList.class, al);
        Marshaller marshaller = jc.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        StringWriter writer = new StringWriter();
        marshaller.marshal(amenity, writer);
        return writer.toString();
    } catch (JAXBException e) {
        throw new RuntimeException(e);
    }
}

but the result is still coming back as an empty list

但结果仍然作为空列表返回

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<pluralName/>

Is there a way to do this without just manually pasting strings of xml together?

有没有办法在不手动将 xml 字符串粘贴在一起的情况下做到这一点?

Update

更新

With some help from Michael Glavassevich I've been able to do this with one caveat, the individual elements are <Item>s

从迈克尔Glavassevich [我已一些帮助能有一点需要注意做到这一点,各个元素是<Item>小号

//http://blog.bdoughan.com/2012/07/jaxb-no-annotations-required.html
@SuppressWarnings({ "unchecked", "rawtypes" })
public <T> String jaxb(Collection<T> elements, Class<T> elementClass, String plural){
    try {
        T[] array = (T[]) Array.newInstance(elementClass, elements.size());
        elements.toArray(array);
        JAXBContext jc = JAXBContext.newInstance(array.getClass());
        JAXBElement<T[]> topElement = new JAXBElement(new QName(plural), array.getClass(), array);
        Marshaller marshaller = jc.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        StringWriter writer = new StringWriter();
        marshaller.marshal(topElement, writer);
        return writer.toString();
    } catch (JAXBException e) {
        throw new RuntimeException(e);
    }
}

The result then becomes

结果就变成了

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Basketballs>
    <item>basketball one</item>
    <item>basketball two</item>
</Basketballs>

采纳答案by Michael Glavassevich

If you don't want to create a wrapper class you could convert the collection into an array, place that array in a JAXBElementand then marshal it.

如果您不想创建包装类,您可以将集合转换为数组,将该数组放在 a 中JAXBElement,然后对其进行编组。

For example:

例如:

public class JAXBArrayWriter {

    public static class Item {
        @XmlValue
        protected String value;

        public Item() {}

        public Item(String value) {
            this.value = value;
        }
    }

    public static void main (String [] args) throws Exception {
        List<Item> items = new ArrayList<Item>();
        items.add(new Item("one"));
        items.add(new Item("two"));
        JAXBContext jc = JAXBContext.newInstance(Item[].class);
        JAXBElement<Item[]> root = new JAXBElement<Item[]>(new QName("items"), 
                Item[].class, items.toArray(new Item[items.size()]));
        Marshaller marshaller = jc.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        StringWriter writer = new StringWriter();
        marshaller.marshal(root, writer);
        System.out.println(writer.toString());
    }
}

which produces the following document:

产生以下文件:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<items>
    <item>one</item>
    <item>two</item>
</items>

回答by jenjis

Please try this:

请试试这个:

First, create a list class:

首先,创建一个列表类:

@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class AmenityList {
    @XmlElement(name = "amenity")
    List<Amenity> amenities = new ArrayList<Amenity>();

    public AmenityList() {}

    public void setList(List<Amenity> amenities) {
        this.amenities = amenities;
    }
}

then the Amenity class:

然后是 Amenity 类:

@XmlAccessorType(XmlAccessType.FIELD)
class Amenity {
    private String amenityName;
    private String amenityDate;

    public Amenity(String name, String date) {
        this.amenityName = name;
        this.amenityDate = date;
    }
}

set where needed your amenities in a list - maybe in a less redundant way :) - and assign it to an AmenityList:

在列表中设置需要您的便利设施的位置 - 可能以不那么冗余的方式:) - 并将其分配给 AmenityList:

AmenityList amenityList = new AmenityList();
List <Amenity> amenities = new ArrayList<Amenity>();
amenities.add(new Amenity("a_one", "today"));
amenities.add(new Amenity("a_two", "tomorrow"));
amenity.setList(amenities);

and finally, a toXml method:

最后,一个 toXml 方法:

public static String toXml(AmenityList amenityList) throws JAXBException {
    JAXBContext jaxbContext = JAXBContext.newInstance(AmenityList.class);
    Marshaller jaxbMarshaller = jaxbContext.createMarshaller();
    jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
    StringWriter sw = new StringWriter();
    jaxbMarshaller.marshal(amenityList, sw);
    return sw.toString()
}

obtaining, i.e. :

获得,即:

<amenityList>
    <amenity>
        <amenityName>a_one</amenityName>
        <amenityDate>today</amenityDate>
    </amenity>
    <amenity>
        <amenityName>a_two</amenityName>
        <amenityDate>tomorrow</amenityDate>
    </amenity>
</amenityList>

回答by Gonen I

The accepted solution with array works but causes each inner element to be named : < item >

接受的数组解决方案有效,但会导致每个内部元素被命名:< item >

The following solution taken from this link worked better for me:

从此链接中获取的以下解决方案对我来说效果更好:

Is it possible to programmatically configure JAXB?

是否可以以编程方式配置 JAXB?

public class Wrapper<T> {

private List<T> items = new ArrayList<T>();

@XmlAnyElement(lax=true)
public List<T> getItems() {
    return items;
}

}

}

//JAXBContext is thread safe and so create it in constructor or 
//setter or wherever:
... 
JAXBContext jc = JAXBContext.newInstance(Wrapper.class, clazz);
... 

public String marshal(List<T> things, Class clazz) {

  //configure JAXB and marshaller     
  Marshaller m = jc.createMarshaller();
  m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);

  //Create wrapper based on generic list of objects
  Wrapper<T> wrapper = new Wrapper<T>(things);
  JAXBElement<Wrapper> wrapperJAXBElement = new JAXBElement<Wrapper>(new QName(clazz.getSimpleName().toLowerCase()+"s"), Wrapper.class, wrapper);

  StringWriter result = new StringWriter();
  //marshal!
  m.marshal(wrapperJAXBElement, result);

  return result.toString();

}

It does not require converting the list to an array, but does require 1 generic general purpose class.

它不需要将列表转换为数组,但需要 1 个通用通用类。