Version 5.13.0
[yaz-moved-to-github.git] / src / xml_get.c
1 /* This file is part of the YAZ toolkit.
2  * Copyright (C) Index Data
3  * See the file LICENSE for details.
4  */
5 /**
6  * \file xml_get.c
7  * \brief XML node getter/creation utilities
8  */
9 #if HAVE_CONFIG_H
10 #include <config.h>
11 #endif
12
13 #include <string.h>
14 #include <stdarg.h>
15 #include <yaz/xmalloc.h>
16 #include <yaz/xml_get.h>
17 #if YAZ_HAVE_XML2
18
19 const char *yaz_xml_get_prop(const xmlNode *n, const char *fmt, ...)
20 {
21     int no = 0;
22     va_list ap;
23     const char *cp;
24     struct _xmlAttr *attr;
25
26     va_start(ap, fmt);
27     for (cp = fmt; *cp; cp++)
28         if (*cp == '%')
29             no++;
30     if (no > 0)
31     {
32         const char ***ar = xmalloc(sizeof(*ar) * no);
33         int i;
34         for (i = 0; i < no; i++)
35         {
36             const char **s = va_arg(ap, const char **);
37             ar[i] = s;
38         }
39         for (attr = n->properties; attr; attr = attr->next)
40         {
41             const char *cp1 = fmt;
42             for (i = 0; *cp1; i++)
43             {
44                 const char *cp2 = cp1;
45                 size_t l;
46                 while (*cp2 != '\0' && *cp2 != '%')
47                     cp2++;
48                 if (*cp2 != '\0')
49                 { /* no % following, break out (bad fmt really) */
50                     cp1 = cp2;
51                     break;
52                 }
53                 l = cp2 - cp1;
54                 if (l > 0 && strlen((const char *) attr->name) == l &&
55                     !memcmp((const char *) attr->name, cp1, l))
56                     break;
57                 cp1 = 1 + cp2;
58                 if (*cp1)
59                     cp1++; /* skip char following % */
60             }
61             if (!*cp1)
62             {
63                 /* attribute not listed in fmt: return first unknown one */
64                 xfree(ar);
65                 return (const char *) attr->name;
66             }
67             *ar[i] = (const char *) attr->children->content;
68         }
69         xfree(ar);
70     }
71     else
72     {
73         for (attr = n->properties; attr; attr = attr->next)
74         {
75             if (!strcmp((const char *) attr->name, fmt))
76                 return (const char *) attr->children->content;
77         }
78     }
79     va_end(ap);
80     return 0; /* failure for simple mode; successful for %mode */
81 }
82
83 #endif
84
85 /*
86  * Local variables:
87  * c-basic-offset: 4
88  * c-file-style: "Stroustrup"
89  * indent-tabs-mode: nil
90  * End:
91  * vim: shiftwidth=4 tabstop=8 expandtab
92  */
93