updated the policy on private mail answers more work on Relax-NG
* README: updated the policy on private mail answers
* relaxng.c: more work on Relax-NG
* test/relaxng/* result/relaxng/*: augmented/updated the
regression tests
Daniel
diff --git a/ChangeLog b/ChangeLog
index 9229d9f..d53f386 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+Sat Jan 25 18:59:54 CET 2003 Daniel Veillard <daniel@veillard.com>
+
+ * README: updated the policy on private mail answers
+ * relaxng.c: more work on Relax-NG
+ * test/relaxng/* result/relaxng/*: augmented/updated the
+ regression tests
+
Fri Jan 24 15:12:44 CET 2003 Daniel Veillard <daniel@veillard.com>
* error.c parser.c tree.c: applied a documentation patch from
diff --git a/README b/README
index f521497..279b375 100644
--- a/README
+++ b/README
@@ -15,6 +15,10 @@
The list archive is at:
http://mail.gnome.org/archives/xml/
+All technical answers asked privately will be automatically answered on
+the list and archived for public access unless pricacy is explicitely
+required and justified.
+
Daniel Veillard
$Id$
diff --git a/relaxng.c b/relaxng.c
index 7ca09a3..61af8c0 100644
--- a/relaxng.c
+++ b/relaxng.c
@@ -74,11 +74,6 @@
};
-#if 0
-struct _xmlRelaxNGSchema {
-};
-#endif
-
typedef enum {
XML_RELAXNG_EMPTY = 0, /* an empty pattern */
XML_RELAXNG_NOT_ALLOWED, /* not allowed top */
@@ -103,6 +98,7 @@
xmlNodePtr node; /* the node in the source */
xmlChar *name; /* the element local name if present */
xmlChar *ns; /* the namespace local name if present */
+ void *data; /* data lib or specific pointer */
xmlRelaxNGDefinePtr content;/* the expected content */
xmlRelaxNGDefinePtr next; /* list within grouping sequences */
xmlRelaxNGDefinePtr attrs; /* list of attributes for elements */
@@ -197,6 +193,61 @@
/************************************************************************
* *
+ * Preliminary type checking interfaces *
+ * *
+ ************************************************************************/
+/**
+ * xmlRelaxNGTypeHave:
+ * @data: data needed for the library
+ * @type: the type name
+ * @value: the value to check
+ *
+ * Function provided by a type library to check if a type is exported
+ *
+ * Returns 1 if yes, 0 if no and -1 in case of error.
+ */
+typedef int (*xmlRelaxNGTypeHave) (void *data, const xmlChar *type);
+
+/**
+ * xmlRelaxNGTypeCheck:
+ * @data: data needed for the library
+ * @type: the type name
+ * @value: the value to check
+ *
+ * Function provided by a type library to check if a value match a type
+ *
+ * Returns 1 if yes, 0 if no and -1 in case of error.
+ */
+typedef int (*xmlRelaxNGTypeCheck) (void *data, const xmlChar *type,
+ const xmlChar *value);
+
+/**
+ * xmlRelaxNGTypeCompare:
+ * @data: data needed for the library
+ * @type: the type name
+ * @value1: the first value
+ * @value2: the second value
+ *
+ * Function provided by a type library to compare two values accordingly
+ * to a type.
+ *
+ * Returns 1 if yes, 0 if no and -1 in case of error.
+ */
+typedef int (*xmlRelaxNGTypeCompare) (void *data, const xmlChar *type,
+ const xmlChar *value1,
+ const xmlChar *value2);
+typedef struct _xmlRelaxNGTypeLibrary xmlRelaxNGTypeLibrary;
+typedef xmlRelaxNGTypeLibrary *xmlRelaxNGTypeLibraryPtr;
+struct _xmlRelaxNGTypeLibrary {
+ const xmlChar *namespace; /* the datatypeLibrary value */
+ void *data; /* data needed for the library */
+ xmlRelaxNGTypeHave have; /* the export function */
+ xmlRelaxNGTypeCheck check; /* the checking function */
+ xmlRelaxNGTypeCompare comp; /* the compare function */
+};
+
+/************************************************************************
+ * *
* Allocation functions *
* *
************************************************************************/
@@ -600,8 +651,226 @@
* *
************************************************************************/
+/**
+ * xmlRelaxNGSchemaTypeHave:
+ * @data: data needed for the library
+ * @type: the type name
+ *
+ * Check if the given type is provided by
+ * the W3C XMLSchema Datatype library.
+ *
+ * Returns 1 if yes, 0 if no and -1 in case of error.
+ */
+static int
+xmlRelaxNGSchemaTypeHave(void *data ATTRIBUTE_UNUSED,
+ const xmlChar *type ATTRIBUTE_UNUSED) {
+ TODO
+ return(1);
+}
+
+/**
+ * xmlRelaxNGSchemaTypeCheck:
+ * @data: data needed for the library
+ * @type: the type name
+ * @value: the value to check
+ *
+ * Check if the given type and value are validated by
+ * the W3C XMLSchema Datatype library.
+ *
+ * Returns 1 if yes, 0 if no and -1 in case of error.
+ */
+static int
+xmlRelaxNGSchemaTypeCheck(void *data ATTRIBUTE_UNUSED,
+ const xmlChar *type ATTRIBUTE_UNUSED,
+ const xmlChar *value ATTRIBUTE_UNUSED) {
+ TODO
+ return(1);
+}
+
+/**
+ * xmlRelaxNGSchemaTypeCompare:
+ * @data: data needed for the library
+ * @type: the type name
+ * @value1: the first value
+ * @value2: the second value
+ *
+ * Compare two values accordingly a type from the W3C XMLSchema
+ * Datatype library.
+ *
+ * Returns 1 if yes, 0 if no and -1 in case of error.
+ */
+static int
+xmlRelaxNGSchemaTypeCompare(void *data ATTRIBUTE_UNUSED,
+ const xmlChar *type ATTRIBUTE_UNUSED,
+ const xmlChar *value1 ATTRIBUTE_UNUSED,
+ const xmlChar *value2 ATTRIBUTE_UNUSED) {
+ TODO
+ return(1);
+}
+
+/**
+ * xmlRelaxNGDefaultTypeHave:
+ * @data: data needed for the library
+ * @type: the type name
+ *
+ * Check if the given type is provided by
+ * the default datatype library.
+ *
+ * Returns 1 if yes, 0 if no and -1 in case of error.
+ */
+static int
+xmlRelaxNGDefaultTypeHave(void *data ATTRIBUTE_UNUSED, const xmlChar *type) {
+ if (type == NULL)
+ return(-1);
+ if (xmlStrEqual(type, BAD_CAST "string"))
+ return(1);
+ if (xmlStrEqual(type, BAD_CAST "token"))
+ return(1);
+ return(0);
+}
+
+/**
+ * xmlRelaxNGDefaultTypeCheck:
+ * @data: data needed for the library
+ * @type: the type name
+ * @value: the value to check
+ *
+ * Check if the given type and value are validated by
+ * the default datatype library.
+ *
+ * Returns 1 if yes, 0 if no and -1 in case of error.
+ */
+static int
+xmlRelaxNGDefaultTypeCheck(void *data ATTRIBUTE_UNUSED,
+ const xmlChar *type ATTRIBUTE_UNUSED,
+ const xmlChar *value ATTRIBUTE_UNUSED) {
+ return(1);
+}
+
+/**
+ * xmlRelaxNGDefaultTypeCompare:
+ * @data: data needed for the library
+ * @type: the type name
+ * @value1: the first value
+ * @value2: the second value
+ *
+ * Compare two values accordingly a type from the default
+ * datatype library.
+ *
+ * Returns 1 if yes, 0 if no and -1 in case of error.
+ */
+static int
+xmlRelaxNGDefaultTypeCompare(void *data ATTRIBUTE_UNUSED,
+ const xmlChar *type ATTRIBUTE_UNUSED,
+ const xmlChar *value1 ATTRIBUTE_UNUSED,
+ const xmlChar *value2 ATTRIBUTE_UNUSED) {
+ TODO
+ return(1);
+}
+
+static int xmlRelaxNGTypeInitialized = 0;
+static xmlHashTablePtr xmlRelaxNGRegisteredTypes = NULL;
+
+/**
+ * xmlRelaxNGFreeTypeLibrary:
+ * @lib: the type library structure
+ * @namespace: the URI bound to the library
+ *
+ * Free the structure associated to the type library
+ */
static void
+xmlRelaxNGFreeTypeLibrary(xmlRelaxNGTypeLibraryPtr lib,
+ const xmlChar *namespace ATTRIBUTE_UNUSED) {
+ if (lib == NULL)
+ return;
+ if (lib->namespace != NULL)
+ xmlFree((xmlChar *)lib->namespace);
+ xmlFree(lib);
+}
+
+/**
+ * xmlRelaxNGRegisterTypeLibrary:
+ * @namespace: the URI bound to the library
+ * @data: data associated to the library
+ * @have: the provide function
+ * @check: the checking function
+ * @comp: the comparison function
+ *
+ * Register a new type library
+ *
+ * Returns 0 in case of success and -1 in case of error.
+ */
+static int
+xmlRelaxNGRegisterTypeLibrary(const xmlChar *namespace, void *data,
+ xmlRelaxNGTypeHave have, xmlRelaxNGTypeCheck check,
+ xmlRelaxNGTypeCompare comp) {
+ xmlRelaxNGTypeLibraryPtr lib;
+ int ret;
+
+ if ((xmlRelaxNGRegisteredTypes == NULL) || (namespace == NULL) ||
+ (check == NULL) || (comp == NULL))
+ return(-1);
+ if (xmlHashLookup(xmlRelaxNGRegisteredTypes, namespace) != NULL) {
+ xmlGenericError(xmlGenericErrorContext,
+ "Relax-NG types library '%s' already registered\n",
+ namespace);
+ return(-1);
+ }
+ lib = (xmlRelaxNGTypeLibraryPtr) xmlMalloc(sizeof(xmlRelaxNGTypeLibrary));
+ if (lib == NULL) {
+ xmlGenericError(xmlGenericErrorContext,
+ "Relax-NG types library '%s' malloc() failed\n",
+ namespace);
+ return (-1);
+ }
+ memset(lib, 0, sizeof(xmlRelaxNGTypeLibrary));
+ lib->namespace = xmlStrdup(namespace);
+ lib->data = data;
+ lib->have = have;
+ lib->comp = comp;
+ lib->check = check;
+ ret = xmlHashAddEntry(xmlRelaxNGRegisteredTypes, namespace, lib);
+ if (ret < 0) {
+ xmlGenericError(xmlGenericErrorContext,
+ "Relax-NG types library failed to register '%s'\n",
+ namespace);
+ xmlRelaxNGFreeTypeLibrary(lib, namespace);
+ return(-1);
+ }
+ return(0);
+}
+
+/**
+ * xmlRelaxNGInitTypes:
+ *
+ * Initilize the default type libraries.
+ *
+ * Returns 0 in case of success and -1 in case of error.
+ */
+static int
xmlRelaxNGInitTypes(void) {
+ if (xmlRelaxNGTypeInitialized != 0)
+ return(0);
+ xmlRelaxNGRegisteredTypes = xmlHashCreate(10);
+ if (xmlRelaxNGRegisteredTypes == NULL) {
+ xmlGenericError(xmlGenericErrorContext,
+ "Failed to allocate sh table for Relax-NG types\n");
+ return(-1);
+ }
+ xmlRelaxNGRegisterTypeLibrary(
+ BAD_CAST "http://www.w3.org/2001/XMLSchema-datatypes",
+ NULL,
+ xmlRelaxNGSchemaTypeHave,
+ xmlRelaxNGSchemaTypeCheck,
+ xmlRelaxNGSchemaTypeCompare);
+ xmlRelaxNGRegisterTypeLibrary(
+ xmlRelaxNGNs,
+ NULL,
+ xmlRelaxNGDefaultTypeHave,
+ xmlRelaxNGDefaultTypeCheck,
+ xmlRelaxNGDefaultTypeCompare);
+ xmlRelaxNGTypeInitialized = 1;
+ return(0);
}
/**
@@ -611,7 +880,12 @@
*/
void
xmlRelaxNGCleanupTypes(void) {
+ if (xmlRelaxNGTypeInitialized == 0)
+ return;
xmlSchemaCleanupTypes();
+ xmlHashFree(xmlRelaxNGRegisteredTypes, (xmlHashDeallocator)
+ xmlRelaxNGFreeTypeLibrary);
+ xmlRelaxNGTypeInitialized = 0;
}
/************************************************************************
@@ -650,7 +924,6 @@
return(1);
}
-#if 0
/**
* xmlRelaxNGGetDataTypeLibrary:
* @ctxt: a Relax-NG parser context
@@ -665,15 +938,10 @@
xmlNodePtr node) {
xmlChar *ret, *escape;
-#ifdef DEBUG
- xmlGenericError(xmlGenericErrorContext,
- "xmlRelaxNGGetDataTypeLibrary()\n");
-#endif
-
if ((IS_RELAXNG(node, "data")) || (IS_RELAXNG(node, "value"))) {
ret = xmlGetProp(node, BAD_CAST "datatypeLibrary");
if (ret != NULL) {
- escape = xmlURIEscapeStr(ret, BAD_CAST "");
+ escape = xmlURIEscapeStr(ret, BAD_CAST ":/#?");
if (escape == NULL) {
return(ret);
}
@@ -686,7 +954,7 @@
if (IS_RELAXNG(node, "element")) {
ret = xmlGetProp(node, BAD_CAST "datatypeLibrary");
if (ret != NULL) {
- escape = xmlURIEscapeStr(ret, BAD_CAST "");
+ escape = xmlURIEscapeStr(ret, BAD_CAST ":/#?");
if (escape == NULL) {
return(ret);
}
@@ -698,7 +966,81 @@
}
return(NULL);
}
-#endif
+
+/**
+ * xmlRelaxNGParseData:
+ * @ctxt: a Relax-NG parser context
+ * @node: the data node.
+ *
+ * parse the content of a RelaxNG data node.
+ *
+ * Returns the definition pointer or NULL in case of error
+ */
+static xmlRelaxNGDefinePtr
+xmlRelaxNGParseData(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node) {
+ xmlRelaxNGDefinePtr def = NULL;
+ xmlRelaxNGTypeLibraryPtr lib;
+ xmlChar *type;
+ xmlChar *library;
+ xmlNodePtr content;
+ int tmp;
+
+ type = xmlGetProp(node, BAD_CAST "type");
+ if (type == NULL) {
+ if (ctxt->error != NULL)
+ ctxt->error(ctxt->userData,
+ "data has no type\n");
+ ctxt->nbErrors++;
+ return(NULL);
+ }
+ library = xmlRelaxNGGetDataTypeLibrary(ctxt, node);
+ if (library == NULL)
+ library = xmlStrdup(BAD_CAST "http://relaxng.org/ns/structure/1.0");
+
+ def = xmlRelaxNGNewDefine(ctxt, node);
+ if (def == NULL) {
+ xmlFree(type);
+ return(NULL);
+ }
+ def->type = XML_RELAXNG_DATATYPE;
+ def->name = type;
+ def->ns = library;
+
+ lib = (xmlRelaxNGTypeLibraryPtr)
+ xmlHashLookup(xmlRelaxNGRegisteredTypes, library);
+ if (lib == NULL) {
+ if (ctxt->error != NULL)
+ ctxt->error(ctxt->userData,
+ "Use of unregistered type library '%s'\n",
+ library);
+ ctxt->nbErrors++;
+ def->data = NULL;
+ } else {
+ def->data = lib;
+ if (lib->have == NULL) {
+ ctxt->error(ctxt->userData,
+ "Internal error with type library '%s': no 'have'\n",
+ library);
+ ctxt->nbErrors++;
+ } else {
+ tmp = lib->have(lib->data, def->name);
+ if (tmp != 1) {
+ ctxt->error(ctxt->userData,
+ "Error type '%s' is not exported by type library '%s'\n",
+ def->name, library);
+ ctxt->nbErrors++;
+ }
+ }
+ }
+ content = node->children;
+ while (content != NULL) {
+ TODO
+ content = content->next;
+ }
+
+ return(def);
+}
+
/**
* xmlRelaxNGParseDefine:
@@ -887,6 +1229,8 @@
}
}
}
+ } else if (IS_RELAXNG(node, "data")) {
+ def = xmlRelaxNGParseData(ctxt, node);
} else if (IS_RELAXNG(node, "define")) {
xmlRelaxNGParseDefine(ctxt, node);
def = NULL;
@@ -2202,6 +2546,45 @@
}
/**
+ * xmlRelaxNGValidateDatatype:
+ * @ctxt: a Relax-NG validation context
+ * @value: the string value
+ * @type: the datatype definition
+ *
+ * Validate the given value against the dataype
+ *
+ * Returns 0 if the validation succeeded or an error code.
+ */
+static int
+xmlRelaxNGValidateDatatype(xmlRelaxNGValidCtxtPtr ctxt, const xmlChar *value,
+ xmlRelaxNGDefinePtr define) {
+ int ret;
+ xmlRelaxNGTypeLibraryPtr lib;
+
+ if ((define == NULL) || (define->data == NULL)) {
+ return(-1);
+ }
+ lib = (xmlRelaxNGTypeLibraryPtr) define->data;
+ if (lib->check != NULL)
+ ret = lib->check(lib->data, define->name, value);
+ else
+ ret = -1;
+ if (ret < 0) {
+ VALID_CTXT();
+ VALID_ERROR("Internal: failed to validate type %s\n", define->name);
+ return(-1);
+ } else if (ret == 1) {
+ ret = 0;
+ } else {
+ VALID_CTXT();
+ VALID_ERROR("Type %s doesn't allow value %s\n", define->name, value);
+ return(-1);
+ ret = -1;
+ }
+ return(ret);
+}
+
+/**
* xmlRelaxNGValidateValue:
* @ctxt: a Relax-NG validation context
* @define: the definition to verify
@@ -2590,7 +2973,32 @@
case XML_RELAXNG_DEF:
ret = xmlRelaxNGValidateDefinition(ctxt, define->content);
break;
- case XML_RELAXNG_DATATYPE:
+ case XML_RELAXNG_DATATYPE: {
+ xmlChar *content;
+
+ content = xmlNodeGetContent(node);
+ ret = xmlRelaxNGValidateDatatype(ctxt, content, define);
+ if (ret == -1) {
+ VALID_CTXT();
+ VALID_ERROR("internal error validating %s\n", define->name);
+ } else if (ret == 0) {
+ ctxt->state->seq = node->next;
+ }
+ /*
+ * TODO cover the problems with
+ * <p>12<!-- comment -->34</p>
+ * TODO detect full element coverage at compilation time.
+ */
+ if ((node != NULL) && (node->next != NULL)) {
+ VALID_CTXT();
+ VALID_ERROR("The data does not cover the full element %s\n",
+ node->parent->name);
+ ret = -1;
+ }
+ if (content != NULL)
+ xmlFree(content);
+ break;
+ }
case XML_RELAXNG_VALUE:
TODO
break;
diff --git a/result/relaxng/tutor3_2_1.err b/result/relaxng/tutor3_2_1.err
index 6bf43e7..8e23334 100644
--- a/result/relaxng/tutor3_2_1.err
+++ b/result/relaxng/tutor3_2_1.err
@@ -1,3 +1,3 @@
-error detected at relaxng.c:2429
-error detected at relaxng.c:2477
+error detected at relaxng.c:2812
+error detected at relaxng.c:2860
xmlRelaxNGValidateDefinition(): validated card : -1
diff --git a/result/relaxng/tutor3_5_2.err b/result/relaxng/tutor3_5_2.err
index cfe23fe..909ad8b 100644
--- a/result/relaxng/tutor3_5_2.err
+++ b/result/relaxng/tutor3_5_2.err
@@ -1,5 +1,5 @@
xmlRelaxNGValidateAttribute(name): -1
xmlRelaxNGValidateDefinition(): validated email : 0
xmlRelaxNGValidateDefinition(): validated card : -1
-error detected at relaxng.c:2477
+error detected at relaxng.c:2860
xmlRelaxNGValidateDefinition(): validated addressBook : -1
diff --git a/result/relaxng/tutor5_1_1 b/result/relaxng/tutor5_1_1
new file mode 100644
index 0000000..e6c2842
--- /dev/null
+++ b/result/relaxng/tutor5_1_1
@@ -0,0 +1 @@
+./test/relaxng/tutor5_1_1.xml validates
diff --git a/result/relaxng/tutor5_1_1.err b/result/relaxng/tutor5_1_1.err
new file mode 100644
index 0000000..d987a68
--- /dev/null
+++ b/result/relaxng/tutor5_1_1.err
@@ -0,0 +1,3 @@
+Unimplemented block at relaxng.c:667
+Unimplemented block at relaxng.c:686
+xmlRelaxNGValidateDefinition(): validated number : 0
diff --git a/result/relaxng/tutor5_2_1 b/result/relaxng/tutor5_2_1
new file mode 100644
index 0000000..a64df3b
--- /dev/null
+++ b/result/relaxng/tutor5_2_1
@@ -0,0 +1 @@
+./test/relaxng/tutor5_2_1.xml validates
diff --git a/result/relaxng/tutor5_2_1.err b/result/relaxng/tutor5_2_1.err
new file mode 100644
index 0000000..24865cc
--- /dev/null
+++ b/result/relaxng/tutor5_2_1.err
@@ -0,0 +1,7 @@
+Unimplemented block at relaxng.c:667
+Unimplemented block at relaxng.c:667
+Unimplemented block at relaxng.c:686
+xmlRelaxNGValidateDefinition(): validated x : 0
+Unimplemented block at relaxng.c:686
+xmlRelaxNGValidateDefinition(): validated y : 0
+xmlRelaxNGValidateDefinition(): validated point : 0
diff --git a/result/relaxng/tutor5_3_1 b/result/relaxng/tutor5_3_1
new file mode 100644
index 0000000..05d0d9c
--- /dev/null
+++ b/result/relaxng/tutor5_3_1
@@ -0,0 +1,2 @@
+The data does not cover the full element bad
+./test/relaxng/tutor5_3_1.xml validation generated an internal error
diff --git a/result/relaxng/tutor5_3_1.err b/result/relaxng/tutor5_3_1.err
new file mode 100644
index 0000000..0ea4f9a
--- /dev/null
+++ b/result/relaxng/tutor5_3_1.err
@@ -0,0 +1,3 @@
+error detected at relaxng.c:2993
+xmlRelaxNGValidateDefinition(): validated note : 0
+xmlRelaxNGValidateDefinition(): validated bad : -1
diff --git a/result/relaxng/tutor5_4_1 b/result/relaxng/tutor5_4_1
new file mode 100644
index 0000000..13ac9bc
--- /dev/null
+++ b/result/relaxng/tutor5_4_1
@@ -0,0 +1 @@
+./test/relaxng/tutor5_4_1.xml validates
diff --git a/result/relaxng/tutor5_4_1.err b/result/relaxng/tutor5_4_1.err
new file mode 100644
index 0000000..c4df2aa
--- /dev/null
+++ b/result/relaxng/tutor5_4_1.err
@@ -0,0 +1,2 @@
+xmlRelaxNGValidateAttribute(note): 0
+xmlRelaxNGValidateDefinition(): validated ok : 0
diff --git a/test/relaxng/tutor5_1.rng b/test/relaxng/tutor5_1.rng
new file mode 100644
index 0000000..bf53247
--- /dev/null
+++ b/test/relaxng/tutor5_1.rng
@@ -0,0 +1,3 @@
+<element name="number" xmlns="http://relaxng.org/ns/structure/1.0">
+ <data type="integer" datatypeLibrary="http://www.w3.org/2001/XMLSchema-datatypes"/>
+</element>
diff --git a/test/relaxng/tutor5_1_1.xml b/test/relaxng/tutor5_1_1.xml
new file mode 100644
index 0000000..aa01853
--- /dev/null
+++ b/test/relaxng/tutor5_1_1.xml
@@ -0,0 +1 @@
+<number>5</number>
diff --git a/test/relaxng/tutor5_2.rng b/test/relaxng/tutor5_2.rng
new file mode 100644
index 0000000..9d749dc
--- /dev/null
+++ b/test/relaxng/tutor5_2.rng
@@ -0,0 +1,9 @@
+<element name="point" xmlns="http://relaxng.org/ns/structure/1.0"
+ datatypeLibrary="http://www.w3.org/2001/XMLSchema-datatypes">
+ <element name="x">
+ <data type="double"/>
+ </element>
+ <element name="y">
+ <data type="double"/>
+ </element>
+</element>
diff --git a/test/relaxng/tutor5_2_1.xml b/test/relaxng/tutor5_2_1.xml
new file mode 100644
index 0000000..75c387d
--- /dev/null
+++ b/test/relaxng/tutor5_2_1.xml
@@ -0,0 +1 @@
+<point><x>1</x><y>5.20</y></point>
diff --git a/test/relaxng/tutor5_3.rng b/test/relaxng/tutor5_3.rng
new file mode 100644
index 0000000..e49f6ec
--- /dev/null
+++ b/test/relaxng/tutor5_3.rng
@@ -0,0 +1,6 @@
+<element name="bad" xmlns="http://relaxng.org/ns/structure/1.0">
+ <data type="string"/>
+ <element name="note">
+ <text/>
+ </element>
+</element>
diff --git a/test/relaxng/tutor5_3_1.xml b/test/relaxng/tutor5_3_1.xml
new file mode 100644
index 0000000..bd73098
--- /dev/null
+++ b/test/relaxng/tutor5_3_1.xml
@@ -0,0 +1 @@
+<bad>5<note>fails</note></bad>
diff --git a/test/relaxng/tutor5_4.rng b/test/relaxng/tutor5_4.rng
new file mode 100644
index 0000000..e6aae94
--- /dev/null
+++ b/test/relaxng/tutor5_4.rng
@@ -0,0 +1,6 @@
+<element name="ok" xmlns="http://relaxng.org/ns/structure/1.0">
+ <data type="string"/>
+ <attribute name="note">
+ <text/>
+ </attribute>
+</element>
diff --git a/test/relaxng/tutor5_4_1.xml b/test/relaxng/tutor5_4_1.xml
new file mode 100644
index 0000000..c9cdef4
--- /dev/null
+++ b/test/relaxng/tutor5_4_1.xml
@@ -0,0 +1 @@
+<ok note="foo">5</ok>
diff --git a/test/relaxng/tutor5_5.rng b/test/relaxng/tutor5_5.rng
new file mode 100644
index 0000000..b620ab8
--- /dev/null
+++ b/test/relaxng/tutor5_5.rng
@@ -0,0 +1,5 @@
+<element name="email" xmlns="http://relaxng.org/ns/structure/1.0">
+ <data type="string">
+ <param name="maxLength">127</param>
+ </data>
+</element>
diff --git a/test/relaxng/tutor6_1.rng b/test/relaxng/tutor6_1.rng
new file mode 100644
index 0000000..7a06092
--- /dev/null
+++ b/test/relaxng/tutor6_1.rng
@@ -0,0 +1,10 @@
+<element name="card" xmlns="http://relaxng.org/ns/structure/1.0">
+ <attribute name="name"/>
+ <attribute name="email"/>
+ <attribute name="preferredFormat">
+ <choice>
+ <value>html</value>
+ <value>text</value>
+ </choice>
+ </attribute>
+</element>
diff --git a/test/relaxng/tutor6_2.rng b/test/relaxng/tutor6_2.rng
new file mode 100644
index 0000000..1237fa7
--- /dev/null
+++ b/test/relaxng/tutor6_2.rng
@@ -0,0 +1,14 @@
+<element name="card" xmlns="http://relaxng.org/ns/structure/1.0">
+ <element name="name">
+ <text/>
+ </element>
+ <element name="email">
+ <text/>
+ </element>
+ <element name="preferredFormat">
+ <choice>
+ <value>html</value>
+ <value>text</value>
+ </choice>
+ </element>
+</element>
diff --git a/test/relaxng/tutor6_3.rng b/test/relaxng/tutor6_3.rng
new file mode 100644
index 0000000..0683d0b
--- /dev/null
+++ b/test/relaxng/tutor6_3.rng
@@ -0,0 +1,10 @@
+<element name="card" xmlns="http://relaxng.org/ns/structure/1.0">
+ <attribute name="name"/>
+ <attribute name="email"/>
+ <attribute name="preferredFormat">
+ <choice>
+ <value type="string">html</value>
+ <value type="string">text</value>
+ </choice>
+ </attribute>
+</element>