2011-05-13 63 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