Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/xml/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何在不创建包装器类的情况下封送Jaxb元素列表?_Java_Xml_Jaxb - Fatal编程技术网

Java 如何在不创建包装器类的情况下封送Jaxb元素列表?

Java 如何在不创建包装器类的情况下封送Jaxb元素列表?,java,xml,jaxb,Java,Xml,Jaxb,除了组成一个writer并将每个元素附加到字符串之外。有没有一种方法可以让JAXB marshaller整理一个对象列表,让我只给它一个顶级元素的名称 我觉得我已经接近了 //http://blog.bdoughan.com/2012/07/jaxb-no-annotations-required.html public <T> String jaxb(Collection<T> o, Class<T> clazz, String plural){ t

除了组成一个writer并将每个元素附加到字符串之外。有没有一种方法可以让JAXB marshaller整理一个对象列表,让我只给它一个顶级元素的名称

我觉得我已经接近了

//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);
    }
}
//http://blog.bdoughan.com/2012/07/jaxb-no-annotations-required.html
公共字符串jaxb(集合o,类clazz,字符串复数){
试一试{
ArrayList al=新的ArrayList(o.size());
艾德尔(o);
JAXBContext jc=JAXBContext.newInstance(ArrayList.class);
JAXBElement礼仪=新的JAXBElement(新的QName(复数),ArrayList.class,al);
Marshaller=jc.createMarshaller();
setProperty(marshaller.JAXB_格式化的_输出,true);
StringWriter编写器=新的StringWriter();
马歇尔(礼仪,作家);
返回writer.toString();
}捕获(JAXBEException e){
抛出新的运行时异常(e);
}
}
但结果仍然是一张空名单

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

有没有一种方法不需要手动将xml字符串粘贴在一起就可以做到这一点

更新 在Michael Glavassevich的帮助下,我已经能够做到这一点,但需要注意的是,单个元素是
s

//http://blog.bdoughan.com/2012/07/jaxb-no-annotations-required.html
@SuppressWarnings({“unchecked”,“rawtypes”})
公共字符串jaxb(集合元素,类elementClass,字符串复数){
试一试{
T[]数组=(T[])array.newInstance(elementClass,elements.size());
元素。toArray(数组);
JAXBContext jc=JAXBContext.newInstance(array.getClass());
JAXBElement topElement=new-JAXBElement(新的QName(复数),array.getClass(),array);
Marshaller=jc.createMarshaller();
setProperty(marshaller.JAXB_格式化的_输出,true);
StringWriter编写器=新的StringWriter();
marshaller.Marshall(topElement,writer);
返回writer.toString();
}捕获(JAXBEException e){
抛出新的运行时异常(e);
}
}
结果就是

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

篮球一号
篮球二号
请尝试以下操作:

首先,创建一个列表类:

@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;
    }
}
在列表中设置所需的便利设施(可能以较少冗余的方式:)-并将其分配给便利设施列表:

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);
获得,即:

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

一个
今天
a_2
明天

如果不想创建包装类,可以将集合转换为数组,将该数组放入
JAXBElement
中,然后封送它

例如:

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());
    }
}
公共类JAXBarryWriter{
公共静态类项{
@XmlValue
保护字符串值;
公共项(){}
公共项(字符串值){
这个值=值;
}
}
公共静态void main(字符串[]args)引发异常{
列表项=新建ArrayList();
项目。添加(新项目(“一”);
增加(新项目(“两”);
JAXBContext jc=JAXBContext.newInstance(Item[].class);
JAXBElement root=新的JAXBElement(新的QName(“项”),
Item[].class,items.toArray(新项[items.size()]);
Marshaller=jc.createMarshaller();
setProperty(marshaller.JAXB_格式化的_输出,true);
StringWriter编写器=新的StringWriter();
marshaller.marshall(root,writer);
System.out.println(writer.toString());
}
}
生成以下文档:

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

一
二

使用数组的公认解决方案可以工作,但会导致每个内部元素被命名:

从该链接获得的以下解决方案更适合我:

公共类包装器{
私有列表项=新的ArrayList();
@xmlanyement(lax=true)
公共列表getItems(){
退货项目;
}
}

//JAXBContext是线程安全的,因此在构造函数或
//塞特或任何地方:
... 
JAXBContext jc=JAXBContext.newInstance(Wrapper.class,clazz);
... 
公共字符串封送处理(列出事物,类clazz){
//配置JAXB和marshaller
Marshaller m=jc.createMarshaller();
m、 setProperty(Marshaller.JAXB_格式化的_输出,true);
//基于通用对象列表创建包装器
包装器=新包装器(物品);
JAXBElement-wrapperJAXBElement=new-JAXBElement(新的QName(clazz.getSimpleName().toLowerCase()+“s”)、Wrapper.class、Wrapper);
StringWriter结果=新建StringWriter();
//元帅!
m、 封送员(包装、结果);
返回result.toString();
}
它不需要将列表转换为数组,但需要一个通用类。

试试这个

POJO类:

@XmlRootElement(name = "classNameTAG")
@XmlAccessorType(XmlAccessType.FIELD)
public class ClassName {

    @XmlElementWrapper(name="listTAG")
    @XmlElement(name="itemTAG") 
    private List<ClassItem> items;
}
Xml结果:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<classNameTAG>
    <listTAG>
        <itemTAG>data</itemTAG>
        <itemTAG>data</itemTAG>
    </listTAG>
</classNameTAG>

数据
数据

这对我来说很有用。

我不知道对象列表会是便利设施,这就是为什么我尝试在没有包装器类的情况下完成它。这是正确的方向,但我在一个部分上遇到了一些问题。如果我不知道该类的类型,您知道如何将该类传递到
JAXBContext.newInstance()
?显然,我不能
JAXBContext.newInstance(t[].class)
实际上,不管我怎么想。不过我还有一个问题。如果我在您的演示中将项目类名称更改为类似Basketball的名称。单个元素仍然显示为
。您知道如何更改吗?似乎与多维数组的映射规则有关,相当于具有
的模式类型。至少在规范级别上,这是不可配置的。要生成JSON而不是XML,上述方法需要做哪些更改
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<items>
    <item>one</item>
    <item>two</item>
</items>
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();

}
@XmlRootElement(name = "classNameTAG")
@XmlAccessorType(XmlAccessType.FIELD)
public class ClassName {

    @XmlElementWrapper(name="listTAG")
    @XmlElement(name="itemTAG") 
    private List<ClassItem> items;
}
public static void pojo2xml(ClassName classData, File outputFile) throws Exception {
    JAXBContext context;
    BufferedWriter writer = null;
    writer = new BufferedWriter(new FileWriter(outputFile));
    context = JAXBContext.newInstance(ClassName.class);
    Marshaller m = context.createMarshaller();
    m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
    m.marshal(classData, writer);
    writer.close();
}
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<classNameTAG>
    <listTAG>
        <itemTAG>data</itemTAG>
        <itemTAG>data</itemTAG>
    </listTAG>
</classNameTAG>