[jboss-svn-commits] JBoss Common SVN: r2048 - in jbossxb/trunk: . src src/test src/test/java src/test/java/org src/test/java/org/jboss src/test/java/org/jboss/test src/test/java/org/jboss/test/xml src/test/resources src/test/resources/org src/test/resources/org/jboss src/test/resources/org/jboss/test src/test/resources/org/jboss/test/xml

jboss-svn-commits at lists.jboss.org jboss-svn-commits at lists.jboss.org
Thu Sep 21 03:19:29 EDT 2006


Author: alex.loubyansky at jboss.com
Date: 2006-09-21 03:19:23 -0400 (Thu, 21 Sep 2006)
New Revision: 2048

Added:
   jbossxb/trunk/src/test/
   jbossxb/trunk/src/test/java/
   jbossxb/trunk/src/test/java/org/
   jbossxb/trunk/src/test/java/org/jboss/
   jbossxb/trunk/src/test/java/org/jboss/test/
   jbossxb/trunk/src/test/java/org/jboss/test/xml/
   jbossxb/trunk/src/test/java/org/jboss/test/xml/AbstractJBossXBTest.java
   jbossxb/trunk/src/test/java/org/jboss/test/xml/JBossXBTestDelegate.java
   jbossxb/trunk/src/test/java/org/jboss/test/xml/RepeatableTermsUnitTestCase.java
   jbossxb/trunk/src/test/java/org/jboss/test/xml/XmlDiff.java
   jbossxb/trunk/src/test/resources/
   jbossxb/trunk/src/test/resources/org/
   jbossxb/trunk/src/test/resources/org/jboss/
   jbossxb/trunk/src/test/resources/org/jboss/test/
   jbossxb/trunk/src/test/resources/org/jboss/test/xml/
   jbossxb/trunk/src/test/resources/org/jboss/test/xml/RepeatableTermsUnitTestCase_testUnmarshal1.xml
   jbossxb/trunk/src/test/resources/org/jboss/test/xml/RepeatableTermsUnitTestCase_testUnmarshal1.xsd
   jbossxb/trunk/src/test/resources/org/jboss/test/xml/RepeatableTermsUnitTestCase_testUnmarshal2.xml
   jbossxb/trunk/src/test/resources/org/jboss/test/xml/RepeatableTermsUnitTestCase_testUnmarshal2.xsd
Modified:
   jbossxb/trunk/pom.xml
Log:
first local test

Modified: jbossxb/trunk/pom.xml
===================================================================
--- jbossxb/trunk/pom.xml	2006-09-20 21:34:53 UTC (rev 2047)
+++ jbossxb/trunk/pom.xml	2006-09-21 07:19:23 UTC (rev 2048)
@@ -113,6 +113,11 @@
       <version>1.0</version>
     </dependency>
     <dependency>
+      <groupId>jboss.logging.log4j</groupId>
+      <artifactId>jboss-logging-log4j</artifactId>
+      <version>1.0</version>
+    </dependency>
+    <dependency>
       <groupId>jboss.common.core</groupId>
       <artifactId>jboss-common-core</artifactId>
       <version>1.0</version>
@@ -148,6 +153,18 @@
       <version>1.2.1</version>
       <scope>compile</scope>
     </dependency>         
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <version>3.8.1</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>jboss.jboss-test</groupId>
+      <artifactId>jboss-test</artifactId>
+      <version>1.0.0.CR1</version>
+      <scope>test</scope>
+    </dependency>
   </dependencies>  
 
 </project>

Added: jbossxb/trunk/src/test/java/org/jboss/test/xml/AbstractJBossXBTest.java
===================================================================
--- jbossxb/trunk/src/test/java/org/jboss/test/xml/AbstractJBossXBTest.java	2006-09-20 21:34:53 UTC (rev 2047)
+++ jbossxb/trunk/src/test/java/org/jboss/test/xml/AbstractJBossXBTest.java	2006-09-21 07:19:23 UTC (rev 2048)
@@ -0,0 +1,192 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2006, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.test.xml;
+
+import java.net.URL;
+
+import org.jboss.test.AbstractTestCaseWithSetup;
+import org.jboss.test.AbstractTestDelegate;
+import org.jboss.util.Classes;
+import org.jboss.xb.binding.sunday.unmarshalling.SchemaBindingResolver;
+
+/**
+ * AbstractJBossXBTest.
+ * 
+ * @author <a href="adrian at jboss.com">Adrian Brock</a>
+ * @version $Revision: 45077 $
+ */
+public class AbstractJBossXBTest extends AbstractTestCaseWithSetup
+{
+   private static final XmlDiff DIFF = new XmlDiff();
+
+   protected String rootName = getRootName();
+   
+   /**
+    * Create a new AbstractJBossXBTest.
+    * 
+    * @param name the name of the test
+    */
+   public AbstractJBossXBTest(String name)
+   {
+      super(name);
+   }
+
+   public void assertXmlEqual(String expected, String was)
+   {
+      String diff = DIFF.diff(expected, was);
+      if(diff != null)
+      {
+         fail(diff);
+      }
+   }
+
+   /**
+    * Unmarshal some xml
+    * 
+    * @param name the name
+    * @param expected the expected type
+    * @return the unmarshalled object
+    * @throws Exception for any error
+    */
+   protected Object unmarshal(String name, Class expected) throws Exception
+   {
+      Object object = unmarshal(name);
+      if (object == null)
+         fail("No object from " + name);
+      assertTrue("Object '" + object + "' cannot be assigned to " + expected.getName(), expected.isAssignableFrom(object.getClass()));
+      return object;
+   }
+   
+   /**
+    * Unmarshal some xml
+    * 
+    * @param name the name
+    * @param expected the expected type
+    * @param resolver the resolver
+    * @return the unmarshalled object
+    * @throws Exception for any error
+    */
+   protected Object unmarshal(String name, Class expected, SchemaBindingResolver resolver) throws Exception
+   {
+      Object object = unmarshal(name, resolver);
+      if (object == null)
+         fail("No object from " + name);
+      assertTrue("Object '" + object + "' cannot be assigned to " + expected.getName(), expected.isAssignableFrom(object.getClass()));
+      return object;
+   }
+   
+   /**
+    * Unmarshal some xml
+    * 
+    * @param name the name
+    * @return the unmarshalled object
+    * @throws Exception for any error
+    */
+   protected Object unmarshal(String name) throws Exception
+   {
+      return unmarshal(name, (SchemaBindingResolver) null);
+   }
+   
+   /**
+    * Unmarshal some xml
+    * 
+    * @param name the name
+    * @return the unmarshalled object
+    * @throws Exception for any error
+    */
+   protected Object unmarshal(String name, SchemaBindingResolver resolver) throws Exception
+   {
+      String url = findXML(name);
+      return getJBossXBDelegate().unmarshal(url, resolver);
+   }
+   
+   /**
+    * Find the xml
+    * 
+    * @param name the name
+    * @return the url of the xml
+    */
+   protected String findXML(String name)
+   {
+      URL url = getResource(name);
+      if (url == null)
+         fail(name + " not found");
+      return url.toString();
+   }
+   
+   /**
+    * Get a schema location
+    * 
+    * @param clazz used to get the package
+    * @param schema the schema name
+    * @return the location in the "classpath"
+    */
+   protected static String getSchemaLocation(Class clazz, String schema)
+   {
+      String packageName = Classes.getPackageName(clazz);
+      packageName = packageName.replace('.', '/');
+      String name = packageName + '/' + schema;
+      return name;
+   }
+
+   /**
+    * Setup the test delegate
+    * 
+    * @param clazz the class
+    * @return the delegate
+    * @throws Exception for any error
+    */
+   public static AbstractTestDelegate getDelegate(Class clazz) throws Exception
+   {
+      return new JBossXBTestDelegate(clazz);
+   }
+
+   protected JBossXBTestDelegate getJBossXBDelegate()
+   {
+      return (JBossXBTestDelegate) getDelegate();
+   }
+   
+   protected void setUp() throws Exception
+   {
+      super.setUp();
+      configureLogging();
+   }
+   
+   /**
+    * Get the package root name
+    * 
+    * @return the root name
+    */
+   protected String getRootName()
+   {
+      String longName = getClass().getName();
+      int dot = longName.lastIndexOf('.');
+      if (dot != -1)
+         return longName.substring(dot + 1);
+      return longName;
+   }
+   
+   protected void configureLogging()
+   {
+      //enableTrace("org.jboss.xb");
+   }
+}

