有没有可能以编程方式configurationJAXB?
假设我有两个JavaBeans Person
和Address
。
如果我创build一个Person对象的列表,我想编组到这样的东西:
<persons> <person>...</person> </persons>
可以使用这里描述的技术: 使用JAXB解组/编组一个List <String>
通过使用@XmlRootElement(name = "persons")
和@XmlElement(name = "person")
对@XmlRootElement(name = "persons")
注释,可以编组上述XML。
但是,能够重用相同的JaxbList<T>
类来编组Address
对象列表也是很好的。 而实际上,我会有很多其他types的豆子。 我可以像这样做:
<list> <item xsi:type="person" xmlns:xsi="http://www.w2.org/2001/XmlSchema-instance"></item> </list>
但是,理想的情况是,用类名称的复数版本replace“list”并用类名replace“item”将会很好。
那么,是否有可能在运行时以编程方式configurationJaxbContext或其他东西?本质上是在@XmlRootElement
和@XmlElement
设置name
的值?
或者任何其他的方式来得到这个工作,而不必为每个beantypes编写单独的JaxbList
实现? 也许XmlJavaTypeAdapter可以实现这样的事情?
更新 @Blaise下面接受的Doughan的解决scheme很好。 对于我的用例,我需要直接从Java对象到XML,下面是什么工作(注意这不是我的完整实现,它只是用于演示的伪代码):
//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(); }
你可以像下面这样创build一个通用的Wrapper
对象:
包装纸
你可以用@XmlAnyElement(lax=true)
来创build一个带有List
属性的通用包装类。 用于填充此列表的对象的types将基于其根元素(请参阅: http : //blog.bdoughan.com/2010/08/using-xmlanyelement-to-build-generic.html )。
package forum13272288; import java.util.*; import javax.xml.bind.annotation.XmlAnyElement; public class Wrapper<T> { private List<T> items = new ArrayList<T>(); @XmlAnyElement(lax=true) public List<T> getItems() { return items; } }
地址
您需要使用@XmlRootElement
注释列表的可能内容。
package forum13272288; import javax.xml.bind.annotation.XmlRootElement; @XmlRootElement public class Address { }
人
package forum13272288; import javax.xml.bind.annotation.XmlRootElement; @XmlRootElement public class Person { }
演示
下面的演示代码演示了如何使用Wrapper
类。 由于根元素可以是不同的,你将需要指定你想解包到类包装。 或者,您可以利用@XmlElementDecl
批注将多个根元素与包装类关联(请参阅: http : //blog.bdoughan.com/2012/07/jaxb-and-root-elements.html )。
package forum13272288; import javax.xml.bind.*; import javax.xml.transform.stream.StreamSource; public class Demo { public static void main(String[] args) throws Exception { JAXBContext jc = JAXBContext.newInstance(Wrapper.class, Person.class, Address.class); Unmarshaller unmarshaller = jc.createUnmarshaller(); Marshaller marshaller = jc.createMarshaller(); marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); StreamSource personsXML = new StreamSource("src/forum13272288/persons.xml"); JAXBElement<Wrapper> wrapper1 = unmarshaller.unmarshal(personsXML, Wrapper.class); marshaller.marshal(wrapper1, System.out); StreamSource addressesXML = new StreamSource("src/forum13272288/addresses.xml"); JAXBElement<Wrapper> wrapper2 = unmarshaller.unmarshal(addressesXML, Wrapper.class); marshaller.marshal(wrapper2, System.out); } }
产量
以下是运行演示代码的输出。 文件persons.xml
和addresses.xml
看起来就像有相应的输出。
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <persons> <person/> <person/> </persons> <?xml version="1.0" encoding="UTF-8" standalone="yes"?> <addresses> <address/> <address/> </addresses>
了解更多信息