[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

[xml] occurrences on elements & sequences



I've come across a couple of bugs in schema handling, specifically
dealing with min & max occurrences on elements and sequences.
If an element has a minOccur='0' and maxOccur > 1 and the element is not
present in the xml file being validated, then the validation fails. See
attached elem.* files for test case. Also minOccur and maxOccur on
sequence are not handled at all.
I (hopefully) fixed the problems in xmlSchemaBuildAContentModel with the
attached patch, but I don't really understand the automata routines so
the patch needs checking. The patch also adds a check for unbounded case
when building a model for choice types.

Charlie B.


<?xml version="1.0"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema";>
  <xsd:annotation>
    <xsd:documentation>
      Testing min and max occurance attributes on element
    </xsd:documentation>
  </xsd:annotation>

  <xsd:element name="doc">
    <xsd:complexType>
      <xsd:sequence>
        <xsd:element name='a' minOccurs='0' maxOccurs='3'/>
      </xsd:sequence>
    </xsd:complexType>
  </xsd:element>
</xsd:schema>
<?xml version="1.0"?>
<doc/>

<?xml version="1.0"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema";>
  <xsd:annotation>
    <xsd:documentation>
      Testing min and max occurance attributes on sequences
    </xsd:documentation>
  </xsd:annotation>

  <xsd:element name="doc">
    <xsd:complexType>
      <xsd:sequence minOccurs='0' maxOccurs='unbounded'>

        <xsd:element name="z-o">
          <xsd:complexType>
            <xsd:sequence minOccurs='0' maxOccurs='1'>
              <xsd:element name='b'/>
            </xsd:sequence>
          </xsd:complexType>
        </xsd:element>

        <xsd:element name="o-o">
          <xsd:complexType>
            <xsd:sequence minOccurs='1' maxOccurs='1'>
              <xsd:element name='c'/>
            </xsd:sequence>
          </xsd:complexType>
        </xsd:element>

        <xsd:element name="z-u">
          <xsd:complexType>
            <xsd:sequence minOccurs='0' maxOccurs='unbounded'>
              <xsd:element name='d'/>
            </xsd:sequence>
          </xsd:complexType>
        </xsd:element>

        <xsd:element name="o-u">
          <xsd:complexType>
            <xsd:sequence minOccurs='1' maxOccurs='unbounded'>
              <xsd:element name='e'/>
            </xsd:sequence>
          </xsd:complexType>
        </xsd:element>

        <xsd:element name="z-3">
          <xsd:complexType>
            <xsd:sequence minOccurs='0' maxOccurs='3'>
              <xsd:element name='f'/>
            </xsd:sequence>
          </xsd:complexType>
        </xsd:element>

        <xsd:element name="o-3">
          <xsd:complexType>
            <xsd:sequence minOccurs='1' maxOccurs='3'>
              <xsd:element name='g'/>
            </xsd:sequence>
          </xsd:complexType>
        </xsd:element>

      </xsd:sequence>
    </xsd:complexType>
  </xsd:element>
</xsd:schema>
<doc>
  <!-- at least one present -->
  <z-o>
    <b/>
  </z-o>
  <o-o>
    <c/>
  </o-o>
  <z-u>
    <d/>
  </z-u>
  <o-u>
    <e/>
  </o-u>
  <z-3>
    <f/>
  </z-3>
  <o-3>
    <g/>
  </o-3>
  <!-- more than one present when allowed -->
  <z-o>
    <b/>
  </z-o>
  <o-o>
    <c/>
  </o-o>
  <z-u>
    <d/>
    <d/>
    <d/>
  </z-u>
  <o-u>
    <e/>
    <e/>
    <e/>
  </o-u>
  <z-3>
    <f/>
    <f/>
    <f/>
  </z-3>
  <o-3>
    <g/>
    <g/>
    <g/>
  </o-3>
  <!-- min 0 are not present -->
  <z-o/>
  <o-o>
    <c/>
  </o-o>
  <z-u/>
  <o-u>
    <e/>
  </o-u>
  <z-3/>
  <o-3>
    <g/>
  </o-3>
</doc>
Index: xmlschemas.c
===================================================================
RCS file: /cvs/gnome/libxml2/xmlschemas.c,v
retrieving revision 1.20
diff -c -r1.20 xmlschemas.c
*** xmlschemas.c	16 Oct 2002 14:08:12 -0000	1.20
--- xmlschemas.c	26 Oct 2002 13:34:18 -0000
***************
*** 3165,3170 ****
--- 3165,3174 ----
  					   counter);
  		ctxt->state = xmlAutomataNewCounterTrans(ctxt->am, tmp,
  					   NULL, counter);
