Jaxb:xs:属性null值

时间:2011-05-13 09:32:25

标签: jaxb

Reg:Jaxb

我基本上试图在JAXB中设置一个角色,它表示只要遇到空字段,而不是在输出中忽略它,就把它设置为空值。

对于xmlElement,我得到了答案,就像我们需要使用nillable =“true”但是我们需要如何设置null值。通过谷歌搜索我发现我们需要使用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>

如果有人知道,请尽快给我解决方案。

3 个答案:

答案 0 :(得分: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>

<强> 字符串转换

我们需要定义一个类来进行特殊的字符串处理。对于此用例,我们希望在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绑定文件来自定义类生成。下面的绑定文件将允许我们利用上面定义的StringConverter类:

<jaxb:bindings 
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
    version="2.1">
    <jaxb:bindings schemaLocation="attributeAdapter.xsd">
        <jaxb:bindings node="//xs:element[@name='root']/xs:complexType">
            <jaxb:bindings node="xs:attribute[@name='foo']">
                <jaxb:property>
                    <jaxb:baseType>
                        <jaxb:javaType name="java.lang.String"
                            parseMethod="com.example.adapter.StringConverter.parseString"
                            printMethod="com.example.adapter.StringConverter.printString"/>
                    </jaxb:baseType>
                </jaxb:property>
            </jaxb:bindings>
            <jaxb:bindings node="xs:attribute[@name='bar']">
                <jaxb:property>
                    <jaxb:baseType>
                        <jaxb:javaType name="java.lang.String"
                            parseMethod="com.example.adapter.StringConverter.parseString"
                            printMethod="com.example.adapter.StringConverter.printString"/>
                    </jaxb:baseType>
                </jaxb:property>
            </jaxb:bindings>
        </jaxb:bindings>
    </jaxb:bindings>
</jaxb:bindings>

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(Adapter1)

生成的XmlAdapter类将如下所示。请注意它如何利用我们的StringConverter类:

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=""/>

更新(替代绑定文件)

或者,如果您希望将适配器应用于类型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>

答案 1 :(得分:5)

从Java对象开始

对于映射为@XmlAttribute的字段/属性,JAXB实现(Metro,MOXy,JaxMe等)将空字符串(“”)值封送为property=""。您可以使用XmlAdapter将空值公开为空字符串以获得所需的行为:

NullStringAdapter

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

public class NullStringAdapter extends XmlAdapter<String, String> {

    @Override
    public String unmarshal(String v) throws Exception {
        if("".equals(v)) {
            return null;
        }
        return v;
    }

    @Override
    public String marshal(String v) throws Exception {
        if(null == v) {
            return "";
        }
        return v;
    }

}

以下是如何在域模型中指定适配器。同一个适配器可用于许多属性:

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的更多信息,请参阅:

答案 2 :(得分:0)

您可以为此使用默认值插件。

请查看以下问题:JAXB xjc: How to generate code for Strings that returns empty if the value is null?