如何给使用JAXB注解的XmlElementWrapper类添加XML属性?

25
我有一个带有XmlElementWrapper注释的类,例如:

...

  @XmlElementWrapper(name="myList")
    @XmlElements({
    @XmlElement(name="myElement") }
    )
    private List<SomeType> someList = new LinkedList();
这段代码生成类似于

的XML。
<myList>
  <myElement> </myElement>
  <myElement> </myElement>
  <myElement> </myElement>
</myList>

目前为止,一切都很顺利。

但是现在我需要向列表标记添加属性,以获得类似于XML的效果

<myList number="2">
  <myElement> </myElement>
  <myElement> </myElement>
  <myElement> </myElement>
</myList>

有没有一种聪明的方法可以在不创建包含代表列表的新类的情况下实现这个?

3个回答

30

我为你的问题提供了更好的解决方案。

要创建Xml Java对象,请使用以下代码:

import java.util.*;
import javax.xml.bind.annotation.*;

@XmlRootElement(name="myList")
public class Root {

    private String number;
    private List<String> someList;

    @XmlAttribute(name="number")
    public String getNumber() {
        return number;
    }

    public void setNumber(String number) {
        this.number = number;
    }

    @XmlElement(name="myElement")
    public List<String> getSomeList() {
        return someList;
    }

    public void setSomeList(List<String> someList) {
        this.someList = someList;
    } 

    public Root(String numValue,List<String> someListValue) {
        this();
        this.number = numValue;
        this.someList = someListValue;  
    }

    /**
     * 
     */
    public Root() {
        // TODO Auto-generated constructor stub
    }

}

要使用JAXB运行上述代码,请使用以下内容:

   import java.util.ArrayList;
import java.util.List;

import javax.xml.bind.*;

public class Demo {

        public static void main(String[] args) throws Exception {
            List<String> arg = new ArrayList<String>();
            arg.add("FOO");
            arg.add("BAR");
            Root root = new Root("123", arg);

            JAXBContext jc = JAXBContext.newInstance(Root.class);
            Marshaller marshaller = jc.createMarshaller();
            marshaller.marshal(root, System.out);
        }
}
这将产生以下 XML 作为输出:
    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    <myList number="123">
        <myElement>FOO</myElement>
        <myElement>BAR</myElement>
    </myList>

我认为这对你更有帮助。

谢谢。


2
如果您只有一个要包装的集合类型(在示例中为String),那么Noby的解决方案效果很好。 如果您想扩展该解决方案以创建具有属性的更通用的列表包装器类,则可以使用@XmlElements注释来创建其他映射。 我在此评论中的空间不足,因此我将在另一个答案中发布示例代码。 - ɲeuroburɳ

11

MOXy是JAXB实现的一种方式(我是技术负责人),它有一个扩展功能(@XmlPath)来处理这种情况:

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

@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Root {

    @XmlPath("myList/@number")
    private int number;

    @XmlElementWrapper(name="myList") 
    @XmlElement(name="myElement") 
    private List<String> someList = new LinkedList<String>();

    public int getNumber() {
        return number;
    }

    public void setNumber(int number) {
        this.number = number;
    }

    public List<String> getSomeList() {
        return someList;
    }

    public void setSomeList(List<String> someList) {
        this.someList = someList;
    } 

}

将生成以下XML:

<?xml version="1.0" encoding="UTF-8"?>
<root>
   <myList number="123">
      <myElement>FOO</myElement>
      <myElement>BAR</myElement>
   </myList>
</root>

当运行以下代码时:

import javax.xml.bind.*;

public class Demo {

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

        Root root = new Root();
        root.setNumber(123);
        root.getSomeList().add("FOO");
        root.getSomeList().add("BAR");

        Marshaller marshaller = jc.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        marshaller.marshal(root, System.out);
    }
}
要使用严格标准的JAXB代码使其正常工作,您需要使用XML适配器: 注意: 要使用MOXy JAXB,需要在模型类中添加名为jaxb.properties的文件,并提供以下条目:
javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory

很棒的答案!有没有办法在元素中添加一个常量硬编码属性?例如,只需在设计时向某些@XmlElements添加类似于“drawable =“ true””这样的内容,而无需为每个元素创建特殊字段? - NumberFour

4
如果您不使用MOXy或者只是想用标准的JAXB注释,那么您可以在Noby的答案基础上扩展来支持一个通用的包装类。Noby的答案目前只支持字符串列表,但是比如说您将要为几个不同的类使用同一个通用的包装类。在我的例子中,我想创建一个通用的“PagedList”类,它将被编组为类似于列表的东西,但同时还包含有关未分页列表中页面偏移量和元素总数的信息。
这种解决方案的一大弊端就是您必须为每种类型的被包装类添加额外的@XmlElement映射。总的来说,这可能是比为每个可分页元素创建一个新类更好的解决方案。
@XmlType
public class PagedList<T> {
    @XmlAttribute
    public int offset;

    @XmlAttribute
    public long total;

    @XmlElements({
        @XmlElement(name="order", type=Order.class),
        @XmlElement(name="address", type=Address.class)
        // additional as needed
    })
    public List<T> items;
}

@XmlRootElement(name="customer-profile")
public class CustomerProfile {
    @XmlElement
    public PagedList<Order> orders;
    @XmlElement
    public PagedList<Address> addresses;
}

对此进行编组将获得以下结果:

<customer-profile>
    <order offset="1" total="100">
        <order> ... </order>
        <order> ... </order>
        <order> ... </order>
        ...
    </orders>
    <addresses offset="1" total="5">
        <address> ... </address>
        <address> ... </address>
        <address> ... </address>
        <address> ... </address>
        <address> ... </address>
    <addresses>
</customer-profile>

希望能对您有所帮助。至少这是我采取的解决方案。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接