Keep white space for XML (do not pretty print)
[yaz-moved-to-github.git] / retrieval / d1_expat.c
1 /*
2  * Copyright (c) 2002, Index Data.
3  * See the file LICENSE for details.
4  *
5  * $Id: d1_expat.c,v 1.4 2002-07-05 12:42:52 adam Exp $
6  */
7
8 #if HAVE_EXPAT_H
9
10 #include <assert.h>
11 #include <stdio.h>
12 #include <stdlib.h>
13
14 #include <yaz/xmalloc.h>
15 #include <yaz/log.h>
16 #include <yaz/data1.h>
17
18 #include <expat.h>
19
20 struct user_info {
21     data1_node *d1_stack[256];
22     int level;
23     data1_handle dh;
24     NMEM nmem;
25 };
26
27 static void cb_start (void *user, const char *el, const char **attr)
28 {
29     struct user_info *ui = (struct user_info*) user;
30     if (ui->level == 1)
31         data1_set_root (ui->dh, ui->d1_stack[0], ui->nmem, el);
32     ui->d1_stack[ui->level] = data1_mk_tag (ui->dh, ui->nmem, el, attr,
33                                                 ui->d1_stack[ui->level-1]);
34     ui->level++;
35     yaz_log (LOG_DEBUG, "cb_start %s", el);
36 }
37
38 static void cb_end (void *user, const char *el)
39 {
40     struct user_info *ui = (struct user_info*) user;
41
42     ui->level--;
43     yaz_log (LOG_DEBUG, "cb_end %s", el);
44 }
45
46 static void cb_chardata (void *user, const char *s, int len)
47 {
48     struct user_info *ui = (struct user_info*) user;
49 #if 1
50     yaz_log (LOG_DEBUG, "cb_chardata %.*s", len, s);
51     ui->d1_stack[ui->level] = data1_mk_text_n (ui->dh, ui->nmem, s, len,
52                                                    ui->d1_stack[ui->level -1]);
53 #else
54     int i;
55
56     for (i = 0; i<len; i++)
57         if (!strchr ("\n\n ", s[i]))
58             break;
59     if (i != len)
60     {
61         ui->d1_stack[ui->level] = data1_mk_text_n (ui->dh, ui->nmem, s, len,
62                                                    ui->d1_stack[ui->level -1]);
63     }
64 #endif
65 }
66
67 static void cb_decl (void *user, const char *version, const char*encoding,
68                      int standalone)
69 {
70     struct user_info *ui = (struct user_info*) user;
71     const char *attr_list[7];
72
73     attr_list[0] = "version";
74     attr_list[1] = version;
75
76     attr_list[2] = "encoding";
77     attr_list[3] = encoding;
78
79     attr_list[4] = "standalone";
80     attr_list[5] = standalone  ? "yes" : "no";
81
82     attr_list[6] = 0;
83     
84     data1_mk_preprocess (ui->dh, ui->nmem, "xml", attr_list,
85                              ui->d1_stack[ui->level-1]);
86     yaz_log (LOG_DEBUG, "decl version=%s encoding=%s",
87              version ? version : "null",
88              encoding ? encoding : "null");
89 }
90     
91 static void cb_processing (void *user, const char *target,
92                            const char *data)
93 {
94     struct user_info *ui = (struct user_info*) user;
95     data1_node *res =
96         data1_mk_preprocess (ui->dh, ui->nmem, target, 0,
97                              ui->d1_stack[ui->level-1]);
98     data1_mk_text_nf (ui->dh, ui->nmem, data, strlen(data), res);
99     
100     yaz_log (LOG_DEBUG, "decl processing target=%s data=%s",
101              target ? target : "null",
102              data ? data : "null");
103     
104     
105 }
106
107 static void cb_comment (void *user, const char *data)
108 {
109     struct user_info *ui = (struct user_info*) user;
110     yaz_log (LOG_DEBUG, "decl comment data=%s", data ? data : "null");
111     data1_mk_comment (ui->dh, ui->nmem, data, ui->d1_stack[ui->level-1]);
112 }
113
114 static void cb_doctype_start (void *userData, const char *doctypeName,
115                               const char *sysid, const char *pubid,
116                               int has_internal_subset)
117 {
118     yaz_log (LOG_DEBUG, "doctype start doctype=%s sysid=%s pubid=%s",
119              doctypeName, sysid, pubid);
120 }
121
122 static void cb_doctype_end (void *userData)
123 {
124     yaz_log (LOG_DEBUG, "doctype end");
125 }
126
127
128 static void cb_entity_decl (void *userData, const char *entityName,
129                             int is_parameter_entity,
130                             const char *value, int value_length,
131                             const char *base, const char *systemId,
132                             const char *publicId, const char *notationName)
133 {
134     yaz_log (LOG_DEBUG,
135              "entity %s is_para_entry=%d value=%.*s base=%s systemId=%s"
136              " publicId=%s notationName=%s",
137              entityName, is_parameter_entity, value_length, value,
138              base, systemId, publicId, notationName);
139     
140 }
141
142 #define XML_CHUNK 1024
143
144 data1_node *data1_read_xml (data1_handle dh,
145                             int (*rf)(void *, char *, size_t), void *fh,
146                             NMEM m)
147 {
148     XML_Parser parser;
149     struct user_info uinfo;
150     int done = 0;
151
152     uinfo.level = 1;
153     uinfo.dh = dh;
154     uinfo.nmem = m;
155     uinfo.d1_stack[0] = data1_mk_node2 (dh, m, DATA1N_root, 0);
156     uinfo.d1_stack[1] = 0; /* indicate no children (see end of routine) */
157     
158     parser = XML_ParserCreate (0 /* encoding */);
159     
160     XML_SetElementHandler (parser, cb_start, cb_end);
161     XML_SetCharacterDataHandler (parser, cb_chardata);
162     XML_SetXmlDeclHandler (parser, cb_decl);
163     XML_SetProcessingInstructionHandler (parser, cb_processing);
164     XML_SetUserData (parser, &uinfo);
165     XML_SetCommentHandler (parser, cb_comment);
166     XML_SetDoctypeDeclHandler (parser, cb_doctype_start, cb_doctype_end);
167     XML_SetEntityDeclHandler (parser, cb_entity_decl);
168
169     while (!done)
170     {
171         int r;
172         void *buf = XML_GetBuffer (parser, XML_CHUNK);
173         if (!buf)
174         {
175             /* error */
176             return 0;
177         }
178         r = (*rf)(fh, buf, XML_CHUNK);
179         if (r < 0)
180         {
181             /* error */
182             return 0;
183         }
184         else if (r == 0)
185             done = 1;
186         XML_ParseBuffer (parser, r, done);
187     }
188     XML_ParserFree (parser);
189     if (!uinfo.d1_stack[1])
190         return 0;
191     return uinfo.d1_stack[0];
192 }
193
194 #endif