Added: jbossxb/trunk/src/test/java/org/jboss/test/xml/JBossXBTestDelegate.java
===================================================================
--- jbossxb/trunk/src/test/java/org/jboss/test/xml/JBossXBTestDelegate.java	2006-09-20 21:34:53 UTC (rev 2047)
+++ jbossxb/trunk/src/test/java/org/jboss/test/xml/JBossXBTestDelegate.java	2006-09-21 07:19:23 UTC (rev 2048)
@@ -0,0 +1,128 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2006, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.test.xml;
+
+import java.lang.reflect.Method;
+import java.net.URL;
+
+import org.jboss.net.protocol.URLStreamHandlerFactory;
+import org.jboss.test.AbstractTestDelegate;
+import org.jboss.xb.binding.Unmarshaller;
+import org.jboss.xb.binding.UnmarshallerFactory;
+import org.jboss.xb.binding.sunday.unmarshalling.DefaultSchemaResolver;
+import org.jboss.xb.binding.sunday.unmarshalling.SchemaBindingResolver;
+
+/**
+ * JBossXBTestDelegate.
+ * 
+ * @author <a href="adrian at jboss.com">Adrian Brock</a>
+ * @version $Revision: 40492 $
+ */
+public class JBossXBTestDelegate extends AbstractTestDelegate
+{
+   /** Whether initialization has been done */
+   private static boolean done = false;
+
+   /** The unmarshaller factory */
+   protected UnmarshallerFactory unmarshallerFactory;
+
+   /** The resolver */
+   protected SchemaBindingResolver defaultResolver;
+   
+   /**
+    * Initialize
+    */
+   public synchronized static void init()
+   {
+      if (done)
+         return;
+      done = true;
+      URL.setURLStreamHandlerFactory(new URLStreamHandlerFactory());
+      URLStreamHandlerFactory.preload();
+      String handlerPkgs = System.getProperty("java.protocol.handler.pkgs");
+      if (handlerPkgs != null)
+         handlerPkgs += "|org.jboss.net.protocol";
+      else
+         handlerPkgs = "org.jboss.net.protocol";
+      System.setProperty("java.protocol.handler.pkgs", handlerPkgs);
+   }
+
+   /**
+    * Create a new JBossXBTestDelegate.
+    * 
+    * @param clazz the test class
+    */
+   public JBossXBTestDelegate(Class clazz)
+   {
+      super(clazz);
+   }
+
+   public void setUp() throws Exception
+   {
+      super.setUp();
+      init();
+      unmarshallerFactory = UnmarshallerFactory.newInstance();
+      initResolver();
+   }
+   
+   protected void initResolver() throws Exception
+   {
+      try
+      {
+         Method method = clazz.getMethod("initResolver", null);
+         defaultResolver = (SchemaBindingResolver) method.invoke(null, null);
+      }
+      catch (NoSuchMethodException ignored)
+      {
+         defaultResolver = new DefaultSchemaResolver();
+      }
+   }
+   
+   /**
+    * Unmarshal an object
+    * 
+    * @param url the url
+    * @param resolver the resolver
+    * @return the object
+    * @throws Exception for any error
+    */
+   public Object unmarshal(String url, SchemaBindingResolver resolver) throws Exception
+   {
+      if (resolver == null)
+         resolver = defaultResolver;
+      
+      long start = System.currentTimeMillis();
+      Unmarshaller unmarshaller = unmarshallerFactory.newUnmarshaller();
+      log.debug("Initialized parsing in " + (System.currentTimeMillis() - start) + "ms");
+      try
+      {
+         Object result = unmarshaller.unmarshal(url, resolver);
+         log.debug("Total parse for " + url + " took " + (System.currentTimeMillis() - start) + "ms");
+         return result;
+      }
+      catch (Exception e)
+      {
+         log.debug("Error during parsing: " + url, e);
+         throw e;
+      }
+   }
+}

