2011-05-13 64 views
6

註冊:JAXBJAXB:XS:屬性空值

基本上,我試圖建立在JAXB作用它說,每當遇到一個空場,而不是在輸出忽視它,將其設置爲一個空值。

對於xmlElement我得到的答案就像我們需要使用nillable =「true」,但是我們需要如何設置空值。通過谷歌搜索,我發現我們需要使用use =「optional」,但它不適用於我的情況。

我的XSD的部分低於:

<xs:attribute name="RomVersion" type="xs:string" use="required" /> 
<xs:attribute name="MACAddress" type="xs:string" use="required" /> 
<xs:attribute name="LargestFreeBlock" type="xs:unsignedInt" use="required" /> 
<xs:attribute name="TimeSinceLastReset" type="xs:unsignedInt" use="optional" /> 
<xs:attribute name="ResetReason" type="xs:string" use="optional" /> 
<xs:attribute name="TimeStamp" type="xs:unsignedInt" use="optional" /> 
<xs:attribute name="ECOList" type="xs:string" use="optional" /> 
</xs:complexType> 
</xs:element> 

請給我儘快解決,如果任何人知道。

回答

5

從Java對象開始

對映射爲@XmlAttribute,一個JAXB實現(新城,MOXY,JaxMe等)的字段/屬性將編組空字符串( 「」)的值作爲property=""。您可以使用XmlAdapter暴露你的空值作爲空字符串,以獲得所需的行爲:

NullStringAdapter

​​

以下是如何指定您的域模型中的適配器。同一個適配器可以在許多屬性可以使用:

import javax.xml.bind.annotation.XmlAttribute; 
import javax.xml.bind.annotation.XmlRootElement; 
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; 

@XmlRootElement 
public class Root { 

    private String foo; 
    private String bar; 

    @XmlAttribute 
    @XmlJavaTypeAdapter(NullStringAdapter.class) 
    public String getFoo() { 
     return foo; 
    } 

    public void setFoo(String foo) { 
     this.foo = foo; 
    } 

    @XmlAttribute 
    @XmlJavaTypeAdapter(NullStringAdapter.class) 
    public String getBar() { 
     return bar; 
    } 

    public void setBar(String bar) { 
     this.bar = bar; 
    } 

} 

演示

可以說明這個概念,通過運行下面的演示代碼:

import javax.xml.bind.JAXBContext; 
import javax.xml.bind.Marshaller; 

public class Demo { 

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

     Root root = new Root(); 
     root.setFoo(null); 
     root.setBar(null); 

     Marshaller marshaller = jc.createMarshaller(); 
     marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); 
     marshaller.marshal(root, System.out); 
    } 

} 

輸出

以下是演示代碼輸出:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?> 
<root bar="" foo=""/> 

的更多信息,JAXB的XmlAdapter參見:

+0

但是,類文件是使用xjc命令生成的。我們不應該做任何改變..我指的是這種變化:@XmlJavaTypeAdapter(NullStringAdapter.class) – Rekha 2011-05-16 11:21:04

+0

@Rekha - 我已經添加了第二個答案,描述了從XML模式啓動時如何處理此用例: http://stackoverflow.com/questions/5989922/jaxb-xsattribute-null-values/6018318#6018318 – 2011-05-16 13:43:44

+0

現在,客戶希望默認值出現而不是空白字符串。如: ... 然後假設這個XML片段: < ... First =「31」Third =「42」... /> 所需的xml應該如下: <... First =「31」Second =「2」Third =「42」... /> – Rekha 2011-05-17 09:24:49

6

從XML模式

開始在previous answer我介紹瞭如何從Java對象開始時解決您的使用情況。根據您對該答案的評論,此答案描述了從XML模式生成模型時如何完成同樣的事情。

XML架構(attributeAdapter.xsd)

在這個例子中,我們將使用以下XML架構:

<?xml version="1.0" encoding="utf-8" ?> 
<xs:schema 
    elementFormDefault="qualified" 
    targetNamespace="http://www.example.com/adapter" 
    xmlns:nytd="http://www.example.com/adapter" 
    xmlns:xs="http://www.w3.org/2001/XMLSchema"> 

    <xs:element name="root"> 
     <xs:complexType> 
      <xs:attribute name="foo" type="xs:string"/> 
      <xs:attribute name="bar" type="xs:string"/> 
     </xs:complexType> 
    </xs:element> 

