users@jaxb.java.net

How to use XML objects as members of other XML objects?

From: Yakov Polonsky <ypolonsky_at_MARKETSWITCH.COM>
Date: Wed, 07 May 2003 15:54:56 -0600

I need a help to solve of to find the work around the following problem:
(This is just a sample to demonstrate)

Schema TEXTB.xsd : (notice that TESTB_type includes element of TESTA_type as a member)
-------------------------
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" >

  <xs:element name="TESTB" type="TESTB_type" />
  <xs:element name="TESTA" type="TESTA_type" />

  <xs:complexType name="TESTA_type">
    <xs:sequence>
      <xs:element name="x" type="xs:int" />
      <xs:element name="y" type="xs:int" />
    </xs:sequence>
  </xs:complexType>

  <xs:complexType name="TESTB_type">
    <xs:sequence>
      <xs:element name="z" type="xs:int" />
      <xs:element name="innertest" type="TESTA_type"/>
    </xs:sequence>
  </xs:complexType>

</xs:schema>
-------------------------

I generated java files into the "generated" package.

Test source InnerTest.java :
-------------------------
import generated.ObjectFactory;
import generated.TESTA;
import generated.TESTB;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;

public class InnerTest
{
   public static void main(String[] args)
   {
      try
      {
         JAXBContext jaxbContext =JAXBContext.newInstance("generated");

         ObjectFactory factory = new ObjectFactory();
         TESTA beanA = factory.createTESTA();
         beanA.setX(5);
         beanA.setY(6);

         TESTB beanB = factory.createTESTB();
         beanB.setZ(0);
         beanB.setInnertest(beanA);

         // create a Marshaller and marshal to a file
         Marshaller m = jaxbContext.createMarshaller();
         m.setProperty( Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE );
         m.marshal( beanB, System.out );
      }
      catch (javax.xml.bind.JAXBException e) { e.printStackTrace(); }
   }
}
-------------------------

Output after compiling and running (I added indents for readability):
-------------------------
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<TESTB>
   <z>0</z>
   <TESTA>
      <x>5</x>
      <y>6</y>
   </TESTA>
</TESTB>
-------------------------

The problem is that instead of <innertest>...</innertest> node Marshaller added <TESTA>...</TESTA>. So the output xml is invalid and validator will failed.

Looking at serializeElements() of the TESTBType implementation class I see that I can not pass TESTA object into the setInnertest() method of TESTB object. I need to create TESTAType object for that.
(replace
               TESTA beanA = factory.createTESTA();
 with
               TESTAType beanA = factory.createTESTAType();
 and everything works)

So my questions are:

1. Why can't I use TESTA object instead of TESTAType one? Nothing prevents me to create invalid output.

2. If I can't use TESTA object how can I "extract" TESTAType object from TESTA one (without copying by members)? In real code, TESTA is a complex object that I receive from the server. TESTB is another complex object that I send back to the server.

3. Any idea how to approach this problem if "this is not a bug, but a feature"?

Thank you,
Yakov Polonsky
ypolonsky_at_marketswitch.com