Added: jbossxb/trunk/src/test/java/org/jboss/test/xml/RepeatableTermsUnitTestCase.java
===================================================================
--- jbossxb/trunk/src/test/java/org/jboss/test/xml/RepeatableTermsUnitTestCase.java	2006-09-20 21:34:53 UTC (rev 2047)
+++ jbossxb/trunk/src/test/java/org/jboss/test/xml/RepeatableTermsUnitTestCase.java	2006-09-21 07:19:23 UTC (rev 2048)
@@ -0,0 +1,240 @@
+/*
+  * JBoss, Home of Professional Open Source
+  * Copyright 2005, JBoss Inc., and individual contributors as indicated
+  * by the @authors tag. See the copyright.txt in the distribution for a
+  * full listing of individual contributors.
+  *
+  * This is free software; you can redistribute it and/or modify it
+  * under the terms of the GNU Lesser General Public License as
+  * published by the Free Software Foundation; either version 2.1 of
+  * the License, or (at your option) any later version.
+  *
+  * This software is distributed in the hope that it will be useful,
+  * but WITHOUT ANY WARRANTY; without even the implied warranty of
+  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  * Lesser General Public License for more details.
+  *
+  * You should have received a copy of the GNU Lesser General Public
+  * License along with this software; if not, write to the Free
+  * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+  * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+  */
+package org.jboss.test.xml;
+
+import java.util.Arrays;
+import org.jboss.xb.binding.sunday.unmarshalling.XsdBinder;
+import org.jboss.xb.binding.sunday.unmarshalling.SchemaBinding;
+import org.jboss.xb.binding.sunday.unmarshalling.SchemaBindingResolver;
+import org.jboss.xb.binding.Unmarshaller;
+import org.jboss.xb.binding.UnmarshallerFactory;
+
+/**
+ * @author <a href="mailto:alex at jboss.org">Alexey Loubyansky</a>
+ * @version <tt>$Revision: $</tt>
+ */
+public class RepeatableTermsUnitTestCase
+   extends AbstractJBossXBTest
+{  
+   public RepeatableTermsUnitTestCase(String name)
+   {
+      super(name);
+   }
+
+   protected void configureLogging()
+   {
+      //enableTrace("org.jboss.xb.binding.sunday");
+      //enableTrace("org.jboss.xb.binding.sunday.unmarshalling.SequenceBinding");
+      //enableTrace("org.jboss.xb.binding.sunday.unmarshalling.ChoiceBinding");
+   }
+
+   public void testUnmarshal1() throws Exception
+   {
+      Object o = unmarshal();
+
+      assertNotNull(o);
+      assertTrue(o instanceof Top);
+      Top top = (Top)o;
+
+      assertNotNull(top.item);
+      assertEquals(3, top.item.length);
+      assertEquals(new String[]{"item1", "item2", "item3"}, top.item);
+
+      assertNotNull(top.sequence);
+      //assertEquals(5, top.sequence.length);
+      assertEquals(
+         new Sequence[]
+         {
+            new Sequence("sequenceChoice1_1", null),
+            new Sequence(null, "sequenceChoice2_1"),
+            new Sequence("sequenceChoice1_2", null),
+            new Sequence("sequenceChoice1_3", null),
+            new Sequence(null, "sequenceChoice2_2")
+         },
+         top.sequence
+      );
+
+      assertNotNull(top.choice);
+      assertEquals(3, top.choice.length);
+      assertEquals(
+         new Choice[]
+         {
+            new Choice(new String[]{"choiceChoice1_1", "choiceChoice1_2"}, null),
+            new Choice(null, new String[]{"choiceChoice2_1", "choiceChoice2_2"}),
+            new Choice(new String[]{"choiceChoice1_3", "choiceChoice1_4"}, null),
+         },
+         top.choice
+      );
+   }
+
+   public void testUnmarshal2() throws Exception
+   {
+      Object o = unmarshal();
+      assertNotNull(o);
+      assertTrue(o instanceof Top);
+      Top top = (Top)o;
+
+      assertNull(top.item);
+      assertNull(top.choice);
+      assertNull(top.sequence);
+      
+      assertEquals("item1", top.item1);
+      assertEquals("item2", top.item2);
+   }
+   
+   private Object unmarshal() throws Exception
+   {
+      String testXsd = findXML(rootName + "_" + getName() + ".xsd");
+      SchemaBinding schema = XsdBinder.bind(testXsd, (SchemaBindingResolver)null);
+      schema.setIgnoreUnresolvedFieldOrClass(false);
+
+      Unmarshaller unmarshaller = UnmarshallerFactory.newInstance().newUnmarshaller();
+      return unmarshaller.unmarshal(findXML(rootName + "_" + getName() + ".xml"), schema);
+   }
+
+   // Inner
+
+   public static final class Top
+   {
+      public String[] item;
+      public Sequence[] sequence;
+      public Choice[] choice;
+
+      public String item1;
+      public String item2;
+      
+      public String toString()
+      {
+         return "[top item=" + (item == null ? null : Arrays.asList(item)) +
+            " sequence=" + (sequence == null ? null : Arrays.asList(sequence)) +
+            " choice=" + (choice == null ? null : Arrays.asList(choice)) +
+            " item1=" + item1 + " item2=" + item2 + "]";
+      }
+   }
+
+   public static final class Sequence
+   {
+      public String sequenceChoice1;
+      public String sequenceChoice2;
+
+      public Sequence()
+      {
+      }
+
+      public Sequence(String sequenceChoice1, String sequenceChoice2)
+      {
+         this.sequenceChoice1 = sequenceChoice1;
+         this.sequenceChoice2 = sequenceChoice2;
+      }
+
+      public String toString()
+      {
+         return "[" + sequenceChoice1 + " " + sequenceChoice2 + "]";
+      }
+
+      public boolean equals(Object o)
+      {
+         if(this == o)
+         {
+            return true;
+         }
+         if(!(o instanceof Sequence))
+         {
+            return false;
+         }
+
+         final Sequence sequence = (Sequence)o;
+
+         if(sequenceChoice1 != null ? !sequenceChoice1.equals(sequence.sequenceChoice1) : sequence.sequenceChoice1 != null)
+         {
+            return false;
+         }
+         if(sequenceChoice2 != null ? !sequenceChoice2.equals(sequence.sequenceChoice2) : sequence.sequenceChoice2 != null)
+         {
+            return false;
+         }
+
+         return true;
+      }
+
+      public int hashCode()
+      {
+         int result;
+         result = (sequenceChoice1 != null ? sequenceChoice1.hashCode() : 0);
+         result = 29 * result + (sequenceChoice2 != null ? sequenceChoice2.hashCode() : 0);
+         return result;
+      }
+   }
+
+   public static final class Choice
+   {
+      public String[] choiceChoice1;
+      public String[] choiceChoice2;
+
+      public Choice()
+      {
+      }
+
+      public Choice(String[] choiceChoice1, String[] choiceChoice2)
+      {
+         this.choiceChoice1 = choiceChoice1;
+         this.choiceChoice2 = choiceChoice2;
+      }
+
+      public String toString()
+      {
+         return "[" +
+            (choiceChoice1 == null ? null : Arrays.asList(choiceChoice1)) +
+            " " + (choiceChoice2 == null ? null : Arrays.asList(choiceChoice2)) + "]";
+      }
+
+      public boolean equals(Object o)
+      {
+         if(this == o)
+         {
+            return true;
+         }
+         if(!(o instanceof Choice))
+         {
+            return false;
+         }
+
+         final Choice choice = (Choice)o;
+
+         if(!Arrays.equals(choiceChoice1, choice.choiceChoice1))
+         {
+            return false;
+         }
+         if(!Arrays.equals(choiceChoice2, choice.choiceChoice2))
+         {
+            return false;
+         }
+
+         return true;
+      }
+
+      public int hashCode()
+      {
+         return 0;
+      }
+   }
+}

