2011-08-24 9 views
10

tengo un elemento en mi esquema XML que se define de la siguiente manera:Uso de JAXB genera la clase de un elemento que requiere un número entero con un patrón

<xs:complexType name="MyNumberCodeType"> 
    <xs:sequence> 
     <xs:element name="Code" type="NumberCodeValueType" maxOccurs="unbounded" /> 
    </xs:sequence> 
</xs:complexType> 

Dónde NumberCodeValueType es:

<xs:simpleType name="NumberCodeValueType"> 
    <xs:restriction base="xs:int"> 
     <xs:pattern value="[0-7]{7}"/> 
    </xs:restriction> 
</xs:simpleType> 

Eso es decir, mi número puede comenzar con 0s principales. No puedo modificar este esquema. Estoy usando JAXB para generar mis clases de Java. Por desgracia, el descriptor de acceso para el elemento Code toma una lista de números enteros como el argumento que significa que todos 0s principales se despojaron (porque, de lo que puedo decir, no hay manera de mantener los principales 0s en Java cuando se utiliza un tipo entero)!

¿Hay alguna manera de solucionar este problema?

Gracias por su ayuda!

Respuesta

31

Se podría hacer lo siguiente:

NumberFormatter

Puede hacer esto escribiendo su propio formateador:

package forum7182533; 

public class NumberFormatter { 

    public static String printInt(Integer value) { 
     String result = String.valueOf(value); 
     for(int x=0, length = 7 - result.length(); x<length; x++) { 
      result = "0" + result; 
     } 
     return result; 
    } 

    public static Integer parseInt(String value) { 
     return Integer.valueOf(value); 
    } 

} 

XMLSchema (format.xsd)

Luego, cuando va a generar sus clases desde su XML Esquema:

<?xml version="1.0" encoding="UTF-8"?> 
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> 

    <xs:element name="root"> 
     <xs:complexType> 
      <xs:sequence> 
       <xs:element name="number" type="NumberCodeValueType" /> 
      </xs:sequence> 
     </xs:complexType> 
    </xs:element> 

    <xs:simpleType name="NumberCodeValueType"> 
     <xs:restriction base="xs:int"> 
      <xs:pattern value="[0-7]{7}" /> 
     </xs:restriction> 
    </xs:simpleType> 

</xs:schema> 

bindings.xml

Va a aprovechar un archivo de enlaces de JAXB hacer referencia a su formateador:

<jxb:bindings xmlns:xs="http://www.w3.org/2001/XMLSchema" 
    xmlns:jxb="http://java.sun.com/xml/ns/jaxb" version="2.1"> 
    <jxb:bindings schemaLocation="format.xsd"> 
     <!--jxb:bindings node="//xs:simpleType[@name='NumberCodeValueType']" --> 
     <jxb:bindings node="//xs:element[@name='number']"> 
      <jxb:property> 
       <jxb:baseType> 
        <jxb:javaType name="java.lang.Integer" 
         parseMethod="forum7182533.NumberFormatter.parseInt" printMethod="forum7182533.NumberFormatter.printInt" /> 
       </jxb:baseType> 
      </jxb:property> 
     </jxb:bindings> 
    </jxb:bindings> 
</jxb:bindings> 

XJC llamada

El archivo de enlaces se hace referencia en la llamada XJC como:

xjc -d out -p forum7182533 -b bindings.xml format.xsd 

Adaptador1

Esto provocará un XmlAdapter que se creen que aprovecha el formateador:

package forum7182533; 

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

public class Adapter1 
    extends XmlAdapter<String, Integer> 
{ 


    public Integer unmarshal(String value) { 
     return (forum7182533.NumberFormatter.parseInt(value)); 
    } 

    public String marshal(Integer value) { 
     return (forum7182533.NumberFormatter.printInt(value)); 
    } 

} 

Raíz

El XmlAdapter se hará referencia desde su objeto de dominio utilizando la @XmlJavaTypeAdapter anotación:

package forum7182533; 

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

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

    @XmlElement(required = true, type = String.class) 
    @XmlJavaTypeAdapter(Adapter1 .class) 
    protected Integer number; 

    public Integer getNumber() { 
     return number; 
    } 

    public void setNumber(Integer value) { 
     this.number = value; 
    } 

} 

Demo

Ahora bien, si se ejecuta el siguiente código de demostración:

package forum7182533; 

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.setNumber(4); 

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

salida

Usted conseguirá el resultado deseado:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?> 
<root> 
    <number>0000004</number> 
</root> 
+5

+1 Me puede no ser molestado en leer el una respuesta completa, pero cualquiera que ponga tanto esfuerzo en una respuesta merece un voto positivo. – Kevin

+0

@Blaise ¿Sabes si sería posible especificar un adaptador directamente? Sería mucho más limpio, pero solo si está permitido. Intenté usar xjc: javaType pero no parece estar autorizado en baseType: - / –

Cuestiones relacionadas