Chapter 33. Using XML Elements
Chapter 33. Using XML Elements Abstract XML Schema elements are used to define an instance of an element in an XML document. Elements are defined either in the global scope of an XML Schema document, or they are defined as a member of a complex type. When they are defined in the global scope, Apache CXF maps them to a JAXB element class that makes manipulating them easier. Overview An element instance in an XML document is defined by an XML Schema element element in the global scope of an XML Schema document To make it easier for Java developers to work with elements, Apache CXF maps globally scoped elements to either a special JAXB element class or to a Java class that is generated to match its content type. How the element is mapped depends on if the element is defined using a named type referenced by the type attribute or if the element is defined using an in-line type definition. Elements defined with in-line type definitions are mapped to Java classes. It is recommended that elements are defined using a named type because in-line types are not reusable by other elements in the schema. XML Schema mapping In XML Schema elements are defined using element elements. element elements has one required attribute. The name specifies the name of the element as it appears in an XML document. In addition to the name attribute element elements have the optional attributes listed in Table 33.1, "Attributes Used to Define an Element" . Table 33.1. Attributes Used to Define an Element Attribute Description type Specifies the type of the element. The type can be any XML Schema primitive type or any named complex type defined in the contract. If this attribute is not specified, you will need to include an in-line type definition. nillable Specifies if an element can be left out of a document entirely. If nillable is set to true , the element can be omitted from any document generated using the schema. abstract Specifies if an element can be used in an instance document. true indicates that the element cannot appear in the instance document. Instead, another element whose substitutionGroup attribute contains the QName of this element must appear in this element's place. For information on how this attribute effects code generation see the section called "Java mapping of abstract elements" . substitutionGroup Specifies the name of an element that can be substituted with this element. For more information on using type substitution see Chapter 37, Element Substitution . default Specifies a default value for an element. For information on how this attribute effects code generation see the section called "Java mapping of elements with a default value" . fixed Specifies a fixed value for the element. Example 33.1, "Simple XML Schema Element Definition" shows a simple element definition. Example 33.1. Simple XML Schema Element Definition An element can also define its own type using an in-line type definition. In-line types are specified using either a complexType element or a simpleType element. Once you specify whether the type of data is complex or simple, you can define any type of data needed using the tools available for each type of data. Example 33.2, "XML Schema Element Definition with an In-Line Type" shows an element definition with an in-line type definition. Example 33.2. XML Schema Element Definition with an In-Line Type Java mapping of elements with a named type By default, globally defined elements are mapped to JAXBElement<T> objects where the template class is determined by the value of the element element's type attribute. For primitive types, the template class is derived using the wrapper class mapping described in the section called "Wrapper classes" . For complex types, the Java class generated to support the complex type is used as the template class. To support the mapping and to relieve the developer of unnecessary worry about an element's QName, an object factory method is generated for each globally defined element, as shown in Example 33.3, "Object Factory Method for a Globally Scoped Element" . Example 33.3. Object Factory Method for a Globally Scoped Element For example, the element defined in Example 33.1, "Simple XML Schema Element Definition" results in the object factory method shown in Example 33.4, "Object Factory for a Simple Element" . Example 33.4. Object Factory for a Simple Element Example 33.5, "Using a Globally Scoped Element" shows an example of using a globally scoped element in Java. Example 33.5. Using a Globally Scoped Element Using elements with named types in WSDL If a globally scoped element is used to define a message part, the generated Java parameter is not an instance of JAXBElement<T> . Instead it is mapped to a regular Java type or class. Given the WSDL fragment shown in Example 33.6, "WSDL Using an Element as a Message Part" , the resulting method has a parameter of type String . Example 33.6. WSDL Using an Element as a Message Part Example 33.7, "Java Method Using a Global Element as a Part" shows the generated method signature for the sayHi operation. Example 33.7. Java Method Using a Global Element as a Part String sayHi String in Java mapping of elements with an in-line type When an element is defined using an in-line type, it is mapped to Java following the same rules used for mapping other types to Java. The rules for simple types are described in Chapter 34, Using Simple Types . The rules for complex types are described in Chapter 35, Using Complex Types . When a Java class is generated for an element with an in-line type definition, the generated class is decorated with the @XmlRootElement annotation. The @XmlRootElement annotation has two useful properties: name and namespace . These attributes are described in Table 33.2, "Properties for the @XmlRootElement Annotation" . Table 33.2. Properties for the @XmlRootElement Annotation Property Description name Specifies the value of the XML Schema element element's name attribute. namespace Specifies the namespace in which the element is defined. If this element is defined in the target namespace, the property is not specified. The @XmlRootElement annotation is not used if the element meets one or more of the following conditions: The element's nillable attribute is set to true The element is the head element of a substitution group For more information on substitution groups see Chapter 37, Element Substitution . Java mapping of abstract elements When the element's abstract attribute is set to true the object factory method for instantiating instances of the type is not generated. If the element is defined using an in-line type, the Java class supporting the in-line type is generated. Java mapping of elements with a default value When the element's default attribute is used the defaultValue property is added to the generated @XmlElementDecl annotation. For example, the element defined in Example 33.8, "XML Schema Element with a Default Value" results in the object factory method shown in Example 33.9, "Object Factory Method for an Element with a Default Value" . Example 33.8. XML Schema Element with a Default Value Example 33.9. Object Factory Method for an Element with a Default Value
<element name="joeFred" type="xsd:string" /> <element name="skate"> <complexType> <sequence> <element name="numWheels" type="xsd:int" /> <element name="brand" type="xsd:string" /> </sequence> </complexType> </element> public class ObjectFactory { private final static QName _ name _QNAME = new QName(" targetNamespace ", " localName "); @XmlElementDecl(namespace = " targetNamespace ", name = " localName ") public JAXBElement< type > create name ( type value); } public class ObjectFactory { private final static QName _JoeFred_QNAME = new QName("...", "joeFred"); @XmlElementDecl(namespace = "...", name = "joeFred") public JAXBElement<String> createJoeFred(String value); } JAXBElement<String> element = createJoeFred("Green"); String color = element.getValue(); <?xml version="1.0" encoding=";UTF-8"?> <wsdl:definitions name="HelloWorld" targetNamespace="http://apache.org/hello_world_soap_http" xmlns="http://schemas.xmlsoap.org/wsdl/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://apache.org/hello_world_soap_http" xmlns:x1="http://apache.org/hello_world_soap_http/types" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <wsdl:types> <schema targetNamespace="http://apache.org/hello_world_soap_http/types" xmlns="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified"><element name="sayHi"> <element name="sayHi" type="string"/> <element name="sayHiResponse" type="string"/> </schema> </wsdl:types> <wsdl:message name="sayHiRequest"> <wsdl:part element="x1:sayHi" name="in"/> </wsdl:message> <wsdl:message name="sayHiResponse"> <wsdl:part element="x1:sayHiResponse" name="out"/> </wsdl:message> <wsdl:portType name="Greeter"> <wsdl:operation name="sayHi"> <wsdl:input message="tns:sayHiRequest" name="sayHiRequest"/> <wsdl:output message="tns:sayHiResponse" name="sayHiResponse"/> </wsdl:operation> </wsdl:portType> </wsdl:definitions> <element name="size" type="xsd:int" default="7"/> @XmlElementDecl(namespace = "...", name = "size", defaultValue = "7" ) public JAXBElement<Integer> createUnionJoe(Integer value) { return new JAXBElement<Integer>(_Size_QNAME, Integer.class, null, value); }