Added: jbossxb/trunk/src/test/java/org/jboss/test/xml/XmlDiff.java
===================================================================
--- jbossxb/trunk/src/test/java/org/jboss/test/xml/XmlDiff.java	2006-09-20 21:34:53 UTC (rev 2047)
+++ jbossxb/trunk/src/test/java/org/jboss/test/xml/XmlDiff.java	2006-09-21 07:19:23 UTC (rev 2048)
@@ -0,0 +1,686 @@
+/*
+  * JBoss, Home of Professional Open Source
+  * Copyright 2005, JBoss Inc., and individual contributors as indicated
+  * by the @authors tag. See the copyright.txt in the distribution for a
+  * full listing of individual contributors.
+  *
+  * This is free software; you can redistribute it and/or modify it
+  * under the terms of the GNU Lesser General Public License as
+  * published by the Free Software Foundation; either version 2.1 of
+  * the License, or (at your option) any later version.
+  *
+  * This software is distributed in the hope that it will be useful,
+  * but WITHOUT ANY WARRANTY; without even the implied warranty of
+  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  * Lesser General Public License for more details.
+  *
+  * You should have received a copy of the GNU Lesser General Public
+  * License along with this software; if not, write to the Free
+  * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+  * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+  */
+package org.jboss.test.xml;
+
+import java.io.StringReader;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import javax.xml.namespace.QName;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import org.w3c.dom.Attr;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.w3c.dom.Text;
+import org.xml.sax.EntityResolver;
+import org.xml.sax.ErrorHandler;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXParseException;
+import org.jboss.xb.binding.Constants;
+
+/**
+ * @author <a href="mailto:alex at jboss.org">Alexey Loubyansky</a>
+ * @version <tt>$Revision: 45494 $</tt>
+ */
+public class XmlDiff
+{
+   public static final ErrorHandler ERROR_HANDLER = new DefErrorHandler();
+
+   public static final byte PRINT_ELEMENT = 0;
+   public static final byte PRINT_PARENT = 1;
+   public static final byte PRINT_ALL = 2;
+
+   private static final DocumentBuilderFactory FACTORY = DocumentBuilderFactory.newInstance();
+   static
+   {
+      FACTORY.setNamespaceAware(true);
+      FACTORY.setValidating(true);
+   }
+
+   private static final String INDENT = "  ";
+
+   public static void main(String[] args) throws Exception
+   {
+      String xml1 =
+         "<ns1:e xmlns:ns1='http://ns' attr1='attr1_val' ns1:attr2='attr2_val'>\n" +
+         "  <ns1:child1>\n" +
+         "     <ns2:child2 xmlns:ns2='http://ns2' child2_attr='child2_attr_val'>child2_val</ns2:child2>\n" +
+         "  </ns1:child1>\n" +
+         "  text\n" +
+         "</ns1:e>";
+
+      String xml2 =
+         "<e xmlns='http://ns' attr1='attr1_val'" +
+         " xmlns:ns='http://ns' ns:attr2='attr2_val'>text" +
+         " <child1>" +
+         "   <child2 xmlns='http://ns2' child2_attr='child2_attr_val'>child2_val</child2>" +
+         " </child1>" +
+         "</e>";
+
+      System.out.println(new XmlDiff().diff(xml1, xml2));
+   }
+
+   public XmlDiff()
+   {
+      this(PRINT_ALL, true);
+   }
+
+   public XmlDiff(byte print, boolean reformat)
+   {
+      this.print = print;
+      this.reformat = reformat;
+   }
+
+   private byte print = PRINT_ALL;
+   private boolean reformat = true;
+
+   public byte getPrint()
+   {
+      return print;
+   }
+
+   public void setPrint(byte print)
+   {
+      this.print = print;
+   }
+
+   public boolean isReformat()
+   {
+      return reformat;
+   }
+
+   public void setReformat(boolean reformat)
+   {
+      this.reformat = reformat;
+   }
+
+   /**
+    * Compares two XML contents and returns a diff if they are different or null if they are equal.
+    *
+    * @param expected expected XML content
+    * @param was      actual XML content
+    * @return difference between XML contents or null if the contents are equal
+    */
+   public String diff(String expected, String was)
+   {
+      return diff(expected, was, ERROR_HANDLER, null);
+   }
+
+   public String diff(String expected, String was, ErrorHandler eh)
+   {
+      return diff(expected, was, eh, null);
+   }
+
+   public String diff(String expected, String was, EntityResolver er)
+   {
+      return diff(expected, was, ERROR_HANDLER, er);
+   }
+
+   public String diff(String expected, String was, ErrorHandler eh, EntityResolver er)
+   {
+      DocumentBuilder documentBuilder = null;
+      try
+      {
+         documentBuilder = FACTORY.newDocumentBuilder();
+      }
+      catch(ParserConfigurationException e)
+      {
+         throw new IllegalStateException("Failed to create a document builder: " + e.getMessage());
+      }
+
+      if(eh != null)
+      {
+         documentBuilder.setErrorHandler(eh);
+      }
+
+      if(er != null)
+      {
+         documentBuilder.setEntityResolver(er);
+      }
+
+      Document expDoc = null;
+      try
+      {
+         expDoc = documentBuilder.parse(new InputSource(new StringReader(expected)));
+      }
+      catch(Exception e)
+      {
+         throw new IllegalStateException("Failed to parse expected XML\n" + expected + ": " + e.getMessage());
+      }
+
+      Document wasDoc = null;
+      try
+      {
+         wasDoc = documentBuilder.parse(new InputSource(new StringReader(was)));
+      }
+      catch(Exception e)
+      {
+         throw new IllegalStateException("Failed to parse XML\n" + was + ": " + e.getMessage());
+      }
+
+      Element expElement = expDoc.getDocumentElement();
+      Element wasElement = wasDoc.getDocumentElement();
+      return assertEquals(expElement, wasElement, expElement, wasElement);
+   }
+
+   private String assertEquals(Element exp, Element was, Element printAsExp, Element printAsWas)
+   {
+      QName expName = new QName(exp.getNamespaceURI(), exp.getLocalName());
+      QName wasName = new QName(was.getNamespaceURI(), was.getLocalName());
+
+      if(!expName.equals(wasName))
+      {
+         return fail("Expected name " + expName + " but was " + wasName, exp, was);
+      }
+
+      NamedNodeMap expAttrs = exp.getAttributes();
+      NamedNodeMap wasAttrs = was.getAttributes();
+
+      if(expAttrs == null && wasAttrs != null && hasNonIgnorableNs(wasAttrs))
+      {
+         return fail("Element " + expName + " doesn't have attributes", printAsExp, printAsWas);
+      }
+      else if(wasAttrs == null && expAttrs != null && hasNonIgnorableNs(expAttrs))
+      {
+         return fail("Element " + expName + " has attributes", printAsExp, printAsWas);
+      }
+      else if(expAttrs != null && wasAttrs != null)
+      {
+         String msg = assertAttrs(expAttrs, wasAttrs, printAsExp);
+         if(msg != null)
+         {
+            return fail(msg, printAsExp, printAsWas);
+         }
+      }
+
+      NodeList expChildren = exp.getChildNodes();
+      NodeList wasChildren = was.getChildNodes();
+
+      NodeList expTexts = getTextNodes(expChildren);
+      NodeList wasTexts = getTextNodes(wasChildren);
+      if(expTexts.getLength() > 0 && wasTexts.getLength() == 0)
+      {
+         return fail("Element " + expName + " has text content", printAsExp, printAsWas);
+      }
+      else if(expTexts.getLength() == 0 && wasTexts.getLength() > 0)
+      {
+         return fail("Element " + expName + " doesn't have text content", printAsExp, printAsWas);
+      }
+      // todo: should text content be concatenated before comparison?
+      else if(expTexts.getLength() != wasTexts.getLength())
+      {
+         return fail(
+            "Element " + expName + " has " + expTexts.getLength() + " text nodes (was " + wasTexts.getLength() + ")",
+            printAsExp,
+            printAsWas
+         );
+      }
+      else if(expTexts.getLength() > 0 && wasTexts.getLength() > 0)
+      {
+         for(int i = 0; i < expTexts.getLength(); ++i)
+         {
+            Text text = (Text)expTexts.item(i);
+            if(!containsText(text.getNodeValue(), wasTexts, i))
+            {
+               return fail("Element " + expName + " has text '" + text.getNodeValue() + "'", printAsExp, printAsWas);
+            }
+         }
+      }
+
+      NodeList expElems = sublist(expChildren, Node.ELEMENT_NODE);
+      NodeList wasElems = sublist(wasChildren, Node.ELEMENT_NODE);
+      if(expElems.getLength() > 0 && wasElems.getLength() == 0)
+      {
+         return fail("Element " + expName + " has child elements", printAsExp, printAsWas);
+      }
+      else if(expElems.getLength() == 0 && wasElems.getLength() > 0)
+      {
+         return fail("Element " + expName + " doesn't have child elements", printAsExp, printAsWas);
+      }
+      else if(expElems.getLength() != wasElems.getLength())
+      {
+         return fail("Element " +
+            expName +
+            " has " +
+            expElems.getLength() +
+            " child elements (was " +
+            wasElems.getLength() +
+            ")",
+            printAsExp,
+            printAsWas
+         );
+      }
+      else if(expElems.getLength() > 0 && wasElems.getLength() > 0)
+      {
+         if(print == PRINT_PARENT)
+         {
+            printAsExp = exp;
+            printAsWas = was;
+         }
+
+         for(int i = 0; i < expElems.getLength(); ++i)
+         {
+            Element expChild = (Element)expElems.item(i);
+            Element wasChild = getElement(expChild.getNamespaceURI(), expChild.getLocalName(), wasElems, i);
+            if(wasChild == null)
+            {
+               return fail("Element " +
+                  expName +
+                  " has child element " +
+                  new QName(expChild.getNamespaceURI(), expChild.getLocalName()),
+                  printAsExp,
+                  printAsWas
+               );
+            }
+
+            if(print == PRINT_ELEMENT)
+            {
+               printAsExp = expChild;
+               printAsWas = wasChild;
+            }
+
+            String diff = assertEquals(expChild, wasChild, printAsExp, printAsWas);
+            if(diff != null)
+            {
+               return diff;
+            }
+         }
+      }
+      return null;
+   }
+
+   private static Element getElement(String ns, String local, NodeList elements, int suggestedIndex)
+   {
+      if(suggestedIndex >= 0 && suggestedIndex < elements.getLength())
+      {
+         Element element = (Element)elements.item(suggestedIndex);
+         if((ns == null && element.getNamespaceURI() == null ||
+            ns != null && ns.equals(element.getNamespaceURI())
+            ) &&
+            local.equals(element.getLocalName()))
+         {
+            return element;
+         }
+      }
+
+      for(int i = 0; i < elements.getLength(); ++i)
+      {
+         Element element = (Element)elements.item(i);
+         if((ns == null && element.getNamespaceURI() == null ||
+            ns != null && ns.equals(element.getNamespaceURI())
+            ) &&
+            local.equals(element.getLocalName()))
+         {
+            return element;
+         }
+      }
+      return null;
+   }
+
+   private static boolean containsText(String text, NodeList textNodes, int suggestedIndex)
+   {
+      text = text.trim();
+      if(suggestedIndex >= 0)
+      {
+         Text textNode = (Text)textNodes.item(suggestedIndex);
+         String wasText = textNode.getNodeValue().trim();
+         if(text.equals(wasText))
+         {
+            return true;
+         }
+      }
+
+      for(int i = 0; i < textNodes.getLength(); ++i)
+      {
+         Text textNode = (Text)textNodes.item(i);
+         String wasText = textNode.getNodeValue().trim();
+         if(text.equals(wasText))
+         {
+            return true;
+         }
+      }
+      return false;
+   }
+
+   private static NodeList getTextNodes(NodeList list)
+   {
+      MutableNodeList result = new MutableNodeList();
+      for(int i = 0; i < list.getLength(); ++i)
+      {
+         Node node = list.item(i);
+         if(node.getNodeType() == Node.TEXT_NODE)
+         {
+            String text = node.getNodeValue();
+            if(text.trim().length() > 0)
+            {
+               result.add(node);
+            }
+         }
+      }
+      return result;
+   }
+
+   private static NodeList sublist(NodeList list, short nodeType)
+   {
+      MutableNodeList result = new MutableNodeList();
+      for(int i = 0; i < list.getLength(); ++i)
+      {
+         Node node = list.item(i);
+         if(node.getNodeType() == nodeType)
+         {
+            result.add(node);
+         }
+      }
+      return result;
+   }
+
+   private static String assertAttrs(NamedNodeMap attrsExp,
+                                     NamedNodeMap attrsWas,
+                                     Element printAsExp)
+   {
+      String result = assertSubset(attrsExp, attrsWas, printAsExp, true);
+      if(result == null)
+      {
+         result = assertSubset(attrsWas, attrsExp, printAsExp, false);
+      }
+      return result;
+   }
+
+   private static String assertSubset(NamedNodeMap attrsSubset,
+                                      NamedNodeMap attrsSet,
+                                      Element printAsExp,
+                                      boolean checkHave)
+   {
+      String msg = checkHave ? " has attribute " : " doesn't have attribute ";
+      QName expName = new QName(printAsExp.getNamespaceURI(), printAsExp.getLocalName());
+      for(int i = 0; i < attrsSubset.getLength(); ++i)
+      {
+         Attr attr = (Attr)attrsSubset.item(i);
+         String attrNs = attr.getNamespaceURI();
+         String localName = attr.getLocalName();
+         if(xsiNs(attrNs) && "type".equals(localName))
+         {
+            Attr wasAttr = (Attr)attrsSet.getNamedItemNS(attrNs, localName);
+            if(wasAttr == null)
+            {
+               return "Element " + expName + msg + new QName(attrNs, localName);
+            }
+
+            String typeName = attr.getValue();
+            int colon = typeName.indexOf(':');
+            if(colon != -1)
+            {
+               typeName = typeName.substring(colon);
+            }
+
+            if(!wasAttr.getValue().endsWith(typeName))
+            {
+               return "Element " + expName +
+                  (checkHave ? " has xsi:type " : " doesn't have xsi:type ") +
+                  attr.getValue();
+            }
+
+            //todo compare namespaces for xsi:types
+         }
+         else if(nonIgnorableNs(attrNs) || xsiNs(attrNs) && localName.equals("nil"))
+         {
+            Attr wasAttr = (Attr)attrsSet.getNamedItemNS(attrNs, localName);
+            if(wasAttr == null)
+            {
+               return "Element " + expName + msg + new QName(attrNs, localName);
+            }
+
+            if(!attr.getValue().equals(wasAttr.getValue()))
+            {
+               return "Attribute " +
+                  new QName(attrNs, localName) +
+                  " in element " +
+                  expName +
+                  " has value " + attr.getValue();
+            }
+         }
+      }      
+      return null;
+   }
+   
+   private static boolean hasNonIgnorableNs(NamedNodeMap nodeMap)
+   {
+      for(int i = 0; i < nodeMap.getLength(); ++i)
+      {
+         Node node = nodeMap.item(i);
+         if(nonIgnorableNs(node.getNamespaceURI()))
+         {
+            return true;
+         }
+      }
+      return false;
+   }
+
+   private static boolean nonIgnorableNs(String ns)
+   {
+      return ns == null ||
+         !ns.equals(Constants.NS_XML_SCHEMA)
+         && !ns.equals(Constants.NS_XML_SCHEMA_INSTANCE)
+         && !ns.equals(Constants.NS_XML_XMLNS);
+   }
+
+   private static boolean xsiNs(String ns)
+   {
+      return Constants.NS_XML_SCHEMA_INSTANCE.equals(ns);
+   }
+
+   private String fail(String msg, Element exp, Element was)
+   {
+      return msg + ". Expected\n" + toString(exp) + "\nbut was\n" + toString(was);
+   }
+
+   private String toString(Element e)
+   {
+      return append(e, new StringBuffer(), 0).toString();
+   }
+
+   private StringBuffer append(Element e, StringBuffer buf, int depth)
+   {
+      if(reformat && depth > 0)
+      {
+         buf.append('\n');
+         for(int i = 0; i < depth; ++i)
+         {
+            buf.append(INDENT);
+         }
+      }
+
+      buf.append('<');
+      if(e.getPrefix() != null && e.getPrefix().length() > 0)
+      {
+         buf.append(e.getPrefix()).append(':');
+      }
+      buf.append(e.getLocalName());
+
+      NamedNodeMap attrs = e.getAttributes();
+      if(attrs != null && attrs.getLength() > 0)
+      {
+         for(int i = 0; i < attrs.getLength(); ++i)
+         {
+            Attr attr = (Attr)attrs.item(i);
+            buf.append(' ')
+               .append(attr.getName())
+               .append('=')
+               .append('\'')
+               .append(attr.getValue())
+               .append('\'');
+         }
+      }
+
+      buf.append('>');
+
+      NodeList childNodes = e.getChildNodes();
+      boolean childElements = false;
+      for(int i = 0; i < childNodes.getLength(); ++i)
+      {
+         Node child = childNodes.item(i);
+         switch(child.getNodeType())
+         {
+            case Node.TEXT_NODE:
+               String chars = child.getNodeValue();
+               if(chars.trim().length() > 0)
+               {
+                  buf.append(chars);
+               }
+               break;
+            case Node.ELEMENT_NODE:
+               append((Element)child, buf, depth + 1);
+               childElements = true;
+               break;
+            default:
+               throw new IllegalStateException("Node type is not supported: " + child.getNodeType());
+         }
+      }
+
+      if(reformat && childElements)
+      {
+         buf.append('\n');
+         for(int i = 0; i < depth; ++i)
+         {
+            buf.append(INDENT);
+         }
+      }
+
+      buf.append("</");
+      if(e.getPrefix() != null && e.getPrefix().length() > 0)
+      {
+         buf.append(e.getPrefix()).append(':');
+      }
+      buf.append(e.getLocalName())
+         .append('>');
+
+      return buf;
+   }
+
+   // Inner
+
+   private static final class MutableNodeList
+      implements NodeList
+   {
+      private List list = Collections.EMPTY_LIST;
+
+      public void add(Node node)
+      {
+         switch(list.size())
+         {
+            case 0:
+               list = Collections.singletonList(node);
+               break;
+            case 1:
+               list = new ArrayList(list);
+            default:
+               list.add(node);
+         }
+      }
+
+      public int getLength()
+      {
+         return list.size();
+      }
+
+      public Node item(int index)
+      {
+         return (Node)list.get(index);
+      }
+   }
+
+   public static final class DefErrorHandler
+      implements ErrorHandler
+   {
+      public static final byte IGNORE = 0;
+      public static final byte LOG = 1;
+      public static final byte FAIL = 3;
+
+      private byte warnEvent = IGNORE;
+      private byte errorEvent = IGNORE;
+      private byte fatalEvent = FAIL;
+
+      public void error(SAXParseException e) throws SAXException
+      {
+         handleEvent(warnEvent, e);
+      }
+
+      public void fatalError(SAXParseException e) throws SAXException
+      {
+         handleEvent(errorEvent, e);
+      }
+
+      public void warning(SAXParseException e) throws SAXException
+      {
+         handleEvent(fatalEvent, e);
+      }
+
+      private void handleEvent(byte event, SAXParseException e)
+         throws SAXException
+      {
+         switch(event)
+         {
+            case IGNORE:
+               break;
+            case LOG:
+               System.out.println(formatMessage(e));
+               break;
+            case FAIL:
+               String msg = formatMessage(e);
+               throw new SAXException(msg);
+         }
+      }
+   }
+
+   private static String formatMessage(SAXParseException exception)
+   {
+      StringBuffer buffer = new StringBuffer(50);
+      buffer.append(exception.getMessage()).append(" @ ");
+      String location = exception.getPublicId();
+      if(location != null)
+      {
+         buffer.append(location);
+      }
+      else
+      {
+         location = exception.getSystemId();
+         if(location != null)
+         {
+            buffer.append(location);
+         }
+         else
+         {
+            buffer.append("*unknown*");
+         }
+      }
+      buffer.append('[');
+      buffer.append(exception.getLineNumber()).append(',');
+      buffer.append(exception.getColumnNumber()).append(']');
+      return buffer.toString();
+   }
+}

