javaxsdjaxbxjccxf-xjc-plugin

JAXB marshalling for BigDecimal using fractionDigits


So here's my problem. I'm given an XSD to which my generated XML file should comply. Using the org.apache.cxf.cxf-xjc-plugin maven plugin and an external binding file I generate the source code. But when I'm trying marshall my object the generated XML doesn't meet my requirements.

My XSD contains the following:

<xsd:element maxOccurs="1" minOccurs="0" name="amount">
  <xsd:simpleType>
    <xsd:restriction base="xsd:decimal">
      <xsd:totalDigits value="13" />
      <xsd:fractionDigits value="2" />
    </xsd:restriction>
  </xsd:simpleType>
</xsd:element>
...
<xsd:element maxOccurs="1" minOccurs="0" name="rate">
  <xsd:simpleType>
    <xsd:restriction base="xsd:decimal">
      <xsd:totalDigits value="8" />
      <xsd:fractionDigits value="5" />
    </xsd:restriction>
  </xsd:simpleType>
</xsd:element>

And the generated piece of XML looks like this:

<amount>109.5</amount>
...
<rate>10.25</rate>

While I was expecting it to be:

<amount>109.50</amount>
...
<rate>10.25000</rate>

Is there a way to solve this problem in a clean way?

I would prefer not writing several adapters for every single totalDigits, fractionDigits combination. And as the XSD is subject to change I'd like to leave the generated source code untouched.


Solution

  • You will need to use XmlAdapter for this use case. Below is a sample binding file that will help you generate them. The logic would be contained in a DecimalFormatter class that contained methods for all the different required formats.

    <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="schema.xsd">
            <jxb:bindings node="//xs:element[@name='amount']">
                <jxb:property>
                    <jxb:baseType>
                        <jxb:javaType name="java.math.BigDecimal"
                            parseMethod="org.example.DecimalFormatter.parseDecimal"
                            printMethod="org.example.DecimalFormatter.printDecimal_2Places" />
                    </jxb:baseType>
                </jxb:property>
            </jxb:bindings>
            <jxb:bindings node="//xs:element[@name='rate']">
                <jxb:property>
                    <jxb:baseType>
                        <jxb:javaType name="java.math.BigDecimal"
                            parseMethod="org.example.DecimalFormatter.parseDecimal"
                            printMethod="org.example.DecimalFormatter.printDecimal_5Places" />
                    </jxb:baseType>
                </jxb:property>
            </jxb:bindings>
        </jxb:bindings>
    </jxb:bindings>
    

    For More Information