1

This is kind of the opposite direction of questions like No @XmlRootElement generated by JAXB. Basically I want to run schemagen and have two global elements of the same type.

<xs:element name="root1" type="tns:sameType"/>
<xs:element name="root2" type="tns:sameType"/>

I understand how to marshal things with JAXBElement but I'm at a loss on how to get the schema generated correctly. In my mind it would look something like the following snippet (@XmlRootElements is fictional).

@XmlRootElements(value = {
    @XmlRootElement(name="root1", namespace="urn:example"),
    @XmlRootElement(name="root2", namespace="urn:example")
})
Community
  • 1
  • 1
Chase
  • 3,123
  • 1
  • 30
  • 35

1 Answers1

3

You can use the @XmlElementDecl annotation on a class annotated with @XmlRegistry.

ObjectFactory

The @XmlElementDecl annotation is used when a type has multiple global elements corresponding to it. The annotation is placed on create methods on a class annotated with @XmlRegistry. When a model is generated from an XML schema this class is always called ObjectFactory.

package forum14845035;

import javax.xml.bind.JAXBElement;
import javax.xml.bind.annotation.*;
import javax.xml.namespace.QName;

@XmlRegistry
public class ObjectFactory {

    @XmlElementDecl(name="root1")
    public JAXBElement<SameType> createRoot1(SameType sameType) {
        return new JAXBElement<SameType>(new QName("urn:example", "root1"), SameType.class, sameType);
    }

    @XmlElementDecl(name="root2")
    public JAXBElement<SameType> createRoot2(SameType sameType) {
        return new JAXBElement<SameType>(new QName("urn:example", "root2"), SameType.class, sameType);
    }

}

SameType

In this use case no annotations are required on the domain class.

package forum14845035;

public class SameType {

}

package-info

We will leverage the package level @XmlSchema annotation to specify the namespace qualification for our model.

@XmlSchema(namespace="urn:example", elementFormDefault=XmlNsForm.QUALIFIED)
package forum14845035;

import javax.xml.bind.annotation.*;

Demo

package forum14845035;

import java.io.IOException;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.SchemaOutputResolver;
import javax.xml.transform.Result;
import javax.xml.transform.stream.StreamResult;

public class Demo {

    public static void main(String[] args) throws Exception {
        JAXBContext jc = JAXBContext.newInstance(SameType.class, ObjectFactory.class);
        jc.generateSchema(new SchemaOutputResolver() {

            @Override
            public Result createOutput(String namespaceUri,
                    String suggestedFileName) throws IOException {
                StreamResult result = new StreamResult(System.out);
                result.setSystemId(suggestedFileName);
                return result;
            }

        });
    }

}

Output

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<xs:schema elementFormDefault="qualified" version="1.0" targetNamespace="urn:example" xmlns:tns="urn:example" xmlns:xs="http://www.w3.org/2001/XMLSchema">

  <xs:element name="root1" type="tns:sameType"/>

  <xs:element name="root2" type="tns:sameType"/>

  <xs:complexType name="sameType">
    <xs:sequence/>
  </xs:complexType>

</xs:schema>

For More Information

bdoughan
  • 147,609
  • 23
  • 300
  • 400
  • 1
    Perfect, thanks. I've been using jaxb.index and didn't even think to look at an ObjectFactory as a possible avenue. – Chase Feb 13 '13 at 01:52