[libxml2] Allow choice within choice in nameClass in RELAX NG



commit 46da8fc5290ed3243d0c137d712a1ed05c489f5f
Author: Nikolai Weibull <now disu se>
Date:   Fri Oct 12 23:46:24 2018 +0200

    Allow choice within choice in nameClass in RELAX NG
    
    The pattern nameClass allows for nested choice elements, for example
    
      <name>
        <choice>
          <choice>
            <name>a</name>
            <name>b</name>
          </choice>
          <name>c</name>
        </choice>
      </name>
    
    which is semantically equivalent to
    
      <name>
        <choice>
          <name>a</name>
          <name>b</name>
          <name>c</name>
        </choice>
      </name>
    
    The old code didn’t handle this correctly, as it never expected a choice inside
    another choice.  This patch fixes this by flattening any nested choices.
    
    This pattern of nested choice elements comes up in RELAX NG simplification,
    where all choice elements are rewritten in this nested manner, see section 4.12
    of the RELAX NG specification.

 relaxng.c                     | 16 ++++++++++------
 result/relaxng/anyName0_0     |  0
 result/relaxng/anyName0_0.err |  1 +
 result/relaxng/anyName0_err   |  1 +
 result/relaxng/anyName0_valid |  0
 test/relaxng/anyName0.rng     | 15 +++++++++++++++
 test/relaxng/anyName0_0.xml   |  1 +
 7 files changed, 28 insertions(+), 6 deletions(-)
---
diff --git a/relaxng.c b/relaxng.c
index a3088cbd..8725444b 100644
--- a/relaxng.c
+++ b/relaxng.c
@@ -5363,11 +5363,15 @@ xmlRelaxNGParseNameClass(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node,
         xmlNodePtr child;
         xmlRelaxNGDefinePtr last = NULL;
 
-        ret = xmlRelaxNGNewDefine(ctxt, node);
-        if (ret == NULL)
-            return (NULL);
-        ret->parent = def;
-        ret->type = XML_RELAXNG_CHOICE;
+        if (def->type == XML_RELAXNG_CHOICE) {
+            ret = def;
+        } else {
+            ret = xmlRelaxNGNewDefine(ctxt, node);
+            if (ret == NULL)
+                return (NULL);
+            ret->parent = def;
+            ret->type = XML_RELAXNG_CHOICE;
+        }
 
         if (node->children == NULL) {
             xmlRngPErr(ctxt, node, XML_RNGP_CHOICE_EMPTY,
@@ -5379,7 +5383,7 @@ xmlRelaxNGParseNameClass(xmlRelaxNGParserCtxtPtr ctxt, xmlNodePtr node,
                 tmp = xmlRelaxNGParseNameClass(ctxt, child, ret);
                 if (tmp != NULL) {
                     if (last == NULL) {
-                        last = ret->nameClass = tmp;
+                        last = tmp;
                     } else {
                         last->next = tmp;
                         last = tmp;
diff --git a/result/relaxng/anyName0_0 b/result/relaxng/anyName0_0
new file mode 100644
index 00000000..e69de29b
diff --git a/result/relaxng/anyName0_0.err b/result/relaxng/anyName0_0.err
new file mode 100644
index 00000000..f660c26d
--- /dev/null
+++ b/result/relaxng/anyName0_0.err
@@ -0,0 +1 @@
+./test/relaxng/anyName0_0.xml validates
diff --git a/result/relaxng/anyName0_err b/result/relaxng/anyName0_err
new file mode 100644
index 00000000..ab6f08da
--- /dev/null
+++ b/result/relaxng/anyName0_err
@@ -0,0 +1 @@
+./test/relaxng/anyName0.rng validates
diff --git a/result/relaxng/anyName0_valid b/result/relaxng/anyName0_valid
new file mode 100644
index 00000000..e69de29b
diff --git a/test/relaxng/anyName0.rng b/test/relaxng/anyName0.rng
new file mode 100644
index 00000000..9fc5ead0
--- /dev/null
+++ b/test/relaxng/anyName0.rng
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<grammar xmlns="http://relaxng.org/ns/structure/1.0";>
+  <start>
+    <element>
+      <choice>
+        <choice>
+          <name>a</name>
+          <name>b</name>
+        </choice>
+        <name>c</name>
+      </choice>
+      <empty/>
+    </element>
+  </start>
+</grammar>
diff --git a/test/relaxng/anyName0_0.xml b/test/relaxng/anyName0_0.xml
new file mode 100644
index 00000000..fb08e36d
--- /dev/null
+++ b/test/relaxng/anyName0_0.xml
@@ -0,0 +1 @@
+<b/>


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