4

Goal

I'm trying to generate a XML that validates against a given XSD by marshalling an object created with classes generated with said XSD.

Note that I cannot modify the XSD and I don't want to edit the generated classes.

Example

foo.xsd

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema>
    <xs:element name="Foo" type="Foo"/>
    <xs:complexType name="Foo">
        <xs:sequence>
            <xs:element name="Bar" type="Bar"/>
        </xs:sequence>
    </xs:complexType>
    <xs:complexType name="Bar">
        <xs:sequence>
            <xs:element maxOccurs="1" minOccurs="0" name="Baz" type="Max6Text"/>
        </xs:sequence>
    </xs:complexType>
    <xs:simpleType name="Max6Text">
        <xs:restriction base="xs:string">
            <xs:minLength value="1"/>
            <xs:maxLength value="6"/>
        </xs:restriction>
    </xs:simpleType>
</xs:schema>

Foo.java generated using jaxb2-maven-plugin

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "Foo", propOrder = {
    "bar"
})
public class Foo {

    @XmlElement(name = "Bar", required = true)
    protected Bar bar;

    public Bar getBar() {
        return bar;
    }

    public void setBar(Bar value) {
        this.bar = value;
    }
}

Bar.java generated using jaxb2-maven-plugin

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "Bar", propOrder = {
    "baz"
})
public class Bar {

    @XmlElement(name = "Baz")
    protected String baz;

    public String getBaz() {
        return baz;
    }

    public void setBaz(String value) {
        this.baz = value;
    }
}

Foo object instance creation

Foo foo = new ObjectFactory().createFoo();

Marshalling

File xmlResult = File.createTempFile("foo", ".xml");

JAXBContext jaxbContext = JAXBContext.newInstance(Foo.class);
Marshaller marshaller = jaxbContext.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(new ObjectFactory().createFoo(foo), new FileOutputStream(xmlResult));

String result = Files.readString(Path.of(xmlResult.getPath()));
System.out.println(result);

Problem

Expected output

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Foo>
    <Bar/>
</Foo>

Actual output

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Foo/>

The problem is due to the fact that the bar field of the Foo object is null, altough it's required = true.

So, here is my question: How can I generate the Java classes with constructors that respect the required field? I would have expected this as a generated Foo.java:

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "Foo", propOrder = {
    "bar"
})
public class Foo {

    @XmlElement(name = "Bar", required = true)
    protected Bar bar;

    public Foo() {
        this.bar = new ObjectFactory().createBar();
    }

    public Bar getBar() {
        return bar;
    }

    public void setBar(Bar value) {
        this.bar = value;
    }
}

I haven't found any configuration to change this in jaxb2-maven-plugin.

  • xs is not defined. Can you try to add `xmlns:xs="http://www.w3.org/2001/XMLSchema"`? I know you don't want to change the xsd but just check if anything changes. – Sherif elKhatib Mar 13 '21 at 12:41
  • I haven't included in the example for simplicity, but it's there on my real-code problem. So it doesn't change anything. – Christophe Broeckx Mar 14 '21 at 15:02
  • 1
    Hello, you can use this approach to instanciate by default and respect the required : http://jaxbnstuff.blogspot.com/2013/09/creating-xjc-plugin-to-instantiate.html – stacky Mar 14 '21 at 15:36

1 Answers1

1

some things here to clear up. I think your problem is probably that your data is getting converted into XML exactly the way your data is in your class structure. It doesn't matter what the XSD says. Your class Foo does not have an instance of Bar in it, so you get not children into the final result.

What you need is something, that automatically fills up your data structure with sample data the way the XSD describes it as valid. And for that you can write a library or you make use of one (unfortunately I don't know any). You could use the JAXB annotations that have been generated.

You could also create XML directly from the XSD without converting everything to Java objects. I think you could make use of this library which I just found on the internet: https://santhosh-tekuri.github.io/jlibs/xsd/XSInstance.html

Janos Vinceller
  • 1,208
  • 11
  • 25