]> mj.ucw.cz Git - libucw.git/blobdiff - sherlock/xml/parse.c
XML: A primitive DTD validation of elements... it is slow and does not
[libucw.git] / sherlock / xml / parse.c
index 67ef107659d357029517fb6456c05fc45451aeee..6f5b192f0ab29e021f4e8e219e6bf6c5d9544cbb 100644 (file)
@@ -654,6 +654,18 @@ xml_attr_find(struct xml_context *ctx, struct xml_node *node, char *name)
   return xml_attrs_find(ctx->tab_attrs, node, name);
 }
 
   return xml_attrs_find(ctx->tab_attrs, node, name);
 }
 
+char *
+xml_attr_value(struct xml_context *ctx, struct xml_node *node, char *name)
+{
+  struct xml_attr *attr = xml_attrs_find(ctx->tab_attrs, node, name);
+  if (attr)
+    return attr->val;
+  if (!node->dtd)
+    return NULL;
+  struct xml_dtd_attr *dtd = xml_dtd_find_attr(ctx, node->dtd, name);
+  return dtd ? dtd->default_value : NULL;
+}
+
 void
 xml_attrs_table_init(struct xml_context *ctx)
 {
 void
 xml_attrs_table_init(struct xml_context *ctx)
 {
@@ -668,6 +680,18 @@ xml_attrs_table_cleanup(struct xml_context *ctx)
 
 /*** Elements ***/
 
 
 /*** Elements ***/
 
+static uns
+xml_validate_element(struct xml_dtd_elem_node *root, struct xml_dtd_elem *elem)
+{
+  if (root->elem)
+    return elem == root->elem;
+  else
+    SLIST_FOR_EACH(struct xml_dtd_elem_node *, son, root->sons)
+      if (xml_validate_element(son, elem))
+       return 1;
+  return 0;
+}
+
 static void
 xml_push_element(struct xml_context *ctx)
 {
 static void
 xml_push_element(struct xml_context *ctx)
 {
@@ -693,12 +717,20 @@ xml_push_element(struct xml_context *ctx)
     xml_error(ctx, "Undefined element <%s>", e->name);
   else
     {
     xml_error(ctx, "Undefined element <%s>", e->name);
   else
     {
-      if (e->dtd->type == XML_DTD_ELEM_MIXED)
+      struct xml_dtd_elem *dtd = e->dtd, *parent_dtd = e->parent ? e->parent->dtd : NULL;
+      if (dtd->type == XML_DTD_ELEM_MIXED)
         ctx->flags &= ~XML_NO_CHARS;
       else
        ctx->flags |= XML_NO_CHARS;
         ctx->flags &= ~XML_NO_CHARS;
       else
        ctx->flags |= XML_NO_CHARS;
-
-      // FIXME: validate regular expressions
+      if (parent_dtd)
+        if (parent_dtd->type == XML_DTD_ELEM_EMPTY)
+         xml_error(ctx, "Empty element must not contain children");
+        else if (parent_dtd->type != XML_DTD_ELEM_ANY)
+         {
+           // FIXME: validate regular expressions
+           if (!xml_validate_element(parent_dtd->node, dtd))
+             xml_error(ctx, "Unexpected element <%s>", e->name);
+         }
     }
   while (1)
     {
     }
   while (1)
     {
@@ -1137,6 +1169,28 @@ epilog:
   ASSERT(0);
 }
 
   ASSERT(0);
 }
 
+uns
+xml_next_state(struct xml_context *ctx, uns pull)
+{
+  uns saved = ctx->pull;
+  ctx->pull = pull;
+  uns res = xml_next(ctx);
+  ctx->pull = saved;
+  return res;
+}
+
+uns
+xml_skip_element(struct xml_context *ctx)
+{
+  ASSERT(ctx->state == XML_STATE_STAG);
+  struct xml_node *node = ctx->node;
+  uns saved = ctx->pull, res;
+  ctx->pull = XML_PULL_ETAG;
+  while ((res = xml_next(ctx)) && ctx->node != node);
+  ctx->pull = saved;
+  return res;
+}
+
 uns
 xml_parse(struct xml_context *ctx)
 {
 uns
 xml_parse(struct xml_context *ctx)
 {