Jaxb: xs: атрибут нулевые значения - PullRequest
6 голосов
/ 13 мая 2011

Рег: Jaxb

Я в основном пытаюсь установить роль в JAXB, которая говорит, что всякий раз, когда встречается пустое поле, вместо игнорирования его в выходных данных, установите его в пустое значение.

Для xmlElement я получил ответ, что нам нужно использовать nillable = "true", но для того, чтобы нам нужно было установить нулевое значение. Погуглив, я обнаружил, что нам нужно использовать use = "необязательный", но в моем случае это не работает.

Часть моего 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 ]

6 голосов
/ 16 мая 2011

Начиная с XML-схемы

В предыдущем ответе я описал, как решить ваш сценарий использования при запуске из объектов 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>

StringConverter

Мы будемНужно определить класс для нашей специальной обработки 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;
    }

}

Binding File (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

Модель домена (Root)

Поля / свойства, которые мы настроили в файле привязки, будутаннотирован @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=""/>

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>
5 голосов
/ 13 мая 2011

Начиная с объектов 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;
    }

}

Root

Ниже описано, как указать адаптер в модели вашего домена.Один и тот же адаптер может использоваться во многих свойствах:

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

Для получения дополнительной информации о XmlAdapter JAXB см .:

0 голосов
/ 26 января 2019

Для этого вы можете использовать плагин значений по умолчанию.

Пожалуйста, посмотрите на этот вопрос: JAXB xjc: Как сгенерировать код для строк, который возвращает пустое значение, если значение равно нулю?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...