+data1_node *data1_mk_root (data1_handle dh, NMEM nmem, const char *name)
+{
+ data1_absyn *absyn = data1_get_absyn (dh, name);
+ data1_node *res;
+ if (!absyn)
+ {
+ yaz_log(LOG_WARN, "Unable to acquire abstract syntax " "for '%s'",
+ name);
+ /* It's now OK for a record not to have an absyn */
+ }
+ res = data1_mk_node2 (dh, nmem, DATA1N_root, 0);
+ res->u.root.type = data1_insert_string (dh, res, nmem, name);
+ res->u.root.absyn = absyn;
+ return res;
+}
+
+void data1_set_root(data1_handle dh, data1_node *res,
+ NMEM nmem, const char *name)
+{
+ data1_absyn *absyn = data1_get_absyn (dh, name);
+
+ res->u.root.type = data1_insert_string (dh, res, nmem, name);
+ res->u.root.absyn = absyn;
+}
+
+data1_node *data1_mk_preprocess (data1_handle dh, NMEM nmem,
+ const char *target, const char **attr,
+ data1_node *at)
+{
+ data1_xattr **p;
+ data1_node *res = data1_mk_node2 (dh, nmem, DATA1N_preprocess, at);
+ res->u.preprocess.target = data1_insert_string (dh, res, nmem, target);
+
+ p = &res->u.preprocess.attributes;
+ while (attr && *attr)
+ {
+ *p = (data1_xattr*) nmem_malloc (nmem, sizeof(**p));
+ (*p)->name = nmem_strdup (nmem, *attr++);
+ (*p)->value = nmem_strdup (nmem, *attr++);
+ p = &(*p)->next;
+ }
+ *p = 0;
+ return res;
+}
+
+data1_node *data1_mk_tag_n (data1_handle dh, NMEM nmem,
+ const char *tag, size_t len, const char **attr,
+ data1_node *at)
+{
+ data1_node *partag = get_parent_tag(dh, at);
+ data1_node *res = data1_mk_node2 (dh, nmem, DATA1N_tag, at);
+ data1_xattr **p;
+ data1_element *e = 0;
+
+ res->u.tag.tag = data1_insert_string_n (dh, res, nmem, tag, len);
+
+ if (!partag) /* top tag? */
+ e = data1_getelementbytagname (dh, at->root->u.root.absyn,
+ 0 /* index as local */,
+ res->u.tag.tag);
+ else
+ {
+ /* only set element for known tags */
+ e = partag->u.tag.element;
+ if (e)
+ e = data1_getelementbytagname (dh, at->root->u.root.absyn,
+ e, res->u.tag.tag);
+ }
+ res->u.tag.element = e;
+ p = &res->u.tag.attributes;
+ while (attr && *attr)
+ {
+ *p = (data1_xattr*) nmem_malloc (nmem, sizeof(**p));
+ (*p)->name = nmem_strdup (nmem, *attr++);
+ (*p)->value = nmem_strdup (nmem, *attr++);
+ p = &(*p)->next;
+ }
+ *p = 0;
+ return res;
+}
+
+void data1_tag_add_attr (data1_handle dh, NMEM nmem,
+ data1_node *res, const char **attr)
+{
+ data1_xattr **p;
+
+ if (res->which != DATA1N_tag)
+ return;
+
+ p = &res->u.tag.attributes;
+ while (*p)
+ p = &(*p)->next;
+
+ while (attr && *attr)
+ {
+ *p = (data1_xattr*) nmem_malloc (nmem, sizeof(**p));
+ (*p)->name = nmem_strdup (nmem, *attr++);
+ (*p)->value = nmem_strdup (nmem, *attr++);
+ p = &(*p)->next;
+ }
+ *p = 0;
+}
+
+data1_node *data1_mk_tag (data1_handle dh, NMEM nmem,
+ const char *tag, const char **attr, data1_node *at)
+{
+ return data1_mk_tag_n (dh, nmem, tag, strlen(tag), attr, at);
+}
+
+data1_node *data1_search_tag (data1_handle dh, data1_node *n,
+ const char *tag)
+{
+ if (*tag == '/')
+ {
+ n = data1_get_root_tag (dh, n);
+ if (n)
+ n = n->child;
+ tag++;
+ }
+ for (; n; n = n->next)
+ if (n->which == DATA1N_tag && n->u.tag.tag &&
+ !yaz_matchstr (tag, n->u.tag.tag))
+ {
+ return n;
+ }
+ return 0;
+}
+
+data1_node *data1_mk_tag_uni (data1_handle dh, NMEM nmem,
+ const char *tag, data1_node *at)
+{
+ data1_node *node = data1_search_tag (dh, at->child, tag);
+ if (!node)
+ node = data1_mk_tag (dh, nmem, tag, 0 /* attr */, at);
+ else
+ node->child = node->last_child = 0;
+ return node;
+}
+
+data1_node *data1_mk_text_n (data1_handle dh, NMEM mem,
+ const char *buf, size_t len, data1_node *parent)
+{
+ data1_node *res = data1_mk_node2 (dh, mem, DATA1N_data, parent);
+ res->u.data.what = DATA1I_text;
+ res->u.data.len = len;
+
+ res->u.data.data = data1_insert_string_n (dh, res, mem, buf, len);
+ return res;
+}
+
+data1_node *data1_mk_text_nf (data1_handle dh, NMEM mem,
+ const char *buf, size_t len, data1_node *parent)
+{
+ data1_node *res = data1_mk_text_n (dh, mem, buf, len, parent);
+ res->u.data.formatted_text = 1;
+ return res;
+}
+
+data1_node *data1_mk_text (data1_handle dh, NMEM mem,
+ const char *buf, data1_node *parent)
+{
+ return data1_mk_text_n (dh, mem, buf, strlen(buf), parent);
+}
+
+data1_node *data1_mk_comment_n (data1_handle dh, NMEM mem,
+ const char *buf, size_t len,
+ data1_node *parent)
+{
+ data1_node *res = data1_mk_node2 (dh, mem, DATA1N_comment, parent);
+ res->u.data.what = DATA1I_text;
+ res->u.data.len = len;
+
+ res->u.data.data = data1_insert_string_n (dh, res, mem, buf, len);
+ return res;
+}
+
+data1_node *data1_mk_comment (data1_handle dh, NMEM mem,
+ const char *buf, data1_node *parent)
+{
+ return data1_mk_comment_n (dh, mem, buf, strlen(buf), parent);
+}
+
+char *data1_insert_string_n (data1_handle dh, data1_node *res,
+ NMEM m, const char *str, size_t len)
+{
+ char *b;
+ if (len >= DATA1_LOCALDATA)
+ b = nmem_malloc (m, len+1);
+ else
+ b = res->lbuf;
+ memcpy (b, str, len);
+ b[len] = 0;
+ return b;
+}
+