If you will be writing Java code that handles XML, you can use XMLBeans. XMLBeans provides two models for accessing XML: strongly typed access through types compiled from schema, and a cursor-based model that is an alternative to using DOM-based access. This topic focuses on using compiled types; for information about using cursors, see Navigating XML with Cursors. (For an introduction to XMLBeans, be sure to read Getting Started with XMLBeans.)
Note: For information on compiling schema, see How Do I: Use XML Schema in WebLogic Workshop? If you don't have schema, you can use a third-party XML authoring tool like Altova's XMLSpy to generate one. For more information, see How Do I: Generate Schema from an XML Instance Document?
Note: WebLogic Workshop also provides XQuery maps, through which you can control how XML messages are mapped to the Java arguments and return value of a method or callback. For more information, see Introduction to XQuery Maps.
If you have a schema for the XML, you can compile the schema to generate an object model that represents the schema. After binding the XML to the object model, the XML is available through JavaBeans-style accessors such as get* and set* methods. With types generated from schema, you can use generated types as method parameters and return types.
If the incoming XML instance conforms to the schema from which the type was generated, WebLogic Workshop will automatically bind the incoming instance to the generated type. When using generated types as parameter and return types, be sure that the type is a "Document" type (generated from a global element) or a named schema type.
For example, imagine you have the following XML instance and the schema that it conforms to.
<xq:employees xmlns:xq="http://openuri.org/bea/samples/workshop/xmlmap/consolidateAddress"> <xq:employee> <xq:name>Fred Jones</xq:name> <xq:address location="home"> <xq:street>900 Aurora Ave.</xq:street> <xq:city>Seattle</xq:city> <xq:state>WA</xq:state> <xq:zip>98115</xq:zip> </xq:address> <xq:phone location="work">(425)555-5665</xq:phone> <xq:phone location="home">(206)555-5555</xq:phone> </xq:employee> <xq:employee> <xq:name>Sally Smith</xq:name> <xq:address location="home"> <xq:street>1430 Oak Place</xq:street> <xq:city>Salem</xq:city> <xq:state>OR</xq:state> <xq:zip>97125</xq:zip> </xq:address> <xq:phone location="work">(503)555-3856</xq:phone> <xq:phone location="home">(503)555-6951</xq:phone> </xq:employee> </xq:employees>
Having compiled the schema in a WebLogic Workshop schema project, your code would have access to types generated specifically for accessing XML based on that schema. You could write the following web service operation designed to add a new telephone number, then return the updated XML. In this example, the EmployeesDocument (used as both a parameter type and the return type) was generated from the schema to represent the document's root element.
/** * Pass in the name of the employee who has a new phone number, * the location for the phone number, and the number itself. Also * pass in the XML that contains employee data, so that it can be * searched (with XQuery) for the employee whose information should be * updated. * * @common:operation */ public EmployeesDocument updateEmployee(String empName, String location, String phoneNumber, EmployeesDocument empDoc) { // Composed an XPath expression that will look for the employee by name. String namespaceDecl = "declare namespace emp='http://openuri.org/bea/samples/workshop/xmlmap/consolidateAddress'"; String queryText = "$this/emp:employees/emp:employee[emp:name = '" + empName + "']"; /* * Execute the XPath expression with the selectPath method, looking for * Fred's information. The return value is an array of all matching * employee elements, but there's only one in this case. */ EmployeeType[] fredJoneses = (EmployeeType[])empDoc.selectPath(namespaceDecl + queryText); /* * Loop through the returned values, inserting the new element * for each one. Note that the "setLocation" and "set" methods * were generated from the schema to make it possible access the XML. */ for (int i = 0; i < fredJoneses.length; i++) { EmployeeType fredJones = fredJoneses[i]; PhoneType newPhone = fredJones.addNewPhone(); newPhone.setLocation(location); newPhone.set(phoneNumber); } // Return the updated document. return empDoc; }
If you had the schema, but expected that the incoming XML might be one of several generated types, you could intercept it by making the parameter type XmlObject, the base type for all generated types. You could then check to see which type your code had received, then cast the incoming XML to that type.
public EmployeesDocument getInfo(String empName, String location, String phoneNumber, XmlObject empDoc) { // Create a document to return, in case the incoming XML matches. EmployeesDocument responseDoc = EmployeesDocument.Factory.newInstance(); // Find out if the incoming XML matches the type you care about. if (empDoc instanceof EmployeesDocument) { // If it matches, assign it to the response type, and carry on as before. responseDoc = (EmployeesDocument)empDoc; ... code as above ... } return responseDoc; }