mirror of
https://gitlab.gnome.org/GNOME/libxml2
synced 2025-03-28 21:33:13 +00:00
579746 XSD validation not correct / nilable groups
* xmlschemas.c: when a particle need to be processed via counted transition, if the group is nillable, the counting won't work, so keep track of nillable subset as they are built and generate the appropriate epsilon transitions as needed * test/schemas/579746* result/schemas/579746*: add related test cases based on the bug report
This commit is contained in:
parent
74eaec1496
commit
4013e83e84
1
result/schemas/579746_0_0
Normal file
1
result/schemas/579746_0_0
Normal file
@ -0,0 +1 @@
|
||||
./test/schemas/579746_0.xml validates
|
0
result/schemas/579746_0_0.err
Normal file
0
result/schemas/579746_0_0.err
Normal file
1
result/schemas/579746_0_1
Normal file
1
result/schemas/579746_0_1
Normal file
@ -0,0 +1 @@
|
||||
./test/schemas/579746_1.xml validates
|
0
result/schemas/579746_0_1.err
Normal file
0
result/schemas/579746_0_1.err
Normal file
1
result/schemas/579746_0_2
Normal file
1
result/schemas/579746_0_2
Normal file
@ -0,0 +1 @@
|
||||
./test/schemas/579746_2.xml validates
|
0
result/schemas/579746_0_2.err
Normal file
0
result/schemas/579746_0_2.err
Normal file
1
result/schemas/579746_0_3
Normal file
1
result/schemas/579746_0_3
Normal file
@ -0,0 +1 @@
|
||||
./test/schemas/579746_3.xml fails to validate
|
1
result/schemas/579746_0_3.err
Normal file
1
result/schemas/579746_0_3.err
Normal file
@ -0,0 +1 @@
|
||||
./test/schemas/579746_3.xml:5: element customer: Schemas validity error : Element 'customer': This element is not expected.
|
1
result/schemas/579746_0_4
Normal file
1
result/schemas/579746_0_4
Normal file
@ -0,0 +1 @@
|
||||
./test/schemas/579746_4.xml validates
|
0
result/schemas/579746_0_4.err
Normal file
0
result/schemas/579746_0_4.err
Normal file
1
result/schemas/579746_0_5
Normal file
1
result/schemas/579746_0_5
Normal file
@ -0,0 +1 @@
|
||||
./test/schemas/579746_5.xml fails to validate
|
1
result/schemas/579746_0_5.err
Normal file
1
result/schemas/579746_0_5.err
Normal file
@ -0,0 +1 @@
|
||||
./test/schemas/579746_5.xml:5: element comment: Schemas validity error : Element 'comment': This element is not expected.
|
1
result/schemas/579746_1_0
Normal file
1
result/schemas/579746_1_0
Normal file
@ -0,0 +1 @@
|
||||
./test/schemas/579746_0.xml validates
|
0
result/schemas/579746_1_0.err
Normal file
0
result/schemas/579746_1_0.err
Normal file
1
result/schemas/579746_1_1
Normal file
1
result/schemas/579746_1_1
Normal file
@ -0,0 +1 @@
|
||||
./test/schemas/579746_1.xml validates
|
0
result/schemas/579746_1_1.err
Normal file
0
result/schemas/579746_1_1.err
Normal file
1
result/schemas/579746_1_2
Normal file
1
result/schemas/579746_1_2
Normal file
@ -0,0 +1 @@
|
||||
./test/schemas/579746_2.xml validates
|
0
result/schemas/579746_1_2.err
Normal file
0
result/schemas/579746_1_2.err
Normal file
1
result/schemas/579746_1_3
Normal file
1
result/schemas/579746_1_3
Normal file
@ -0,0 +1 @@
|
||||
./test/schemas/579746_3.xml fails to validate
|
1
result/schemas/579746_1_3.err
Normal file
1
result/schemas/579746_1_3.err
Normal file
@ -0,0 +1 @@
|
||||
./test/schemas/579746_3.xml:5: element customer: Schemas validity error : Element 'customer': This element is not expected.
|
1
result/schemas/579746_1_4
Normal file
1
result/schemas/579746_1_4
Normal file
@ -0,0 +1 @@
|
||||
./test/schemas/579746_4.xml validates
|
0
result/schemas/579746_1_4.err
Normal file
0
result/schemas/579746_1_4.err
Normal file
1
result/schemas/579746_1_5
Normal file
1
result/schemas/579746_1_5
Normal file
@ -0,0 +1 @@
|
||||
./test/schemas/579746_5.xml fails to validate
|
1
result/schemas/579746_1_5.err
Normal file
1
result/schemas/579746_1_5.err
Normal file
@ -0,0 +1 @@
|
||||
./test/schemas/579746_5.xml:5: element comment: Schemas validity error : Element 'comment': This element is not expected.
|
3
test/schemas/579746_0.xml
Normal file
3
test/schemas/579746_0.xml
Normal file
@ -0,0 +1,3 @@
|
||||
<?xml version="1.0"?>
|
||||
<contact>
|
||||
</contact>
|
11
test/schemas/579746_0.xsd
Normal file
11
test/schemas/579746_0.xsd
Normal file
@ -0,0 +1,11 @@
|
||||
<?xml version="1.0"?>
|
||||
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
|
||||
<xsd:element name= "contact" type="ContactType"/>
|
||||
<xsd:complexType name="ContactType">
|
||||
<xsd:choice minOccurs="2" maxOccurs="2">
|
||||
<xsd:element name="customer" type="xsd:string" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0"/>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:schema>
|
||||
|
4
test/schemas/579746_1.xml
Normal file
4
test/schemas/579746_1.xml
Normal file
@ -0,0 +1,4 @@
|
||||
<?xml version="1.0"?>
|
||||
<contact>
|
||||
<customer/>
|
||||
</contact>
|
10
test/schemas/579746_1.xsd
Normal file
10
test/schemas/579746_1.xsd
Normal file
@ -0,0 +1,10 @@
|
||||
<?xml version="1.0"?>
|
||||
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
|
||||
<xsd:element name= "contact" type="ContactType"/>
|
||||
<xsd:complexType name="ContactType">
|
||||
<xsd:choice minOccurs="1" maxOccurs="2">
|
||||
<xsd:element name="customer" type="xsd:string" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0"/>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:schema>
|
5
test/schemas/579746_2.xml
Normal file
5
test/schemas/579746_2.xml
Normal file
@ -0,0 +1,5 @@
|
||||
<?xml version="1.0"?>
|
||||
<contact>
|
||||
<customer/>
|
||||
<customer/>
|
||||
</contact>
|
7
test/schemas/579746_3.xml
Normal file
7
test/schemas/579746_3.xml
Normal file
@ -0,0 +1,7 @@
|
||||
<?xml version="1.0"?>
|
||||
<contact>
|
||||
<customer/>
|
||||
<comment/>
|
||||
<customer/>
|
||||
<comment/>
|
||||
</contact>
|
5
test/schemas/579746_4.xml
Normal file
5
test/schemas/579746_4.xml
Normal file
@ -0,0 +1,5 @@
|
||||
<?xml version="1.0"?>
|
||||
<contact>
|
||||
<customer/>
|
||||
<comment/>
|
||||
</contact>
|
6
test/schemas/579746_5.xml
Normal file
6
test/schemas/579746_5.xml
Normal file
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0"?>
|
||||
<contact>
|
||||
<comment/>
|
||||
<customer/>
|
||||
<comment/>
|
||||
</contact>
|
459
xmlschemas.c
459
xmlschemas.c
@ -12525,7 +12525,12 @@ xmlSchemaFreeParserCtxt(xmlSchemaParserCtxtPtr ctxt)
|
||||
* *
|
||||
************************************************************************/
|
||||
|
||||
static void
|
||||
/**
|
||||
* xmlSchemaBuildContentModelForSubstGroup:
|
||||
*
|
||||
* Returns 1 if nillable, 0 otherwise
|
||||
*/
|
||||
static int
|
||||
xmlSchemaBuildContentModelForSubstGroup(xmlSchemaParserCtxtPtr pctxt,
|
||||
xmlSchemaParticlePtr particle, int counter, xmlAutomataStatePtr end)
|
||||
{
|
||||
@ -12533,6 +12538,7 @@ xmlSchemaBuildContentModelForSubstGroup(xmlSchemaParserCtxtPtr pctxt,
|
||||
xmlSchemaElementPtr elemDecl, member;
|
||||
xmlSchemaSubstGroupPtr substGroup;
|
||||
int i;
|
||||
int ret = 0;
|
||||
|
||||
elemDecl = (xmlSchemaElementPtr) particle->children;
|
||||
/*
|
||||
@ -12548,7 +12554,7 @@ xmlSchemaBuildContentModelForSubstGroup(xmlSchemaParserCtxtPtr pctxt,
|
||||
"Internal error: xmlSchemaBuildContentModelForSubstGroup, "
|
||||
"declaration is marked having a subst. group but none "
|
||||
"available.\n", elemDecl->name, NULL);
|
||||
return;
|
||||
return(0);
|
||||
}
|
||||
if (counter >= 0) {
|
||||
/*
|
||||
@ -12628,21 +12634,31 @@ xmlSchemaBuildContentModelForSubstGroup(xmlSchemaParserCtxtPtr pctxt,
|
||||
xmlAutomataNewCountedTrans(pctxt->am, hop, start, counter);
|
||||
xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter);
|
||||
}
|
||||
if (particle->minOccurs == 0)
|
||||
if (particle->minOccurs == 0) {
|
||||
xmlAutomataNewEpsilon(pctxt->am, start, end);
|
||||
ret = 1;
|
||||
}
|
||||
pctxt->state = end;
|
||||
return(ret);
|
||||
}
|
||||
|
||||
static void
|
||||
/**
|
||||
* xmlSchemaBuildContentModelForElement:
|
||||
*
|
||||
* Returns 1 if nillable, 0 otherwise
|
||||
*/
|
||||
static int
|
||||
xmlSchemaBuildContentModelForElement(xmlSchemaParserCtxtPtr ctxt,
|
||||
xmlSchemaParticlePtr particle)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (((xmlSchemaElementPtr) particle->children)->flags &
|
||||
XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) {
|
||||
/*
|
||||
* Substitution groups.
|
||||
*/
|
||||
xmlSchemaBuildContentModelForSubstGroup(ctxt, particle, -1, NULL);
|
||||
ret = xmlSchemaBuildContentModelForSubstGroup(ctxt, particle, -1, NULL);
|
||||
} else {
|
||||
xmlSchemaElementPtr elemDecl;
|
||||
xmlAutomataStatePtr start;
|
||||
@ -12650,7 +12666,7 @@ xmlSchemaBuildContentModelForElement(xmlSchemaParserCtxtPtr ctxt,
|
||||
elemDecl = (xmlSchemaElementPtr) particle->children;
|
||||
|
||||
if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT)
|
||||
return;
|
||||
return(0);
|
||||
if (particle->maxOccurs == 1) {
|
||||
start = ctxt->state;
|
||||
ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
|
||||
@ -12678,9 +12694,12 @@ xmlSchemaBuildContentModelForElement(xmlSchemaParserCtxtPtr ctxt,
|
||||
ctxt->state = xmlAutomataNewCounterTrans(ctxt->am, ctxt->state,
|
||||
NULL, counter);
|
||||
}
|
||||
if (particle->minOccurs == 0)
|
||||
if (particle->minOccurs == 0) {
|
||||
xmlAutomataNewEpsilon(ctxt->am, start, ctxt->state);
|
||||
ret = 1;
|
||||
}
|
||||
}
|
||||
return(ret);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -12691,21 +12710,24 @@ xmlSchemaBuildContentModelForElement(xmlSchemaParserCtxtPtr ctxt,
|
||||
*
|
||||
* Create the automaton for the {content type} of a complex type.
|
||||
*
|
||||
* Returns 1 if the content is nillable, 0 otherwise
|
||||
*/
|
||||
static void
|
||||
static int
|
||||
xmlSchemaBuildAContentModel(xmlSchemaParserCtxtPtr pctxt,
|
||||
xmlSchemaParticlePtr particle)
|
||||
{
|
||||
int ret = 0, tmp2;
|
||||
|
||||
if (particle == NULL) {
|
||||
PERROR_INT("xmlSchemaBuildAContentModel", "particle is NULL");
|
||||
return;
|
||||
return(1);
|
||||
}
|
||||
if (particle->children == NULL) {
|
||||
/*
|
||||
* Just return in this case. A missing "term" of the particle
|
||||
* might arise due to an invalid "term" component.
|
||||
*/
|
||||
return;
|
||||
return(1);
|
||||
}
|
||||
|
||||
switch (particle->children->type) {
|
||||
@ -12757,7 +12779,8 @@ xmlSchemaBuildAContentModel(xmlSchemaParserCtxtPtr pctxt,
|
||||
int counter;
|
||||
xmlAutomataStatePtr hop;
|
||||
int maxOccurs =
|
||||
particle->maxOccurs == UNBOUNDED ? UNBOUNDED : particle->maxOccurs - 1;
|
||||
particle->maxOccurs == UNBOUNDED ? UNBOUNDED :
|
||||
particle->maxOccurs - 1;
|
||||
int minOccurs =
|
||||
particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
|
||||
|
||||
@ -12792,247 +12815,273 @@ xmlSchemaBuildAContentModel(xmlSchemaParserCtxtPtr pctxt,
|
||||
}
|
||||
if (particle->minOccurs == 0) {
|
||||
xmlAutomataNewEpsilon(pctxt->am, start, end);
|
||||
ret = 1;
|
||||
}
|
||||
pctxt->state = end;
|
||||
break;
|
||||
}
|
||||
case XML_SCHEMA_TYPE_ELEMENT:
|
||||
xmlSchemaBuildContentModelForElement(pctxt, particle);
|
||||
ret = xmlSchemaBuildContentModelForElement(pctxt, particle);
|
||||
break;
|
||||
case XML_SCHEMA_TYPE_SEQUENCE:{
|
||||
xmlSchemaTreeItemPtr sub;
|
||||
xmlSchemaTreeItemPtr sub;
|
||||
|
||||
/*
|
||||
* If max and min occurances are default (1) then
|
||||
* simply iterate over the particles of the <sequence>.
|
||||
*/
|
||||
if ((particle->minOccurs == 1) && (particle->maxOccurs == 1)) {
|
||||
sub = particle->children->children;
|
||||
while (sub != NULL) {
|
||||
xmlSchemaBuildAContentModel(pctxt,
|
||||
(xmlSchemaParticlePtr) sub);
|
||||
sub = sub->next;
|
||||
}
|
||||
} else {
|
||||
xmlAutomataStatePtr oldstate = pctxt->state;
|
||||
ret = 1;
|
||||
/*
|
||||
* If max and min occurances are default (1) then
|
||||
* simply iterate over the particles of the <sequence>.
|
||||
*/
|
||||
if ((particle->minOccurs == 1) && (particle->maxOccurs == 1)) {
|
||||
sub = particle->children->children;
|
||||
|
||||
if (particle->maxOccurs >= UNBOUNDED) {
|
||||
if (particle->minOccurs > 1) {
|
||||
xmlAutomataStatePtr tmp;
|
||||
int counter;
|
||||
while (sub != NULL) {
|
||||
tmp2 = xmlSchemaBuildAContentModel(pctxt,
|
||||
(xmlSchemaParticlePtr) sub);
|
||||
if (tmp2 != 1) ret = 0;
|
||||
sub = sub->next;
|
||||
}
|
||||
} else {
|
||||
xmlAutomataStatePtr oldstate = pctxt->state;
|
||||
|
||||
pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
|
||||
oldstate, NULL);
|
||||
oldstate = pctxt->state;
|
||||
|
||||
counter = xmlAutomataNewCounter(pctxt->am,
|
||||
particle->minOccurs - 1, UNBOUNDED);
|
||||
|
||||
sub = particle->children->children;
|
||||
while (sub != NULL) {
|
||||
xmlSchemaBuildAContentModel(pctxt,
|
||||
(xmlSchemaParticlePtr) sub);
|
||||
sub = sub->next;
|
||||
}
|
||||
tmp = pctxt->state;
|
||||
xmlAutomataNewCountedTrans(pctxt->am, tmp,
|
||||
oldstate, counter);
|
||||
pctxt->state =
|
||||
xmlAutomataNewCounterTrans(pctxt->am, tmp,
|
||||
NULL, counter);
|
||||
|
||||
} else {
|
||||
pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
|
||||
oldstate, NULL);
|
||||
oldstate = pctxt->state;
|
||||
|
||||
sub = particle->children->children;
|
||||
while (sub != NULL) {
|
||||
xmlSchemaBuildAContentModel(pctxt,
|
||||
(xmlSchemaParticlePtr) sub);
|
||||
sub = sub->next;
|
||||
}
|
||||
xmlAutomataNewEpsilon(pctxt->am, pctxt->state,
|
||||
oldstate);
|
||||
/*
|
||||
* epsilon needed to block previous trans from
|
||||
* being allowed to enter back from another
|
||||
* construct
|
||||
*/
|
||||
pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
|
||||
pctxt->state, NULL);
|
||||
if (particle->minOccurs == 0) {
|
||||
xmlAutomataNewEpsilon(pctxt->am,
|
||||
oldstate, pctxt->state);
|
||||
}
|
||||
}
|
||||
} else if ((particle->maxOccurs > 1)
|
||||
|| (particle->minOccurs > 1)) {
|
||||
if (particle->maxOccurs >= UNBOUNDED) {
|
||||
if (particle->minOccurs > 1) {
|
||||
xmlAutomataStatePtr tmp;
|
||||
int counter;
|
||||
|
||||
pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
|
||||
oldstate, NULL);
|
||||
oldstate, NULL);
|
||||
oldstate = pctxt->state;
|
||||
|
||||
counter = xmlAutomataNewCounter(pctxt->am,
|
||||
particle->minOccurs - 1,
|
||||
particle->maxOccurs - 1);
|
||||
particle->minOccurs - 1, UNBOUNDED);
|
||||
|
||||
sub = particle->children->children;
|
||||
while (sub != NULL) {
|
||||
xmlSchemaBuildAContentModel(pctxt,
|
||||
(xmlSchemaParticlePtr) sub);
|
||||
tmp2 = xmlSchemaBuildAContentModel(pctxt,
|
||||
(xmlSchemaParticlePtr) sub);
|
||||
if (tmp2 != 1) ret = 0;
|
||||
sub = sub->next;
|
||||
}
|
||||
tmp = pctxt->state;
|
||||
xmlAutomataNewCountedTrans(pctxt->am,
|
||||
tmp, oldstate, counter);
|
||||
xmlAutomataNewCountedTrans(pctxt->am, tmp,
|
||||
oldstate, counter);
|
||||
pctxt->state =
|
||||
xmlAutomataNewCounterTrans(pctxt->am, tmp, NULL,
|
||||
counter);
|
||||
if (particle->minOccurs == 0) {
|
||||
xmlAutomataNewCounterTrans(pctxt->am, tmp,
|
||||
NULL, counter);
|
||||
if (ret == 1)
|
||||
xmlAutomataNewEpsilon(pctxt->am,
|
||||
oldstate, pctxt->state);
|
||||
}
|
||||
oldstate, pctxt->state);
|
||||
|
||||
} else {
|
||||
pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
|
||||
oldstate, NULL);
|
||||
oldstate = pctxt->state;
|
||||
|
||||
sub = particle->children->children;
|
||||
while (sub != NULL) {
|
||||
xmlSchemaBuildAContentModel(pctxt,
|
||||
(xmlSchemaParticlePtr) sub);
|
||||
tmp2 = xmlSchemaBuildAContentModel(pctxt,
|
||||
(xmlSchemaParticlePtr) sub);
|
||||
if (tmp2 != 1) ret = 0;
|
||||
sub = sub->next;
|
||||
}
|
||||
xmlAutomataNewEpsilon(pctxt->am, pctxt->state,
|
||||
oldstate);
|
||||
/*
|
||||
* epsilon needed to block previous trans from
|
||||
* being allowed to enter back from another
|
||||
* construct
|
||||
*/
|
||||
pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
|
||||
pctxt->state, NULL);
|
||||
if (particle->minOccurs == 0) {
|
||||
xmlAutomataNewEpsilon(pctxt->am, oldstate,
|
||||
pctxt->state);
|
||||
xmlAutomataNewEpsilon(pctxt->am,
|
||||
oldstate, pctxt->state);
|
||||
ret = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case XML_SCHEMA_TYPE_CHOICE:{
|
||||
xmlSchemaTreeItemPtr sub;
|
||||
xmlAutomataStatePtr start, end;
|
||||
} else if ((particle->maxOccurs > 1)
|
||||
|| (particle->minOccurs > 1)) {
|
||||
xmlAutomataStatePtr tmp;
|
||||
int counter;
|
||||
|
||||
start = pctxt->state;
|
||||
end = xmlAutomataNewState(pctxt->am);
|
||||
pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
|
||||
oldstate, NULL);
|
||||
oldstate = pctxt->state;
|
||||
|
||||
/*
|
||||
* iterate over the subtypes and remerge the end with an
|
||||
* epsilon transition
|
||||
*/
|
||||
if (particle->maxOccurs == 1) {
|
||||
sub = particle->children->children;
|
||||
counter = xmlAutomataNewCounter(pctxt->am,
|
||||
particle->minOccurs - 1,
|
||||
particle->maxOccurs - 1);
|
||||
|
||||
sub = particle->children->children;
|
||||
while (sub != NULL) {
|
||||
pctxt->state = start;
|
||||
xmlSchemaBuildAContentModel(pctxt,
|
||||
(xmlSchemaParticlePtr) sub);
|
||||
xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
|
||||
tmp2 = xmlSchemaBuildAContentModel(pctxt,
|
||||
(xmlSchemaParticlePtr) sub);
|
||||
if (tmp2 != 1) ret = 0;
|
||||
sub = sub->next;
|
||||
}
|
||||
tmp = pctxt->state;
|
||||
xmlAutomataNewCountedTrans(pctxt->am,
|
||||
tmp, oldstate, counter);
|
||||
pctxt->state =
|
||||
xmlAutomataNewCounterTrans(pctxt->am, tmp, NULL,
|
||||
counter);
|
||||
if ((particle->minOccurs == 0) || (ret == 1)) {
|
||||
xmlAutomataNewEpsilon(pctxt->am,
|
||||
oldstate, pctxt->state);
|
||||
ret = 1;
|
||||
}
|
||||
} else {
|
||||
int counter;
|
||||
xmlAutomataStatePtr hop, base;
|
||||
int maxOccurs = particle->maxOccurs == UNBOUNDED ?
|
||||
UNBOUNDED : particle->maxOccurs - 1;
|
||||
int minOccurs =
|
||||
particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
|
||||
|
||||
/*
|
||||
* use a counter to keep track of the number of transtions
|
||||
* which went through the choice.
|
||||
*/
|
||||
counter =
|
||||
xmlAutomataNewCounter(pctxt->am, minOccurs, maxOccurs);
|
||||
hop = xmlAutomataNewState(pctxt->am);
|
||||
base = xmlAutomataNewState(pctxt->am);
|
||||
|
||||
sub = particle->children->children;
|
||||
sub = particle->children->children;
|
||||
while (sub != NULL) {
|
||||
pctxt->state = base;
|
||||
xmlSchemaBuildAContentModel(pctxt,
|
||||
(xmlSchemaParticlePtr) sub);
|
||||
xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
|
||||
tmp2 = xmlSchemaBuildAContentModel(pctxt,
|
||||
(xmlSchemaParticlePtr) sub);
|
||||
if (tmp2 != 1) ret = 0;
|
||||
sub = sub->next;
|
||||
}
|
||||
xmlAutomataNewEpsilon(pctxt->am, start, base);
|
||||
xmlAutomataNewCountedTrans(pctxt->am, hop, base, counter);
|
||||
xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter);
|
||||
if (particle->minOccurs == 0) {
|
||||
xmlAutomataNewEpsilon(pctxt->am, oldstate,
|
||||
pctxt->state);
|
||||
ret = 1;
|
||||
}
|
||||
}
|
||||
if (particle->minOccurs == 0) {
|
||||
xmlAutomataNewEpsilon(pctxt->am, start, end);
|
||||
}
|
||||
pctxt->state = end;
|
||||
break;
|
||||
}
|
||||
case XML_SCHEMA_TYPE_ALL:{
|
||||
xmlAutomataStatePtr start, tmp;
|
||||
xmlSchemaParticlePtr sub;
|
||||
xmlSchemaElementPtr elemDecl;
|
||||
break;
|
||||
}
|
||||
case XML_SCHEMA_TYPE_CHOICE:{
|
||||
xmlSchemaTreeItemPtr sub;
|
||||
xmlAutomataStatePtr start, end;
|
||||
|
||||
sub = (xmlSchemaParticlePtr) particle->children->children;
|
||||
if (sub == NULL)
|
||||
break;
|
||||
start = pctxt->state;
|
||||
tmp = xmlAutomataNewState(pctxt->am);
|
||||
xmlAutomataNewEpsilon(pctxt->am, pctxt->state, tmp);
|
||||
pctxt->state = tmp;
|
||||
ret = 0;
|
||||
start = pctxt->state;
|
||||
end = xmlAutomataNewState(pctxt->am);
|
||||
|
||||
/*
|
||||
* iterate over the subtypes and remerge the end with an
|
||||
* epsilon transition
|
||||
*/
|
||||
if (particle->maxOccurs == 1) {
|
||||
sub = particle->children->children;
|
||||
while (sub != NULL) {
|
||||
pctxt->state = tmp;
|
||||
|
||||
elemDecl = (xmlSchemaElementPtr) sub->children;
|
||||
if (elemDecl == NULL) {
|
||||
PERROR_INT("xmlSchemaBuildAContentModel",
|
||||
"<element> particle has no term");
|
||||
return;
|
||||
};
|
||||
/*
|
||||
* NOTE: The {max occurs} of all the particles in the
|
||||
* {particles} of the group must be 0 or 1; this is
|
||||
* already ensured during the parse of the content of
|
||||
* <all>.
|
||||
*/
|
||||
if (elemDecl->flags & XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) {
|
||||
int counter;
|
||||
|
||||
/*
|
||||
* This is an abstract group, we need to share
|
||||
* the same counter for all the element transitions
|
||||
* derived from the group
|
||||
*/
|
||||
counter = xmlAutomataNewCounter(pctxt->am,
|
||||
sub->minOccurs, sub->maxOccurs);
|
||||
xmlSchemaBuildContentModelForSubstGroup(pctxt,
|
||||
sub, counter, pctxt->state);
|
||||
} else {
|
||||
if ((sub->minOccurs == 1) &&
|
||||
(sub->maxOccurs == 1)) {
|
||||
xmlAutomataNewOnceTrans2(pctxt->am, pctxt->state,
|
||||
pctxt->state,
|
||||
elemDecl->name,
|
||||
elemDecl->targetNamespace,
|
||||
1, 1, elemDecl);
|
||||
} else if ((sub->minOccurs == 0) &&
|
||||
(sub->maxOccurs == 1)) {
|
||||
|
||||
xmlAutomataNewCountTrans2(pctxt->am, pctxt->state,
|
||||
pctxt->state,
|
||||
elemDecl->name,
|
||||
elemDecl->targetNamespace,
|
||||
0,
|
||||
1,
|
||||
elemDecl);
|
||||
}
|
||||
}
|
||||
sub = (xmlSchemaParticlePtr) sub->next;
|
||||
pctxt->state = start;
|
||||
tmp2 = xmlSchemaBuildAContentModel(pctxt,
|
||||
(xmlSchemaParticlePtr) sub);
|
||||
if (tmp2 == 1) ret = 1;
|
||||
xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
|
||||
sub = sub->next;
|
||||
}
|
||||
pctxt->state =
|
||||
xmlAutomataNewAllTrans(pctxt->am, pctxt->state, NULL, 0);
|
||||
if (particle->minOccurs == 0) {
|
||||
xmlAutomataNewEpsilon(pctxt->am, start, pctxt->state);
|
||||
} else {
|
||||
int counter;
|
||||
xmlAutomataStatePtr hop, base;
|
||||
int maxOccurs = particle->maxOccurs == UNBOUNDED ?
|
||||
UNBOUNDED : particle->maxOccurs - 1;
|
||||
int minOccurs =
|
||||
particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
|
||||
|
||||
/*
|
||||
* use a counter to keep track of the number of transtions
|
||||
* which went through the choice.
|
||||
*/
|
||||
counter =
|
||||
xmlAutomataNewCounter(pctxt->am, minOccurs, maxOccurs);
|
||||
hop = xmlAutomataNewState(pctxt->am);
|
||||
base = xmlAutomataNewState(pctxt->am);
|
||||
|
||||
sub = particle->children->children;
|
||||
while (sub != NULL) {
|
||||
pctxt->state = base;
|
||||
tmp2 = xmlSchemaBuildAContentModel(pctxt,
|
||||
(xmlSchemaParticlePtr) sub);
|
||||
if (tmp2 == 1) ret = 1;
|
||||
xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
|
||||
sub = sub->next;
|
||||
}
|
||||
break;
|
||||
xmlAutomataNewEpsilon(pctxt->am, start, base);
|
||||
xmlAutomataNewCountedTrans(pctxt->am, hop, base, counter);
|
||||
xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter);
|
||||
if (ret == 1)
|
||||
xmlAutomataNewEpsilon(pctxt->am, base, end);
|
||||
}
|
||||
if (particle->minOccurs == 0) {
|
||||
xmlAutomataNewEpsilon(pctxt->am, start, end);
|
||||
ret = 1;
|
||||
}
|
||||
pctxt->state = end;
|
||||
break;
|
||||
}
|
||||
case XML_SCHEMA_TYPE_ALL:{
|
||||
xmlAutomataStatePtr start, tmp;
|
||||
xmlSchemaParticlePtr sub;
|
||||
xmlSchemaElementPtr elemDecl;
|
||||
|
||||
ret = 1;
|
||||
|
||||
sub = (xmlSchemaParticlePtr) particle->children->children;
|
||||
if (sub == NULL)
|
||||
break;
|
||||
|
||||
ret = 0;
|
||||
|
||||
start = pctxt->state;
|
||||
tmp = xmlAutomataNewState(pctxt->am);
|
||||
xmlAutomataNewEpsilon(pctxt->am, pctxt->state, tmp);
|
||||
pctxt->state = tmp;
|
||||
while (sub != NULL) {
|
||||
pctxt->state = tmp;
|
||||
|
||||
elemDecl = (xmlSchemaElementPtr) sub->children;
|
||||
if (elemDecl == NULL) {
|
||||
PERROR_INT("xmlSchemaBuildAContentModel",
|
||||
"<element> particle has no term");
|
||||
return(ret);
|
||||
};
|
||||
/*
|
||||
* NOTE: The {max occurs} of all the particles in the
|
||||
* {particles} of the group must be 0 or 1; this is
|
||||
* already ensured during the parse of the content of
|
||||
* <all>.
|
||||
*/
|
||||
if (elemDecl->flags & XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) {
|
||||
int counter;
|
||||
|
||||
/*
|
||||
* This is an abstract group, we need to share
|
||||
* the same counter for all the element transitions
|
||||
* derived from the group
|
||||
*/
|
||||
counter = xmlAutomataNewCounter(pctxt->am,
|
||||
sub->minOccurs, sub->maxOccurs);
|
||||
xmlSchemaBuildContentModelForSubstGroup(pctxt,
|
||||
sub, counter, pctxt->state);
|
||||
} else {
|
||||
if ((sub->minOccurs == 1) &&
|
||||
(sub->maxOccurs == 1)) {
|
||||
xmlAutomataNewOnceTrans2(pctxt->am, pctxt->state,
|
||||
pctxt->state,
|
||||
elemDecl->name,
|
||||
elemDecl->targetNamespace,
|
||||
1, 1, elemDecl);
|
||||
} else if ((sub->minOccurs == 0) &&
|
||||
(sub->maxOccurs == 1)) {
|
||||
|
||||
xmlAutomataNewCountTrans2(pctxt->am, pctxt->state,
|
||||
pctxt->state,
|
||||
elemDecl->name,
|
||||
elemDecl->targetNamespace,
|
||||
0,
|
||||
1,
|
||||
elemDecl);
|
||||
}
|
||||
}
|
||||
sub = (xmlSchemaParticlePtr) sub->next;
|
||||
}
|
||||
pctxt->state =
|
||||
xmlAutomataNewAllTrans(pctxt->am, pctxt->state, NULL, 0);
|
||||
if (particle->minOccurs == 0) {
|
||||
xmlAutomataNewEpsilon(pctxt->am, start, pctxt->state);
|
||||
ret = 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case XML_SCHEMA_TYPE_GROUP:
|
||||
/*
|
||||
* If we hit a model group definition, then this means that
|
||||
@ -13041,14 +13090,16 @@ xmlSchemaBuildAContentModel(xmlSchemaParserCtxtPtr pctxt,
|
||||
* TODO: But the group should be substituted and not occur at
|
||||
* all in the content model at this point. Fix this.
|
||||
*/
|
||||
ret = 1;
|
||||
break;
|
||||
default:
|
||||
xmlSchemaInternalErr2(ACTXT_CAST pctxt,
|
||||
"xmlSchemaBuildAContentModel",
|
||||
"found unexpected term of type '%s' in content model",
|
||||
WXS_ITEM_TYPE_NAME(particle->children), NULL);
|
||||
return;
|
||||
return(ret);
|
||||
}
|
||||
return(ret);
|
||||
}
|
||||
|
||||
/**
|
||||
|
Loading…
x
Reference in New Issue
Block a user