Using JAXB generated class for an element that requires an integer with a pattern

后端 未结 1 688
日久生厌
日久生厌 2020-11-29 05:47

I have an element in my XML Schema that is defined as follows:


    
        

        
相关标签:
1条回答
  • 2020-11-29 05:57

    You could do the following:

    NumberFormatter

    You can do this by writing your own formatter:

    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)

    Then when you are going to generate your classes from your XML Schema:

    <?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

    You will leverage a JAXB bindings file to reference your formatter:

    <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 Call

    The bindings file is referenced in the XJC call as:

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

    Adapter1

    This will cause an XmlAdapter to be created that leverages your formatter:

    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));
        }
    
    }
    

    Root

    The XmlAdapter will be referenced from your domain object using the @XmlJavaTypeAdapter annotation:

    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

    Now if you run the following demo code:

    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);
        }
    }
    

    Output

    You will get the desired output:

    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    <root>
        <number>0000004</number>
    </root>
    
    0 讨论(0)
提交回复
热议问题