Added: jbossxb/trunk/src/test/resources/org/jboss/test/xml/RepeatableTermsUnitTestCase_testUnmarshal1.xml
===================================================================
--- jbossxb/trunk/src/test/resources/org/jboss/test/xml/RepeatableTermsUnitTestCase_testUnmarshal1.xml	2006-09-20 21:34:53 UTC (rev 2047)
+++ jbossxb/trunk/src/test/resources/org/jboss/test/xml/RepeatableTermsUnitTestCase_testUnmarshal1.xml	2006-09-21 07:19:23 UTC (rev 2048)
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<top xmlns='http://www.jboss.org/test/xml/repeatableterms'>
+  <item>item1</item>
+  <item>item2</item>
+  <item>item3</item>
+
+  <sequenceChoice1>sequenceChoice1_1</sequenceChoice1>
+  <sequenceChoice2>sequenceChoice2_1</sequenceChoice2>
+  <sequenceChoice1>sequenceChoice1_2</sequenceChoice1>
+  <sequenceChoice1>sequenceChoice1_3</sequenceChoice1>
+  <sequenceChoice2>sequenceChoice2_2</sequenceChoice2>
+
+  <choiceChoice1>choiceChoice1_1</choiceChoice1>
+  <choiceChoice1>choiceChoice1_2</choiceChoice1>
+
+  <choiceChoice2>choiceChoice2_1</choiceChoice2>
+  <choiceChoice2>choiceChoice2_2</choiceChoice2>
+
+  <choiceChoice1>choiceChoice1_3</choiceChoice1>
+  <choiceChoice1>choiceChoice1_4</choiceChoice1>
+</top>

