1
0
mirror of https://gitlab.gnome.org/GNOME/libxml2.git synced 2025-01-13 13:17:36 +03:00

include seems to work okay now augmented/updated the regression tests

* relaxng: include seems to work okay now
* test/relaxng/* result/relaxng/*: augmented/updated the
  regression tests
Daniel
This commit is contained in:
Daniel Veillard 2003-02-02 14:35:17 +00:00
parent a9d912de79
commit e2a5a08b0f
47 changed files with 410 additions and 86 deletions

View File

@ -1,3 +1,9 @@
Sun Feb 2 15:33:38 CET 2003 Daniel Veillard <daniel@veillard.com>
* relaxng: include seems to work okay now
* test/relaxng/* result/relaxng/*: augmented/updated the
regression tests
Sat Feb 1 19:44:58 CET 2003 Daniel Veillard <daniel@veillard.com>
* relaxng.c: a bit of work done in the train back.

176
relaxng.c
View File

@ -8,10 +8,10 @@
/**
* TODO:
* - <interleave></interleave><element>...
* - error reporting
* - module
* - fixing ref/def cross grammar contexts
* - simplification of the resulting compiled trees:
* - NOT_ALLOWED
* - EMPTY
*/
#define IN_LIBXML
@ -1560,6 +1560,8 @@ static xmlRelaxNGDefinePtr xmlRelaxNGParsePattern(
xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node);
static xmlRelaxNGPtr xmlRelaxNGParseDocument(
xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node);
static int xmlRelaxNGParseGrammarContent(
xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr nodes);
#define IS_BLANK_NODE(n) \
@ -2086,6 +2088,61 @@ xmlRelaxNGParseInterleave(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node) {
return(def);
}
/**
* xmlRelaxNGParseInclude:
* @ctxt: a Relax-NG parser context
* @node: the include node
*
* Integrate the content of an include node in the current grammar
*
* Returns 0 in case of success or -1 in case of error
*/
static int
xmlRelaxNGParseInclude(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node) {
xmlRelaxNGIncludePtr incl;
xmlNodePtr root;
int ret = 0, tmp;
incl = node->_private;
if (incl == NULL) {
if (ctxt->error != NULL)
ctxt->error(ctxt->userData,
"Include node has no data\n");
ctxt->nbErrors++;
return(-1);
}
root = xmlDocGetRootElement(incl->doc);
if (root == NULL) {
if (ctxt->error != NULL)
ctxt->error(ctxt->userData,
"Include document is empty\n");
ctxt->nbErrors++;
return(-1);
}
if (!xmlStrEqual(root->name, BAD_CAST "grammar")) {
if (ctxt->error != NULL)
ctxt->error(ctxt->userData,
"Include document root is not a grammar\n");
ctxt->nbErrors++;
return(-1);
}
/*
* Merge the definition from both the include and the internal list
*/
if (root->children != NULL) {
tmp = xmlRelaxNGParseGrammarContent(ctxt, root->children);
if (tmp != 0)
ret = -1;
}
if (node->children != NULL) {
tmp = xmlRelaxNGParseGrammarContent(ctxt, node->children);
if (tmp != 0)
ret = -1;
}
return(ret);
}
/**
* xmlRelaxNGParseDefine:
* @ctxt: a Relax-NG parser context
@ -2093,7 +2150,7 @@ xmlRelaxNGParseInterleave(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node) {
*
* parse the content of a RelaxNG define element node.
*
* Returns the definition pointer or NULL in case of error.
* Returns 0 in case of success or -1 in case of error
*/
static int
xmlRelaxNGParseDefine(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node) {
@ -2332,8 +2389,20 @@ xmlRelaxNGParsePattern(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node) {
} else {
def = NULL;
}
} else if (IS_RELAXNG(node, "notAllowed")) {
def = xmlRelaxNGNewDefine(ctxt, node);
if (def == NULL)
return(NULL);
def->type = XML_RELAXNG_NOT_ALLOWED;
if (node->children != NULL) {
if (ctxt->error != NULL)
ctxt->error(ctxt->userData,
"xmlRelaxNGParse: notAllowed element is not empty\n");
ctxt->nbErrors++;
}
} else {
TODO
def = NULL;
}
return(def);
}
@ -2644,10 +2713,9 @@ xmlRelaxNGParseStart(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr nodes) {
* Returns 0 in case of success, -1 in case of error
*/
static int
xmlRelaxNGParseGrammarContent(xmlRelaxNGParserCtxtPtr ctxt
ATTRIBUTE_UNUSED, xmlNodePtr nodes)
xmlRelaxNGParseGrammarContent(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr nodes)
{
int ret = 0;
int ret = 0, tmp;
if (nodes == NULL) {
if (ctxt->error != NULL)
@ -2656,30 +2724,30 @@ xmlRelaxNGParseGrammarContent(xmlRelaxNGParserCtxtPtr ctxt
ctxt->nbErrors++;
return(-1);
}
if (IS_RELAXNG(nodes, "start")) {
if (nodes->children == NULL) {
if (ctxt->error != NULL)
ctxt->error(ctxt->userData,
"grammar has no children\n");
ctxt->nbErrors++;
} else {
xmlRelaxNGParseStart(ctxt, nodes->children);
}
nodes = nodes->next;
} else {
if (ctxt->error != NULL)
ctxt->error(ctxt->userData,
"grammar first child must be a <start>\n");
ctxt->nbErrors++;
return(-1);
}
while (nodes != NULL) {
if (IS_RELAXNG(nodes, "define")) {
ret = xmlRelaxNGParseDefine(ctxt, nodes);
if (IS_RELAXNG(nodes, "start")) {
if (nodes->children == NULL) {
if (ctxt->error != NULL)
ctxt->error(ctxt->userData,
"grammar has no children\n");
ctxt->nbErrors++;
} else {
tmp = xmlRelaxNGParseStart(ctxt, nodes->children);
if (tmp != 0)
ret = -1;
}
} else if (IS_RELAXNG(nodes, "define")) {
tmp = xmlRelaxNGParseDefine(ctxt, nodes);
if (tmp != 0)
ret = -1;
} else if (IS_RELAXNG(nodes, "include")) {
tmp = xmlRelaxNGParseInclude(ctxt, nodes);
if (tmp != 0)
ret = -1;
} else {
if (ctxt->error != NULL)
ctxt->error(ctxt->userData,
"grammar allows onlys <define> child after <start>\n");
"grammar has unexpected child %s\n", nodes->name);
ctxt->nbErrors++;
ret = -1;
}
@ -3213,23 +3281,7 @@ xmlRelaxNGCleanupDoc(xmlRelaxNGParserCtxtPtr ctxt, xmlDocPtr doc) {
delete = cur;
goto skip_children;
} else {
if (xmlStrEqual(cur->name, BAD_CAST "div")) {
/*
* implements rule 4.11
*/
xmlNodePtr child, ins, tmp;
child = cur->children;
ins = child;
while (child != NULL) {
tmp = child->next;
xmlUnlinkNode(child);
ins = xmlAddNextSibling(ins, child);
child = tmp;
}
delete = cur;
goto skip_children;
} else if (xmlStrEqual(cur->name, BAD_CAST "externalRef")) {
if (xmlStrEqual(cur->name, BAD_CAST "externalRef")) {
xmlChar *href, *ns, *base, *URL;
xmlRelaxNGDocumentPtr docu;
@ -3281,7 +3333,7 @@ xmlRelaxNGCleanupDoc(xmlRelaxNGParserCtxtPtr ctxt, xmlDocPtr doc) {
if (href == NULL) {
if (ctxt->error != NULL)
ctxt->error(ctxt->userData,
"xmlRelaxNGParse: externalRef has no href attribute\n");
"xmlRelaxNGParse: include has no href attribute\n");
ctxt->nbErrors++;
delete = cur;
goto skip_children;
@ -3291,7 +3343,7 @@ xmlRelaxNGCleanupDoc(xmlRelaxNGParserCtxtPtr ctxt, xmlDocPtr doc) {
if (URL == NULL) {
if (ctxt->error != NULL)
ctxt->error(ctxt->userData,
"Failed to compute URL for externalRef %s\n", href);
"Failed to compute URL for include %s\n", href);
ctxt->nbErrors++;
if (href != NULL)
xmlFree(href);
@ -3308,7 +3360,7 @@ xmlRelaxNGCleanupDoc(xmlRelaxNGParserCtxtPtr ctxt, xmlDocPtr doc) {
if (incl == NULL) {
if (ctxt->error != NULL)
ctxt->error(ctxt->userData,
"Failed to load externalRef %s\n", URL);
"Failed to load include %s\n", URL);
ctxt->nbErrors++;
xmlFree(URL);
delete = cur;
@ -3418,6 +3470,27 @@ xmlRelaxNGCleanupDoc(xmlRelaxNGParserCtxtPtr ctxt, xmlDocPtr doc) {
}
}
}
/*
* Thisd is not an else since "include" is transformed
* into a div
*/
if (xmlStrEqual(cur->name, BAD_CAST "div")) {
/*
* implements rule 4.11
*/
xmlNodePtr child, ins, tmp;
child = cur->children;
ins = child;
while (child != NULL) {
tmp = child->next;
xmlUnlinkNode(child);
ins = xmlAddNextSibling(ins, child);
child = tmp;
}
delete = cur;
goto skip_children;
}
}
}
/*
@ -3587,6 +3660,8 @@ xmlRelaxNGParse(xmlRelaxNGParserCtxtPtr ctxt)
ctxt->document = NULL;
ret->documents = ctxt->documents;
ctxt->documents = NULL;
ret->includes = ctxt->includes;
ctxt->includes = NULL;
return (ret);
}
@ -4631,8 +4706,7 @@ xmlRelaxNGValidateDefinition(xmlRelaxNGValidCtxtPtr ctxt,
#endif
return(0);
case XML_RELAXNG_NOT_ALLOWED:
TODO
break;
return(-1);
case XML_RELAXNG_TEXT:
if (node == NULL)
return(0);
@ -4794,6 +4868,7 @@ xmlRelaxNGValidateDefinition(xmlRelaxNGValidCtxtPtr ctxt,
ctxt->flags = oldflags;
break;
}
case XML_RELAXNG_DEF:
case XML_RELAXNG_GROUP: {
xmlRelaxNGDefinePtr list = define->content;
@ -4815,9 +4890,6 @@ xmlRelaxNGValidateDefinition(xmlRelaxNGValidCtxtPtr ctxt,
case XML_RELAXNG_REF:
ret = xmlRelaxNGValidateDefinition(ctxt, define->content);
break;
case XML_RELAXNG_DEF:
ret = xmlRelaxNGValidateDefinition(ctxt, define->content);
break;
case XML_RELAXNG_DATATYPE: {
xmlChar *content;

View File

@ -1,3 +1,3 @@
error detected at relaxng.c:4293
error detected at relaxng.c:4341
error detected at relaxng.c:4733
error detected at relaxng.c:4781
xmlRelaxNGValidateDefinition(): validated card : -1

View File

@ -1,5 +1,5 @@
xmlRelaxNGValidateAttribute(name): -1
xmlRelaxNGValidateDefinition(): validated email : 0
xmlRelaxNGValidateDefinition(): validated card : -1
error detected at relaxng.c:4341
error detected at relaxng.c:4781
xmlRelaxNGValidateDefinition(): validated addressBook : -1

View File

@ -1,2 +1 @@
Extra content for element addressBook
./test/relaxng/tutor4_1_1.xml validation generated an internal error
./test/relaxng/tutor4_1_1.xml validates

View File

@ -1,4 +1,7 @@
xmlRelaxNGValidateDefinition(): validated name : 0
xmlRelaxNGValidateDefinition(): validated card : -1
error detected at relaxng.c:4341
xmlRelaxNGValidateDefinition(): validated addressBook : -1
xmlRelaxNGValidateDefinition(): validated email : 0
xmlRelaxNGValidateDefinition(): validated card : 0
xmlRelaxNGValidateDefinition(): validated name : 0
xmlRelaxNGValidateDefinition(): validated email : 0
xmlRelaxNGValidateDefinition(): validated card : 0
xmlRelaxNGValidateDefinition(): validated addressBook : 0

View File

@ -1,3 +1,3 @@
error detected at relaxng.c:4472
error detected at relaxng.c:4910
xmlRelaxNGValidateDefinition(): validated note : 0
xmlRelaxNGValidateDefinition(): validated bad : -1

View File

@ -1,5 +1,5 @@
xmlRelaxNGValidateAttribute(preferredFormat): -1
xmlRelaxNGValidateAttribute(email): 0
xmlRelaxNGValidateAttribute(name): 0
error detected at relaxng.c:4349
error detected at relaxng.c:4789
xmlRelaxNGValidateDefinition(): validated card : -1

View File

@ -1,5 +1,5 @@
xmlRelaxNGValidateDefinition(): validated name : 0
xmlRelaxNGValidateDefinition(): validated email : 0
error detected at relaxng.c:4341
error detected at relaxng.c:4781
xmlRelaxNGValidateDefinition(): validated preferredFormat : -1
xmlRelaxNGValidateDefinition(): validated card : -1

View File

@ -1,5 +1,5 @@
xmlRelaxNGValidateAttribute(preferredFormat): -1
xmlRelaxNGValidateAttribute(email): 0
xmlRelaxNGValidateAttribute(name): 0
error detected at relaxng.c:4349
error detected at relaxng.c:4789
xmlRelaxNGValidateDefinition(): validated card : -1

View File

@ -1,5 +1,5 @@
Unimplemented block at xmlschemastypes.c:1132
error detected at relaxng.c:3551
error detected at relaxng.c:4526
error detected at relaxng.c:4341
error detected at relaxng.c:3992
error detected at relaxng.c:4964
error detected at relaxng.c:4781
xmlRelaxNGValidateDefinition(): validated vector : -1

View File

@ -1,6 +1,6 @@
Unimplemented block at xmlschemastypes.c:1132
Unimplemented block at xmlschemastypes.c:1132
error detected at relaxng.c:3739
error detected at relaxng.c:4526
error detected at relaxng.c:4341
error detected at relaxng.c:4180
error detected at relaxng.c:4964
error detected at relaxng.c:4781
xmlRelaxNGValidateDefinition(): validated vector : -1

View File

@ -1,3 +1,3 @@
error detected at relaxng.c:3714
error detected at relaxng.c:4526
error detected at relaxng.c:4155
error detected at relaxng.c:4964
xmlRelaxNGValidateDefinition(): validated vector : -1

View File

@ -1,7 +1,7 @@
Unimplemented block at xmlschemastypes.c:1135
Unimplemented block at xmlschemastypes.c:1135
Unimplemented block at xmlschemastypes.c:1135
error detected at relaxng.c:3739
error detected at relaxng.c:4526
error detected at relaxng.c:4341
error detected at relaxng.c:4180
error detected at relaxng.c:4964
error detected at relaxng.c:4781
xmlRelaxNGValidateDefinition(): validated path : -1

View File

@ -1,5 +1,5 @@
Unimplemented block at xmlschemastypes.c:1135
error detected at relaxng.c:3551
error detected at relaxng.c:4526
error detected at relaxng.c:4341
error detected at relaxng.c:3992
error detected at relaxng.c:4964
error detected at relaxng.c:4781
xmlRelaxNGValidateDefinition(): validated path : -1

View File

@ -3,5 +3,5 @@ xmlRelaxNGComputeInterleaves(interleave0)
6 groups
xmlRelaxNGValidateDefinition(): validated title : 0
xmlRelaxNGValidateDefinition(): validated title : 0
error detected at relaxng.c:4341
error detected at relaxng.c:4781
xmlRelaxNGValidateDefinition(): validated head : -1

View File

@ -1,6 +1,6 @@
xmlRelaxNGComputeInterleaves(interleave0)
6 child
6 groups
error detected at relaxng.c:4287
error detected at relaxng.c:4341
error detected at relaxng.c:4727
error detected at relaxng.c:4781
xmlRelaxNGValidateDefinition(): validated head : -1

View File

@ -4,5 +4,5 @@ xmlRelaxNGComputeInterleaves(interleave0)
xmlRelaxNGValidateDefinition(): validated title : 0
xmlRelaxNGValidateDefinition(): validated base : 0
xmlRelaxNGValidateDefinition(): validated base : 0
error detected at relaxng.c:4341
error detected at relaxng.c:4781
xmlRelaxNGValidateDefinition(): validated head : -1

View File

@ -0,0 +1 @@
./test/relaxng/tutor9_10_1.xml validates

View File

@ -0,0 +1,6 @@
xmlRelaxNGCheckCombine(): merging inline.extra defines: 1
xmlRelaxNGValidateDefinition(): validated italic : 0
xmlRelaxNGValidateDefinition(): validated em : 0
xmlRelaxNGValidateDefinition(): validated bold : 0
xmlRelaxNGValidateDefinition(): validated p : 0
xmlRelaxNGValidateDefinition(): validated doc : 0

View File

@ -0,0 +1 @@
./test/relaxng/tutor9_11_1.xml validates

View File

@ -0,0 +1,4 @@
xmlRelaxNGValidateDefinition(): validated name : 0
xmlRelaxNGValidateDefinition(): validated emailAddress : 0
xmlRelaxNGValidateDefinition(): validated card : 0
xmlRelaxNGValidateDefinition(): validated addressBook : 0

View File

@ -0,0 +1 @@
./test/relaxng/tutor9_12_1.xml validates

View File

@ -0,0 +1,4 @@
xmlRelaxNGValidateDefinition(): validated name : 0
xmlRelaxNGValidateDefinition(): validated emailAddress : 0
xmlRelaxNGValidateDefinition(): validated card : 0
xmlRelaxNGValidateDefinition(): validated addressBook : 0

View File

@ -5,5 +5,5 @@ xmlRelaxNGComputeInterleaves(interleave0)
xmlRelaxNGValidateAttribute(name): 0
xmlRelaxNGValidateAttribute(email): -1
xmlRelaxNGValidateDefinition(): validated card : -1
error detected at relaxng.c:4341
error detected at relaxng.c:4781
xmlRelaxNGValidateDefinition(): validated addressBook : -1

View File

@ -5,5 +5,5 @@ xmlRelaxNGComputeInterleaves(interleave0)
xmlRelaxNGValidateAttribute(name): 0
xmlRelaxNGValidateAttribute(email): 0
xmlRelaxNGValidateDefinition(): validated card : -1
error detected at relaxng.c:4341
error detected at relaxng.c:4781
xmlRelaxNGValidateDefinition(): validated addressBook : -1

View File

@ -1,5 +1,5 @@
xmlRelaxNGValidateAttribute(name): 0
xmlRelaxNGValidateAttribute(email): -1
xmlRelaxNGValidateDefinition(): validated card : -1
error detected at relaxng.c:4341
error detected at relaxng.c:4781
xmlRelaxNGValidateDefinition(): validated addressBook : -1

View File

@ -1,5 +1,5 @@
xmlRelaxNGValidateAttribute(name): 0
xmlRelaxNGValidateAttribute(email): 0
xmlRelaxNGValidateDefinition(): validated card : -1
error detected at relaxng.c:4341
error detected at relaxng.c:4781
xmlRelaxNGValidateDefinition(): validated addressBook : -1

View File

@ -0,0 +1 @@
./test/relaxng/tutor9_7_1.xml validates

View File

@ -0,0 +1,6 @@
xmlRelaxNGCheckCombine(): merging inline.class defines: 1
xmlRelaxNGValidateDefinition(): validated italic : 0
xmlRelaxNGValidateDefinition(): validated em : 0
xmlRelaxNGValidateDefinition(): validated bold : 0
xmlRelaxNGValidateDefinition(): validated p : 0
xmlRelaxNGValidateDefinition(): validated doc : 0

View File

@ -0,0 +1 @@
./test/relaxng/tutor9_8_1.xml validates

View File

@ -0,0 +1,6 @@
xmlRelaxNGCheckCombine(): merging inline.class defines: 1
xmlRelaxNGValidateDefinition(): validated italic : 0
xmlRelaxNGValidateDefinition(): validated em : 0
xmlRelaxNGValidateDefinition(): validated bold : 0
xmlRelaxNGValidateDefinition(): validated p : 0
xmlRelaxNGValidateDefinition(): validated doc : 0

View File

@ -0,0 +1 @@
./test/relaxng/tutor9_9_1.xml validates

View File

@ -0,0 +1,5 @@
xmlRelaxNGValidateDefinition(): validated italic : 0
xmlRelaxNGValidateDefinition(): validated em : 0
xmlRelaxNGValidateDefinition(): validated bold : 0
xmlRelaxNGValidateDefinition(): validated p : 0
xmlRelaxNGValidateDefinition(): validated doc : 0

View File

@ -0,0 +1,24 @@
<grammar xmlns="http://relaxng.org/ns/structure/1.0">
<start>
<element name="addressBook">
<zeroOrMore>
<element name="card">
<ref name="cardContent"/>
</element>
</zeroOrMore>
</element>
</start>
<define name="cardContent">
<element name="name">
<text/>
</element>
<element name="email">
<text/>
</element>
</define>
</grammar>

22
test/relaxng/inline3.rng Normal file
View File

@ -0,0 +1,22 @@
<grammar xmlns="http://relaxng.org/ns/structure/1.0">
<define name="inline">
<zeroOrMore>
<choice>
<text/>
<element name="bold">
<ref name="inline"/>
</element>
<element name="italic">
<ref name="inline"/>
</element>
<ref name="inline.extra"/>
</choice>
</zeroOrMore>
</define>
<define name="inline.extra">
<notAllowed/>
</define>
</grammar>

View File

@ -0,0 +1,26 @@
<grammar xmlns="http://relaxng.org/ns/structure/1.0">
<include href="inline3.rng"/>
<start>
<element name="doc">
<zeroOrMore>
<element name="p">
<ref name="inline"/>
</element>
</zeroOrMore>
</element>
</start>
<define name="inline.extra" combine="choice">
<choice>
<element name="code">
<ref name="inline"/>
</element>
<element name="em">
<ref name="inline"/>
</element>
</choice>
</define>
</grammar>

View File

@ -0,0 +1,3 @@
<doc>
<p>a<bold>b<em>c<italic>d</italic>e</em>f</bold>g</p>
</doc>

View File

@ -0,0 +1,16 @@
<grammar xmlns="http://relaxng.org/ns/structure/1.0">
<include href="addressBook.rng">
<define name="cardContent">
<element name="name">
<text/>
</element>
<element name="emailAddress">
<text/>
</element>
</define>
</include>
</grammar>

View File

@ -0,0 +1,3 @@
<addressBook>
<card><name>foo</name><emailAddress>bar</emailAddress></card>
</addressBook>

View File

@ -0,0 +1,22 @@
<grammar xmlns="http://relaxng.org/ns/structure/1.0">
<start>
<element name="addressBook">
<zeroOrMore>
<element name="card">
<ref name="cardContent"/>
</element>
</zeroOrMore>
</element>
</start>
<define name="cardContent">
<element name="name">
<text/>
</element>
<element name="emailAddress">
<text/>
</element>
</define>
</grammar>

View File

@ -0,0 +1,3 @@
<addressBook>
<card><name>foo</name><emailAddress>bar</emailAddress></card>
</addressBook>

View File

@ -0,0 +1,3 @@
<doc>
<p>a<bold>b<em>c<italic>d</italic>e</em>f</bold>g</p>
</doc>

42
test/relaxng/tutor9_8.rng Normal file
View File

@ -0,0 +1,42 @@
<grammar xmlns="http://relaxng.org/ns/structure/1.0">
<define name="inline">
<zeroOrMore>
<ref name="inline.class"/>
</zeroOrMore>
</define>
<define name="inline.class">
<choice>
<text/>
<element name="bold">
<ref name="inline"/>
</element>
<element name="italic">
<ref name="inline"/>
</element>
</choice>
</define>
<start>
<element name="doc">
<zeroOrMore>
<element name="p">
<ref name="inline"/>
</element>
</zeroOrMore>
</element>
</start>
<define name="inline.class" combine="choice">
<choice>
<element name="code">
<ref name="inline"/>
</element>
<element name="em">
<ref name="inline"/>
</element>
</choice>
</define>
</grammar>

View File

@ -0,0 +1,3 @@
<doc>
<p>a<bold>b<em>c<italic>d</italic>e</em>f</bold>g</p>
</doc>

37
test/relaxng/tutor9_9.rng Normal file
View File

@ -0,0 +1,37 @@
<grammar xmlns="http://relaxng.org/ns/structure/1.0">
<define name="inline">
<zeroOrMore>
<ref name="inline.class"/>
</zeroOrMore>
</define>
<define name="inline.class">
<choice>
<text/>
<element name="bold">
<ref name="inline"/>
</element>
<element name="italic">
<ref name="inline"/>
</element>
<element name="code">
<ref name="inline"/>
</element>
<element name="em">
<ref name="inline"/>
</element>
</choice>
</define>
<start>
<element name="doc">
<zeroOrMore>
<element name="p">
<ref name="inline"/>
</element>
</zeroOrMore>
</element>
</start>
</grammar>

View File

@ -0,0 +1,3 @@
<doc>
<p>a<bold>b<em>c<italic>d</italic>e</em>f</bold>g</p>
</doc>