2011-05-25 110 views
9

我使用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> 

回答

5

另外,這種使用情況下,可以很容易地用JAXB實現處理( MetroEclipseLink MOXyApache 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> 

更多信息

15

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> 
+0

不錯,謝謝!好的,但仍然有一個問題:我不希望該qemu前綴作爲所有節點的默認前綴。它應該只在根節點內部定義,以便生成的XML看起來完全像我的問題。你有什麼提示如何實現這一點? – ifischer 2011-05-25 08:16:21

+0

@ifischer我不認爲有一種方法來獲得您的確切輸出。您可以嘗試刪除'setDefaultPrefix'語句,但這也會從xmlns聲明中刪除qemu。爲什麼你需要在你的輸出中輸入qemu,如果你不打算用它作爲你的元素的前綴? – dogbane 2011-05-25 08:29:10

+0

,因爲並非所有子節點都使用qemu名稱空間。另外,也許我想稍後添加更多的XML名稱空間。順便說一句,生成的XML需要採用非常特定的格式,因爲它已發送到非常嚴格的Libvirt。 – ifischer 2011-05-25 08:35:47

4

這是一個黑客位,但它的快速和容易:一個字段添加到您的類名爲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聲明。

相關問題