Added: jbossxb/trunk/src/test/resources/org/jboss/test/xml/RepeatableTermsUnitTestCase_testUnmarshal1.xsd
===================================================================
--- jbossxb/trunk/src/test/resources/org/jboss/test/xml/RepeatableTermsUnitTestCase_testUnmarshal1.xsd	2006-09-20 21:34:53 UTC (rev 2047)
+++ jbossxb/trunk/src/test/resources/org/jboss/test/xml/RepeatableTermsUnitTestCase_testUnmarshal1.xsd	2006-09-21 07:19:23 UTC (rev 2048)
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+   targetNamespace="http://www.jboss.org/test/xml/repeatableterms"
+   xmlns="http://www.jboss.org/test/xml/repeatableterms"
+   xmlns:jbxb="http://www.jboss.org/xml/ns/jbxb"
+   elementFormDefault="qualified"
+   attributeFormDefault="unqualified"
+   version="1.0">
+
+   <xsd:element name="top">
+      <xsd:annotation>
+         <xsd:appinfo>
+            <jbxb:class impl="org.jboss.test.xml.RepeatableTermsUnitTestCase$Top"/>
+         </xsd:appinfo>
+      </xsd:annotation>
+      <xsd:complexType>
+         <xsd:sequence>
+            <xsd:element name="item" type="xsd:string" maxOccurs="unbounded"/>
+            <xsd:sequence maxOccurs="unbounded">
+               <xsd:annotation>
+                  <xsd:appinfo>
+                     <jbxb:class impl="org.jboss.test.xml.RepeatableTermsUnitTestCase$Sequence"/>
+                     <jbxb:property name="sequence"/>
+                  </xsd:appinfo>
+               </xsd:annotation>
+               <xsd:choice>
+                  <xsd:element name="sequenceChoice1" type="xsd:string"/>
+                  <xsd:element name="sequenceChoice2" type="xsd:string"/>
+               </xsd:choice>
+            </xsd:sequence>
+            <xsd:choice maxOccurs="unbounded">
+               <xsd:annotation>
+                  <xsd:appinfo>
+                     <jbxb:class impl="org.jboss.test.xml.RepeatableTermsUnitTestCase$Choice"/>
+                     <jbxb:property name="choice"/>
+                  </xsd:appinfo>
+               </xsd:annotation>
+               <xsd:element name="choiceChoice1" type="xsd:string" maxOccurs="unbounded"/>
+               <xsd:element name="choiceChoice2" type="xsd:string" maxOccurs="unbounded"/>
+            </xsd:choice>
+         </xsd:sequence>
+      </xsd:complexType>
+   </xsd:element>
+</xsd:schema>

