6f125558390bceaea751437097bb0ffd1cd9b8e5
[idzebra-moved-to-github.git] / data1 / d1_write.c
1 /* $Id: d1_write.c,v 1.5 2004-10-20 10:36:40 adam Exp $
2    Copyright (C) 1995,1996,1997,1998,1999,2000,2001,2002
3    Index Data Aps
4
5 This file is part of the Zebra server.
6
7 Zebra is free software; you can redistribute it and/or modify it under
8 the terms of the GNU General Public License as published by the Free
9 Software Foundation; either version 2, or (at your option) any later
10 version.
11
12 Zebra is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15 for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with Zebra; see the file LICENSE.zebra.  If not, write to the
19 Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
20 02111-1307, USA.
21 */
22
23 /* converts data1 tree to XML record */
24
25 #include <string.h>
26
27 #include <idzebra/data1.h>
28 #include <yaz/wrbuf.h>
29
30 #define IDSGML_MARGIN 75
31
32 #define PRETTY_FORMAT 0
33
34 static int wordlen(char *b, int max)
35 {
36     int l = 0;
37
38     while (l < max && !d1_isspace(*b))
39         l++, b++;
40     return l;
41 }
42
43 static void indent (WRBUF b, int col)
44 {
45     int i;
46     for (i = 0; i<col; i++)
47         wrbuf_putc (b, ' ');
48 }
49
50 static void wrbuf_put_xattr(WRBUF b, data1_xattr *p)
51 {
52     for (; p; p = p->next)
53     {
54         wrbuf_putc (b, ' ');
55         if (p->what == DATA1I_xmltext)
56             wrbuf_puts (b, p->name);
57         else
58             wrbuf_xmlputs (b, p->name);
59         if (p->value)
60         {
61             wrbuf_putc (b, '=');
62             wrbuf_putc (b, '"');
63             if (p->what == DATA1I_text)
64                 wrbuf_xmlputs (b, p->value);
65             else
66                 wrbuf_puts (b, p->value);
67             wrbuf_putc (b, '"');
68         }
69     }
70 }
71
72 static int nodetoidsgml(data1_node *n, int select, WRBUF b, int col,
73                         int pretty_format)
74 {
75     data1_node *c;
76
77     for (c = n->child; c; c = c->next)
78     {
79         char *tag;
80
81         if (c->which == DATA1N_preprocess)
82         {
83             if (pretty_format)
84                 indent (b, col);
85             wrbuf_puts (b, "<?");
86             wrbuf_xmlputs (b, c->u.preprocess.target);
87             wrbuf_put_xattr (b, c->u.preprocess.attributes);
88             if (c->child)
89                 wrbuf_puts(b, " ");
90             if (nodetoidsgml(c, select, b, (col > 40) ? 40 : col+2,
91                              pretty_format) < 0)
92                 return -1;
93             wrbuf_puts (b, "?>\n");
94         }
95         else if (c->which == DATA1N_tag)
96         {
97             if (select && !c->u.tag.node_selected)
98                 continue;
99             tag = c->u.tag.tag;
100             if (!data1_matchstr(tag, "wellknown")) /* skip wellknown */
101             {
102                 if (nodetoidsgml(c, select, b, col, pretty_format) < 0)
103                     return -1;
104             }
105             else
106             {
107                 if (pretty_format)
108                     indent (b, col);
109                 wrbuf_puts (b, "<");    
110                 wrbuf_xmlputs (b, tag);
111                 wrbuf_put_xattr (b, c->u.tag.attributes);
112                 wrbuf_puts(b, ">");
113                 if (pretty_format)
114                     wrbuf_puts(b, "\n");
115                 if (nodetoidsgml(c, select, b, (col > 40) ? 40 : col+2,
116                                  pretty_format) < 0)
117                     return -1;
118                 if (pretty_format)
119                     indent (b, col);
120                 wrbuf_puts(b, "</");
121                 wrbuf_xmlputs(b, tag);
122                 wrbuf_puts(b, ">");
123                 if (pretty_format)
124                     wrbuf_puts (b, "\n");
125             }
126         }
127         else if (c->which == DATA1N_data || c->which == DATA1N_comment)
128         {
129             char *p = c->u.data.data;
130             int l = c->u.data.len;
131             int first = 1;
132             int lcol = col;
133
134             if (pretty_format && !c->u.data.formatted_text)
135                 indent (b, col);
136             if (c->which == DATA1N_comment)
137                 wrbuf_puts (b, "<!--");
138             switch (c->u.data.what)
139             {
140             case DATA1I_xmltext:
141                 wrbuf_write(b, c->u.data.data, c->u.data.len);
142                 break;
143             case DATA1I_text:
144                 if (!pretty_format || c->u.data.formatted_text)
145                 {
146                     wrbuf_xmlputs_n (b, p, l);
147                 }
148                 else
149                 {
150                     while (l)
151                     {
152                         int wlen;
153                         
154                         while (l && d1_isspace(*p))
155                             p++, l--;
156                         if (!l)
157                             break;
158                         /* break if we cross margin and word is not too long */
159                         if (lcol + (wlen = wordlen(p, l)) > IDSGML_MARGIN &&
160                             wlen < IDSGML_MARGIN)
161                         {
162                             wrbuf_puts (b, "\n");
163                             indent (b, col);
164                             lcol = col;
165                             first = 1;
166                         }
167                         if (!first)
168                         {
169                             wrbuf_putc(b, ' ');
170                             lcol++;
171                         }
172                         while (l && !d1_isspace(*p))
173                         {
174                             wrbuf_putc(b, *p);
175                             p++;
176                             l--;
177                             lcol++;
178                         }
179                         first = 0;
180                     }
181                     wrbuf_puts(b, "\n");
182                 }
183                 break;
184             case DATA1I_num:
185                 wrbuf_xmlputs_n(b, c->u.data.data, c->u.data.len);
186                 if (pretty_format)
187                     wrbuf_puts(b, "\n");
188                 break;
189             case DATA1I_oid:
190                 wrbuf_xmlputs_n(b, c->u.data.data, c->u.data.len);
191                 if (pretty_format)
192                     wrbuf_puts(b, "\n");
193             }
194             if (c->which == DATA1N_comment)
195             {
196                 wrbuf_puts(b, "-->");
197                 if (pretty_format)
198                     wrbuf_puts(b, "\n");
199             }
200         }
201     }
202     return 0;
203 }
204
205 char *data1_nodetoidsgml (data1_handle dh, data1_node *n, int select, int *len)
206 {
207     WRBUF b = data1_get_wrbuf (dh);
208     
209     wrbuf_rewind(b);
210     
211     if (!data1_is_xmlmode (dh))
212     {
213         wrbuf_puts (b, "<");
214         wrbuf_puts (b, n->u.root.type);
215         wrbuf_puts (b, ">\n");
216     }
217     if (nodetoidsgml(n, select, b, 0, 0 /* no pretty format */))
218         return 0;
219     if (!data1_is_xmlmode (dh))
220     {
221         wrbuf_puts (b, "</");
222         wrbuf_puts (b, n->u.root.type);
223         wrbuf_puts (b, ">\n");
224     }
225     *len = wrbuf_len(b);
226     return wrbuf_buf(b);
227 }