You are viewing a plain text version of this content. The canonical link for it is here.
Posted to user@xmlbeans.apache.org by Radu Preotiuc-Pietro <ra...@bea.com> on 2008/06/13 02:13:46 UTC

RE: Same element name but different complex type

I want to come back to this to clarify the case where one wants to parse
an existing XML file, rather than create a new one (and there are two
elements with the same name but mapped to different Java packages on the
classpath).
 
Using the context typeloader, one needs to do:
 
SchemaTypeLoader stl = XmlBeans.getContextTypeLoader();
XmlOptions o = new
XmlOptions().setDocumentType(com.mysite.XMLSchema.Apparel.ItemDataFeedDo
cument.type);
com.mysite.XMLSchema.Apparel.ItemDataFeedDocument newDoc1 =
(com.mysite.XMLSchema.Apparel.ItemDataFeedDocument)stl.parse(file, null,
o);
 
Alternatively one can use separate typeloaders like this:
 
SchemaTypeLoader appareltl =
com.mysite.XMLSchema.Apparel.ItemDataFeedDocument.type.getTypeSystem();
com.mysite.XMLSchema.Apparel.ItemDataFeedDocument newDoc1 =
(com.mysite.XMLSchema.Apparel.ItemDataFeedDocument)appareltl.parse(file,
null, null);
 
Radu


________________________________

	From: Radu Preotiuc-Pietro [mailto:radup@bea.com] 
	Sent: Friday, April 25, 2008 5:43 PM
	To: user@xmlbeans.apache.org; john.gan@worldofgoodinc.com
	Subject: RE: Same element name but different complex type
	
	
	Ok, got it. It says "some features might not work correctly".
But most will, so one can use that setup, it's just trickier.
	 
	Sure you can dynamically load the schemas at runtime, if that's
what you want. Of course, if you do that, then you won't be able to use
the generated classes. If you want to use generated classes, these
classes have to be loaded in a Java classloader, that's how Java works
(and the way to load them usually involves putting a jar file containing
the classes on the classpath). This is why I recommended that code.
	 
	If you don't know the Schemas until runtime, you can use
something like:
	 
	SchemaTypeSystem sts = XmlBeans.compileXsd(new XmlObject[] {
apparelSchema }, XmlBeans.getBuiltinTypeSystem(), null);
	XmlObject newDoc1 = sts.newInstance(sts.findDocumentType(new
QName("http://www.mysite.com/XMLSchema", "ItemDataFeed")), null);
	 
	But at this point, you would need to use XmlCursor because there
are no generated classes that Java knows of, like I said.
	 
	Radu


________________________________

		From: John Gan [mailto:john.gan@worldofgoodinc.com] 
		Sent: Friday, April 25, 2008 11:11 AM
		To: user@xmlbeans.apache.org
		Subject: RE: Same element name but different complex
type
		
		

		Hi Radu,

		 

		Thanks for the reply.  I have another question, I don't
suppose there is a way to dynamically load the schema at runtime from a
user and still be able to probe and execute methods that are unique to
the loaded schema? In other words, the schema is not known ahead of time
nor has a jar file in the build path. Basically apply my situation of
same namespace and element name to schemas that are not known ahead of
time. Does Java's "ClassLoader" (not XmlBean's "SchemaTypeLoader") have
something to do with it? I'm still a Java rookie and don't know much
about ClassLoaders. I just wanted to be pointed in the correct direction
if Java's "ClassLoader" is the solution or XmlBean's "SchemaTypeLoader"
is the solution.

		 

		Here is the link to the wiki that says to use class
loaders when changing the package names:

		 

	
http://wiki.apache.org/xmlbeans/XmlBeansFaq#configPackageName

		 

		The last paragraph in this section says the following:

		 

		Note: XMLBeans doesn't support using two or more sets of
java classes (in different packages) mapped to schema types/elements
that have the same names and target namespaces, using all in the same
class loader. Depending on the direction you are using for the java
classes to schema types mapping, some features might not work correctly.
This is because even though the package names for the java classes are
different, the schema location for the schema metadata (.xsb files) is
the same and contains the corresponding implementing java class, so the
JVM will always pick up the first on the classpath. This can be avoided
if multiple class loaders are used.

		 

		Thanks again,

		John

		 

		
________________________________


		From: Radu Preotiuc-Pietro [mailto:radup@bea.com] 
		Sent: Thursday, April 24, 2008 7:43 PM
		To: user@xmlbeans.apache.org
		Subject: RE: Same element name but different complex
type

		 

		John,

		 

		It's actually simpler than that. But first of all, let
me ask you where on the wiki have you found the bit with using multiple
typeloaders?

		 

		I am assuming that, since you have references to