</xs:schema> 

字符串轉換

我們需要定義一個類來做我們特殊的String處理。對於這種使用情況下,我們希望得到的空字段/屬性值空字符串(「」)的XML文檔中:

package com.example.adapter; 

public class StringConverter { 

    public static String parseString(String value) { 
     if("".equals(value)) { 
      return null; 
     } 
     return value; 
    } 

    public static String printString(String value) { 
     if(null == value) { 
      return ""; 
     } 
     return value; 
    } 

} 

綁定文件(attributeAdapterBinding.xml)

我們將需要使用JAXB綁定文件來定製類生成。下面結合文件將使我們能夠利用我們在上面定義的字符串轉換類:

​​

XJC調用

我們將盡我們的XJC電話如下:

xjc -d out -b attributeAdapterBinding.xml attributeAdapter.xsd 

域模型(根)

的字段/我們在綁定文件將與@XmlJavaTypeAdapter進行註釋定製屬性;

package com.example.adapter; 

import javax.xml.bind.annotation.XmlAccessType; 
import javax.xml.bind.annotation.XmlAccessorType; 
import javax.xml.bind.annotation.XmlAttribute; 
import javax.xml.bind.annotation.XmlRootElement; 
import javax.xml.bind.annotation.XmlType; 
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; 


@XmlAccessorType(XmlAccessType.FIELD) 
@XmlType(name = "") 
@XmlRootElement(name = "root") 
public class Root { 

    @XmlAttribute 
    @XmlJavaTypeAdapter(Adapter1 .class) 
    protected String foo; 

    @XmlAttribute 
    @XmlJavaTypeAdapter(Adapter2 .class) 
    protected String bar; 

    public String getFoo() { 
     return foo; 
    } 

    public void setFoo(String value) { 
     this.foo = value; 
    } 

    public String getBar() { 
     return bar; 
    } 

    public void setBar(String value) { 
     this.bar = value; 
    } 

} 

XmlAdapter(適配器1)

生成的XmlAdapter類看起來像下面這樣。注意它是如何利用我們的類字符串轉換:

package com.example.adapter; 

import javax.xml.bind.annotation.adapters.XmlAdapter; 

public class Adapter1 extends XmlAdapter<String, String> { 

    public String unmarshal(String value) { 
     return (com.example.adapter.StringConverter.parseString(value)); 
    } 

    public String marshal(String value) { 
     return (com.example.adapter.StringConverter.printString(value)); 
    } 

} 

演示

現在,如果我們運行下面的演示代碼:

package com.example.adapter; 

import javax.xml.bind.JAXBContext; 
import javax.xml.bind.Marshaller; 

public class Demo { 

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

     Root root = new Root(); 
     root.setFoo(null); 
     root.setBar(null); 

     Marshaller marshaller = jc.createMarshaller(); 
     marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); 
     marshaller.marshal(root, System.out); 
    } 

} 

輸出

,我們將獲得所需的輸出:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?> 
<root xmlns="http://www.example.com/adapter" foo="" bar=""/> 

UPDATE(交替綁定文件)

另外,如果你想應用到xsd:string類型的所有屬性的適配器,那麼你可以使用看着一個綁定文件就像是;

<jaxb:bindings 
    xmlns:xs="http://www.w3.org/2001/XMLSchema" 
    xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" 
    version="2.1"> 
    <jaxb:globalBindings> 
     <jaxb:javaType 
      name="String" 
      xmlType="xs:string" 
      parseMethod="com.example.adapter.StringConverter.parseString" 
      printMethod="com.example.adapter.StringConverter.printString"/> 
    </jaxb:globalBindings> 

</jaxb:bindings> 
+0

它的工作正常我用globalBindings作爲我的xsd的非常大,所以創建binding.xml將是一個繁忙的過程。但如果我想同樣的東西申請長,int等不只是字符串,我可以用globalBindings相同的方式定義它的字符串? – Rekha 2011-05-17 07:21:08

+1

@Rekha - 您應該可以對任何簡單類型使用相同的策略。 – 2011-05-17 16:21:45