Added: jbossxb/trunk/src/test/resources/org/jboss/test/xml/RepeatableTermsUnitTestCase_testUnmarshal2.xml
===================================================================
--- jbossxb/trunk/src/test/resources/org/jboss/test/xml/RepeatableTermsUnitTestCase_testUnmarshal2.xml	2006-09-20 21:34:53 UTC (rev 2047)
+++ jbossxb/trunk/src/test/resources/org/jboss/test/xml/RepeatableTermsUnitTestCase_testUnmarshal2.xml	2006-09-21 07:19:23 UTC (rev 2048)
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<top xmlns='http://www.jboss.org/test/xml/repeatableterms'>
+  <item1>item1</item1>
+  <item2>item2</item2>
+</top>

Added: jbossxb/trunk/src/test/resources/org/jboss/test/xml/RepeatableTermsUnitTestCase_testUnmarshal2.xsd
===================================================================
--- jbossxb/trunk/src/test/resources/org/jboss/test/xml/RepeatableTermsUnitTestCase_testUnmarshal2.xsd	2006-09-20 21:34:53 UTC (rev 2047)
+++ jbossxb/trunk/src/test/resources/org/jboss/test/xml/RepeatableTermsUnitTestCase_testUnmarshal2.xsd	2006-09-21 07:19:23 UTC (rev 2048)
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+   targetNamespace="http://www.jboss.org/test/xml/repeatableterms"
+   xmlns="http://www.jboss.org/test/xml/repeatableterms"
+   xmlns:jbxb="http://www.jboss.org/xml/ns/jbxb"
+   elementFormDefault="qualified"
+   attributeFormDefault="unqualified"
+   version="1.0">
+
+   <xsd:element name="top">
+      <xsd:annotation>
+         <xsd:appinfo>
+            <jbxb:class impl="org.jboss.test.xml.RepeatableTermsUnitTestCase$Top"/>
+         </xsd:appinfo>
+      </xsd:annotation>
+      <xsd:complexType>
+         <xsd:sequence maxOccurs="unbounded">
+            <xsd:sequence maxOccurs="unbounded">
+               <xsd:choice maxOccurs="unbounded">
+                  <xsd:sequence maxOccurs="unbounded">
+                     <xsd:element name="item1" type="xsd:string"/>
+                  </xsd:sequence>
+                  <xsd:sequence maxOccurs="unbounded">
+                     <xsd:sequence maxOccurs="unbounded">
+                        <xsd:element name="item2" type="xsd:string"/>
+                     </xsd:sequence>
+                  </xsd:sequence>
+               </xsd:choice>
+            </xsd:sequence>
+         </xsd:sequence>
+      </xsd:complexType>
+   </xsd:element>
+</xsd:schema>




More information about the jboss-svn-commits mailing list