com.mysite.XMLSchema.Apparel.ItemDataFeedDocument in your code, your
classpath contains both Apparel.jar and Books.jar. In this case just do

		 

		        SchemaTypeLoader stl =
XmlBeans.getContextTypeLoader();

		and you have a SchemaTypeLoader that has access to both
types' definitions.

		 

		But here's the main trick: the findDocumentType() method
expects the QName from the Schema as its argument (new
QName("http://www.mysite.com/XMLSchema", "ItemDataFeed")) but because
the target namespace is the same, this will not work (you will not be
able to get both types, for Apparel and for Book, but only the one that
is first on the classpath)! So instead, get the Schema type directly
from its associated class:

		 

	
com.mysite.XMLSchema.Apparel.ItemDataFeedDocument newDoc1 =
(com.mysite.XMLSchema.Apparel.ItemDataFeedDocument)stl.newInstance(com.m
ysite.XMLSchema.Apparel.ItemDataFeedDocument.type, null);

		This will work and, by replacing "Apparel" with "Book"
in the package names, you can create Book items too.

		 

		Hope this helps,

		Radu

			 

			
________________________________


			From: John Gan
[mailto:john.gan@worldofgoodinc.com] 
			Sent: Tuesday, April 22, 2008 7:33 PM
			To: user@xmlbeans.apache.org
			Subject: Same element name but different complex
type

			Hi,

			 

			I'm really new to xmlbeans and I have a
question. I have 2 xsd files which have pretty much the same element
names. The only difference is that they have some complex types which
have different elements inside them but have same global element name,
e.g.:

			 

			Books.xsd would have a complex type called
ItemProperties:

			 

			                    <xs:element minOccurs="0"
name="ItemProperties">

			                      <xs:complexType>

			                        <xs:sequence>

			                          <xs:element
minOccurs="0" name="ISBN" nillable="true" type="xs:string" />

			                          <xs:element
minOccurs="0" name="Author" nillable="true" type="xs:string" />

			                          <xs:element
minOccurs="0" name="of-Pages" nillable="true" type="xs:string" />

			                          <xs:element
minOccurs="0" name="Series-Vol." nillable="true" type="xs:string" />

			                          <xs:element
minOccurs="0" name="Publisher" nillable="true" type="xs:string" />

			                        </xs:sequence>

			                      </xs:complexType>

			                    </xs:element>

			 

			Apparel.xsd would also have a complex type call
ItemProperties:

			 

			                    <xs:element minOccurs="0"
name="ItemProperties">

			                      <xs:complexType>

			                        <xs:sequence>

			                          <xs:element
minOccurs="0" name="Style" nillable="true" type="Style_Type" />

			                          <xs:element
minOccurs="0" name="Womens-Sizes" nillable="true"
type="Womens-Sizes_Type" />

			                          <xs:element
minOccurs="0" name="Sizes" nillable="true" type="Sizes_Type" />

			                          <xs:element
minOccurs="0" name="Infant-Child-sizes" nillable="true"
type="Infant-Child-sizes_Type" />

			                          <xs:element
minOccurs="0" name="Juniors-Sizes" nillable="true"
type="Juniors-Sizes_Type" />

			                        </xs:sequence>

			                      </xs:complexType>

			                    </xs:element>

			 

			They both have the same namespace and I can't
change them because that is given to me:

			 

			<?xml version="1.0" encoding="utf-8"?>

			<xs:schema
xmlns="http://www.mysite.com/XMLSchema" elementFormDefault="qualified"
targetNamespace="http://www. mysite.com/XMLSchema"
xmlns:xs="http://www.w3.org/2001/XMLSchema">

			 

			The wiki said to use multiple class loaders for
each jar to solve this issue of same namespace and element names. So I
compiled them into .jar with scomp individually since sfactor would give
me an error and I think the error is because there are complex types
with same name but different internal structure? 

			 

			I found this sample code from the mailing list
back in 2005:

			 

			        // get a SchemaTypeLoader from an array
of directories or jar
			files
			 
			        File[] schemaPath = null;
			 
			        SchemaTypeLoader stl =
	
XmlBeans.typeLoaderForResource(XmlBeans.resourceLoaderForPath(schemaPath
			));
			 
			 
			 
			        // include the built-in type system
			 
			        stl = XmlBeans.typeLoaderUnion(new
	
SchemaTypeLoader[]{XmlBeans.getBuiltinTypeSystem(), stl});
			 
			 
			 
			        // parse the document in the given 
			 
			        a.b.c.RETURNDATADocument doc =
			(a.b.c.RETURNDATADocument)stl.parse("xml", null,
null);
			 
			 
			 
			        // or create a new one, given a