+ 		if (elem->minOccurs == 0) {
+ 		    /* basically an elem? */
+ 		    xmlAutomataNewEpsilon(ctxt->am, oldstate, ctxt->state);
+ 		}
  
  	    } else {
  		if (elem->refDecl != NULL) {
***************
*** 3186,3197 ****
  	    xmlSchemaTypePtr subtypes;
  
  	    /*
! 	     * Simply iterate over the subtypes
  	     */
! 	    subtypes = type->subtypes;
! 	    while (subtypes != NULL) {
! 		xmlSchemaBuildAContentModel(subtypes, ctxt, name);
! 		subtypes = subtypes->next;
  	    }
  	    break;
  	}
--- 3190,3276 ----
  	    xmlSchemaTypePtr subtypes;
  
  	    /*
! 	     * If max and min occurances are default (1) then
! 	     * simply iterate over the subtypes
  	     */
! 	    if ((type->minOccurs == 1 ) && (type->maxOccurs == 1)) {
! 	        subtypes = type->subtypes;
! 	        while (subtypes != NULL) {
! 		    xmlSchemaBuildAContentModel(subtypes, ctxt, name);
! 		    subtypes = subtypes->next;
! 	        }
! 	    } else {
! 	        xmlAutomataStatePtr oldstate = ctxt->state;
! 	        if (type->maxOccurs >= UNBOUNDED) {
! 		    if (type->minOccurs > 1) {
! 		        xmlAutomataStatePtr tmp;
! 		        int counter;
! 
! 		        ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
! 			                                oldstate, NULL);
! 		        oldstate = ctxt->state;
! 
! 		        counter = xmlAutomataNewCounter(ctxt->am,
! 			        	    type->minOccurs - 1, UNBOUNDED);
! 
! 	                subtypes = type->subtypes;
! 	                while (subtypes != NULL) {
! 		            xmlSchemaBuildAContentModel(subtypes, ctxt, name);
! 		            subtypes = subtypes->next;
! 	                }
! 		        tmp = ctxt->state;
! 		        xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
! 		                            counter);
! 		        ctxt->state = xmlAutomataNewCounterTrans(ctxt->am, tmp,
! 		                            NULL, counter);
! 
! 		    } else {
! 	                subtypes = type->subtypes;
! 	                while (subtypes != NULL) {
! 		            xmlSchemaBuildAContentModel(subtypes, ctxt, name);
! 		            subtypes = subtypes->next;
! 	                }
! 		        xmlAutomataNewEpsilon(ctxt->am, ctxt->state, oldstate);
! 		        if (type->minOccurs == 0) {
! 			    xmlAutomataNewEpsilon(ctxt->am, oldstate,
! 				                  ctxt->state);
! 		        }
! 		    }
! 	        } else if ((type->maxOccurs > 1) || (type->minOccurs > 1)) {
! 		    xmlAutomataStatePtr tmp;
! 		    int counter;
! 
! 		    ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
! 						    oldstate, NULL);
! 		    oldstate = ctxt->state;
! 
! 		    counter = xmlAutomataNewCounter(ctxt->am,
! 		                  type->minOccurs - 1, type->maxOccurs - 1);
! 
! 	            subtypes = type->subtypes;
! 	            while (subtypes != NULL) {
! 		        xmlSchemaBuildAContentModel(subtypes, ctxt, name);
! 		        subtypes = subtypes->next;
! 	            }
! 		    tmp = ctxt->state;
! 		    xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
! 		          counter);
! 		    ctxt->state = xmlAutomataNewCounterTrans(ctxt->am, tmp,
! 		                                             NULL, counter);
! 		    if (type->minOccurs == 0) {
! 		        xmlAutomataNewEpsilon(ctxt->am, oldstate, ctxt->state);
! 		    }
! 
! 	        } else {
! 	            subtypes = type->subtypes;
! 	            while (subtypes != NULL) {
! 		        xmlSchemaBuildAContentModel(subtypes, ctxt, name);
! 		        subtypes = subtypes->next;
! 	            }
! 		    if (type->minOccurs == 0) {
! 		        xmlAutomataNewEpsilon(ctxt->am, oldstate, ctxt->state);
! 		    }
! 	        }
  	    }
  	    break;
  	}
***************
*** 3217,3234 ****
  	    } else {
  		int counter;
  		xmlAutomataStatePtr hop;
  
  		/*
  		 * use a counter to keep track of the number of transtions
  		 * which went through the choice.
  		 */
! 		if (type->minOccurs < 1) {
! 		    counter = xmlAutomataNewCounter(ctxt->am, 0,
! 			                            type->maxOccurs - 1);
! 		} else {
! 		    counter = xmlAutomataNewCounter(ctxt->am,
! 			    type->minOccurs - 1, type->maxOccurs - 1);
! 		}
  		hop = xmlAutomataNewState(ctxt->am);
  
  		subtypes = type->subtypes;
--- 3296,3310 ----
  	    } else {
  		int counter;
  		xmlAutomataStatePtr hop;
+ 		int maxOccurs = type->maxOccurs == UNBOUNDED ?
+ 		                      UNBOUNDED : type->maxOccurs - 1;
+ 		int minOccurs = type->minOccurs < 1 ? 0 : type->minOccurs - 1;
  
  		/*
  		 * use a counter to keep track of the number of transtions
  		 * which went through the choice.
  		 */
! 		counter = xmlAutomataNewCounter(ctxt->am, minOccurs, maxOccurs);
  		hop = xmlAutomataNewState(ctxt->am);
  
  		subtypes = type->subtypes;


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]