如何在将对象序列化为XML时添加XML名称空间(xmlns)
问题描述:
我使用XStream将对象序列化为XML。 如何让XStream将xmlns插入到对象的XML输出中?如何在将对象序列化为XML时添加XML名称空间(xmlns)
举个例子,我有这个简单的对象我想要序列:
@XStreamAlias(value="domain")
public class Domain
{
@XStreamAsAttribute
private String type;
private String os;
(...)
}
如何实现正是使用XStream以下输出?
<domain type="kvm" xmlns:qemu="http://libvirt.org/schemas/domain/qemu/1.0">
<os>linux</os>
</domain>
答
另外,这种使用情况下,可以很容易地用JAXB实现处理( Metro,EclipseLink MOXy,Apache JaxMe等):
域
package com.example;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement
public class Domain
{
private String type;
private String os;
@XmlAttribute
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getOs() {
return os;
}
public void setOs(String os) {
this.os = os;
}
}
包信息
@XmlSchema(xmlns={
@XmlNs(
prefix="qemu",
namespaceURI="http://libvirt.org/schemas/domain/qemu/1.0")
})
package com.example;
import javax.xml.bind.annotation.XmlNs;
import javax.xml.bind.annotation.XmlSchema;
演示
package com.example;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
public class Demo {
public static void main(String[] args) throws JAXBException {
JAXBContext jc = JAXBContext.newInstance(Domain.class);
Domain domain = new Domain();
domain.setType("kvm");
domain.setOs("linux");
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(domain, System.out);
}
}
输出
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<domain xmlns:qemu="http://libvirt.org/schemas/domain/qemu/1.0" type="kvm">
<os>linux</os>
</domain>
更多信息
答
XStream的不支持命名空间,但它使用的StaxDriver
,确实。您需要将命名空间的细节设置成QNameMap
并传递到StaxDriver
:
QNameMap qmap = new QNameMap();
qmap.setDefaultNamespace("http://libvirt.org/schemas/domain/qemu/1.0");
qmap.setDefaultPrefix("qemu");
StaxDriver staxDriver = new StaxDriver(qmap);
XStream xstream = new XStream(staxDriver);
xstream.autodetectAnnotations(true);
xstream.alias("domain", Domain.class);
Domain d = new Domain("kvm","linux");
String xml = xstream.toXML(d);
输出:
<qemu:domain type="kvm" xmlns:qemu="http://libvirt.org/schemas/domain/qemu/1.0">
<qemu:os>linux</qemu:os>
</qemu:domain>
答
这是一个黑客位,但它的快速和容易:一个字段添加到您的类名为xmlns
,只有拥有它序列化期间非空。要继续例如:
@XStreamAlias(value="domain")
public class Domain
{
@XStreamAsAttribute
private String type;
private String os;
(...)
@XStreamAsAttribute
@XStreamAlias("xmlns:qemu")
String xmlns;
public void serialise(File path) {
XStream xstream = new XStream(new DomDriver());
xstream.processAnnotations(Domain.class);
(...)
PrintWriter out = new PrintWriter(new FileWriter(path.toFile()));
xmlns = "http://libvirt.org/schemas/domain/qemu/1.0";
xstream.toXML(this, out);
xmlns = null;
}
}
齐全,设置xmlns = null
应在finally
条款。如果你喜欢,使用PrintWriter
也可以让你在输出的开头插入一个XML声明。
不错,谢谢!好的,但仍然有一个问题:我不希望该qemu前缀作为所有节点的默认前缀。它应该只在根节点内部定义,以便生成的XML看起来完全像我的问题。你有什么提示如何实现这一点? – ifischer 2011-05-25 08:16:21
@ifischer我不认为有一种方法来获得您的确切输出。您可以尝试删除'setDefaultPrefix'语句,但这也会从xmlns声明中删除qemu。为什么你需要在你的输出中输入qemu,如果你不打算用它作为你的元素的前缀? – dogbane 2011-05-25 08:29:10
,因为并非所有子节点都使用qemu名称空间。另外,也许我想稍后添加更多的XML名称空间。顺便说一句,生成的XML需要采用非常特定的格式,因为它已发送到非常严格的Libvirt。 – ifischer 2011-05-25 08:35:47