schemaType
			 
			        SchemaType st = stl.findDocumentType(new
QName("a.b.c",
			"RETURNDATA"));
			 
			        a.b.c.RETURNDATADocument newDoc =
			(a.b.c.RETURNDATADocument)stl.newInstance(st,
null);

			 

			I tried to compile each xsd with the following
xsdconfig file:

			 

			For books.xsd:

			 

			<xb:config
xmlns:xb="http://xml.apache.org/xmlbeans/2004/02/xbean/config">

			 

			  <xb:namespace
uri="http://www.mysite.com/XMLSchema">

	
<xb:package>com.mysite.XMLSchema.Book</xb:package>

			  </xb:namespace>

			 

			</xb:config>

			 

			For apparel.xsd:

			 

			<xb:config
xmlns:xb="http://xml.apache.org/xmlbeans/2004/02/xbean/config">

			 

			  <xb:namespace
uri="http://www.mysite.com/XMLSchema">

	
<xb:package>com.mysite.XMLSchema.Apparel</xb:package>

			  </xb:namespace>

			 

			</xb:config>

			 

			And this is my source code:

			 

			import java.io.File;

			import javax.xml.namespace.QName;

			import org.apache.xmlbeans.SchemaType;

			import org.apache.xmlbeans.SchemaTypeLoader;

			import org.apache.xmlbeans.XmlBeans;

			import org.apache.xmlbeans.XmlException;

			import
com.mysite.XMLSchema.Apparel.ItemDataFeedDocument;

			 

			 

			public class Test {

			 

			      /**

			       * @param args

			       * @throws XmlException 

			       */

			      public static void main(String[] args) {

			 

			            File[] schemaPath = {new
File("Apparel.jar"), new File("Books.jar")};

			        SchemaTypeLoader stl =
XmlBeans.typeLoaderForResource(XmlBeans.resourceLoaderForPath(schemaPath
));

			 

			        stl = XmlBeans.typeLoaderUnion(new
SchemaTypeLoader[]{XmlBeans.getBuiltinTypeSystem(), stl});        

			        

			        SchemaType st = stl.findDocumentType(new
QName("com.mysite.XMLSchema.Apparel", "ItemDataFeed"));

			 

	
com.mysite.XMLSchema.Apparel.ItemDataFeedDocument newDoc1 =
(com.mysite.XMLSchema.Apparel.ItemDataFeedDocument)stl.newInstance(st,
null);

	
com.mysite.XMLSchema.Accessories.ItemDataFeedDocument newDoc2 =
(com.mysite.XMLSchema.Accessories.ItemDataFeedDocument)stl.newInstance(s
t, null);

			        

	
com.mysite.XMLSchema.Apparel.ItemDataFeedDocument.ItemDataFeed apparel =
newDoc1.addNewItemDataFeed();

	
com.mysite.XMLSchema.Apparel.ItemDataFeedDocument.ItemDataFeed.Items
apparelItems = apparel.addNewItems();

	
com.mysite.XMLSchema.Apparel.ItemDataFeedDocument.ItemDataFeed.Items.Ite
m aItem = apparelItems.addNewItem();

	
com.mysite.XMLSchema.Apparel.ItemDataFeedDocument.ItemDataFeed.Items.Ite
m.ItemProperties itemProp = aItem.addNewItemProperties();

	
itemProp.setAge(com.mysite.XMLSchema.Apparel.AgeType.TEEN);

			        

			        System.out.println(newDoc1.toString());

			      }

			}

			 

			 

			But SchemaType st would just return null? What
am I doing wrong and is there a better solution to the problem? I just
want to be able to create new instances of the xmlbean classes that have
the same namespace and element name (but different internal structures
for the complex types). Then set some values for the elements and write
to file.

			 

			Any help is greatly appreciated.

			John


		Notice: This email message, together with any
attachments, may contain information of BEA Systems, Inc., its
subsidiaries and affiliated entities, that may be confidential,
proprietary, copyrighted and/or legally privileged, and is intended
solely for the use of the individual or entity named in this message. If
you are not the intended recipient, and have received this message in
error, please immediately return this by email and then delete it.


	Notice: This email message, together with any attachments, may
contain information of BEA Systems, Inc., its subsidiaries and
affiliated entities, that may be confidential, proprietary, copyrighted
and/or legally privileged, and is intended solely for the use of the
individual or entity named in this message. If you are not the intended
recipient, and have received this message in error, please immediately
return this by email and then delete it.


Notice:  This email message, together with any attachments, may contain information  of  BEA Systems,  Inc.,  its subsidiaries  and  affiliated entities,  that may be confidential,  proprietary,  copyrighted  and/or legally privileged, and is intended solely for the use of the individual or entity named in this message. If you are not the intended recipient, and have received this message in error, please immediately return this by email and then delete it.