1/**
2 * section: xmlWriter
3 * synopsis: use various APIs for the xmlWriter
4 * purpose: tests a number of APIs for the xmlWriter, especially
5 *          the various methods to write to a filename, to a memory
6 *          buffer, to a new document, or to a subtree. It shows how to
7 *          do encoding string conversions too. The resulting
8 *          documents are then serialized.
9 * usage: testWriter
10 * test: testWriter && for i in 1 2 3 4 ; do diff $(srcdir)/writer.xml writer$$i.tmp || break ; done
11 * author: Alfred Mickautsch
12 * copy: see Copyright for the status of this software.
13 */
14#include <stdio.h>
15#include <string.h>
16#include <libxml/encoding.h>
17#include <libxml/xmlwriter.h>
18
19#if defined(LIBXML_WRITER_ENABLED) && defined(LIBXML_OUTPUT_ENABLED)
20
21#define MY_ENCODING "ISO-8859-1"
22
23void testXmlwriterFilename(const char *uri);
24void testXmlwriterMemory(const char *file);
25void testXmlwriterDoc(const char *file);
26void testXmlwriterTree(const char *file);
27xmlChar *ConvertInput(const char *in, const char *encoding);
28
29int
30main(void)
31{
32    /*
33     * this initialize the library and check potential ABI mismatches
34     * between the version it was compiled for and the actual shared
35     * library used.
36     */
37    LIBXML_TEST_VERSION
38
39    /* first, the file version */
40    testXmlwriterFilename("writer1.tmp");
41
42    /* next, the memory version */
43    testXmlwriterMemory("writer2.tmp");
44
45    /* next, the DOM version */
46    testXmlwriterDoc("writer3.tmp");
47
48    /* next, the tree version */
49    testXmlwriterTree("writer4.tmp");
50
51    /*
52     * Cleanup function for the XML library.
53     */
54    xmlCleanupParser();
55    /*
56     * this is to debug memory for regression tests
57     */
58    xmlMemoryDump();
59    return 0;
60}
61
62/**
63 * testXmlwriterFilename:
64 * @uri: the output URI
65 *
66 * test the xmlWriter interface when writing to a new file
67 */
68void
69testXmlwriterFilename(const char *uri)
70{
71    int rc;
72    xmlTextWriterPtr writer;
73    xmlChar *tmp;
74
75    /* Create a new XmlWriter for uri, with no compression. */
76    writer = xmlNewTextWriterFilename(uri, 0);
77    if (writer == NULL) {
78        printf("testXmlwriterFilename: Error creating the xml writer\n");
79        return;
80    }
81
82    /* Start the document with the xml default for the version,
83     * encoding ISO 8859-1 and the default for the standalone
84     * declaration. */
85    rc = xmlTextWriterStartDocument(writer, NULL, MY_ENCODING, NULL);
86    if (rc < 0) {
87        printf
88            ("testXmlwriterFilename: Error at xmlTextWriterStartDocument\n");
89        return;
90    }
91
92    /* Start an element named "EXAMPLE". Since thist is the first
93     * element, this will be the root element of the document. */
94    rc = xmlTextWriterStartElement(writer, BAD_CAST "EXAMPLE");
95    if (rc < 0) {
96        printf
97            ("testXmlwriterFilename: Error at xmlTextWriterStartElement\n");
98        return;
99    }
100
101    /* Write a comment as child of EXAMPLE.
102     * Please observe, that the input to the xmlTextWriter functions
103     * HAS to be in UTF-8, even if the output XML is encoded
104     * in iso-8859-1 */
105    tmp = ConvertInput("This is a comment with special chars: <���>",
106                       MY_ENCODING);
107    rc = xmlTextWriterWriteComment(writer, tmp);
108    if (rc < 0) {
109        printf
110            ("testXmlwriterFilename: Error at xmlTextWriterWriteComment\n");
111        return;
112    }
113    if (tmp != NULL) xmlFree(tmp);
114
115    /* Start an element named "ORDER" as child of EXAMPLE. */
116    rc = xmlTextWriterStartElement(writer, BAD_CAST "ORDER");
117    if (rc < 0) {
118        printf
119            ("testXmlwriterFilename: Error at xmlTextWriterStartElement\n");
120        return;
121    }
122
123    /* Add an attribute with name "version" and value "1.0" to ORDER. */
124    rc = xmlTextWriterWriteAttribute(writer, BAD_CAST "version",
125                                     BAD_CAST "1.0");
126    if (rc < 0) {
127        printf
128            ("testXmlwriterFilename: Error at xmlTextWriterWriteAttribute\n");
129        return;
130    }
131
132    /* Add an attribute with name "xml:lang" and value "de" to ORDER. */
133    rc = xmlTextWriterWriteAttribute(writer, BAD_CAST "xml:lang",
134                                     BAD_CAST "de");
135    if (rc < 0) {
136        printf
137            ("testXmlwriterFilename: Error at xmlTextWriterWriteAttribute\n");
138        return;
139    }
140
141    /* Write a comment as child of ORDER */
142    tmp = ConvertInput("<���>", MY_ENCODING);
143    rc = xmlTextWriterWriteFormatComment(writer,
144		     "This is another comment with special chars: %s",
145		     tmp);
146    if (rc < 0) {
147        printf
148            ("testXmlwriterFilename: Error at xmlTextWriterWriteFormatComment\n");
149        return;
150    }
151    if (tmp != NULL) xmlFree(tmp);
152
153    /* Start an element named "HEADER" as child of ORDER. */
154    rc = xmlTextWriterStartElement(writer, BAD_CAST "HEADER");
155    if (rc < 0) {
156        printf
157            ("testXmlwriterFilename: Error at xmlTextWriterStartElement\n");
158        return;
159    }
160
161    /* Write an element named "X_ORDER_ID" as child of HEADER. */
162    rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "X_ORDER_ID",
163                                         "%010d", 53535);
164    if (rc < 0) {
165        printf
166            ("testXmlwriterFilename: Error at xmlTextWriterWriteFormatElement\n");
167        return;
168    }
169
170    /* Write an element named "CUSTOMER_ID" as child of HEADER. */
171    rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "CUSTOMER_ID",
172                                         "%d", 1010);
173    if (rc < 0) {
174        printf
175            ("testXmlwriterFilename: Error at xmlTextWriterWriteFormatElement\n");
176        return;
177    }
178
179    /* Write an element named "NAME_1" as child of HEADER. */
180    tmp = ConvertInput("M�ller", MY_ENCODING);
181    rc = xmlTextWriterWriteElement(writer, BAD_CAST "NAME_1", tmp);
182    if (rc < 0) {
183        printf
184            ("testXmlwriterFilename: Error at xmlTextWriterWriteElement\n");
185        return;
186    }
187    if (tmp != NULL) xmlFree(tmp);
188
189    /* Write an element named "NAME_2" as child of HEADER. */
190    tmp = ConvertInput("J�rg", MY_ENCODING);
191    rc = xmlTextWriterWriteElement(writer, BAD_CAST "NAME_2", tmp);
192    if (rc < 0) {
193        printf
194            ("testXmlwriterFilename: Error at xmlTextWriterWriteElement\n");
195        return;
196    }
197    if (tmp != NULL) xmlFree(tmp);
198
199    /* Close the element named HEADER. */
200    rc = xmlTextWriterEndElement(writer);
201    if (rc < 0) {
202        printf
203            ("testXmlwriterFilename: Error at xmlTextWriterEndElement\n");
204        return;
205    }
206
207    /* Start an element named "ENTRIES" as child of ORDER. */
208    rc = xmlTextWriterStartElement(writer, BAD_CAST "ENTRIES");
209    if (rc < 0) {
210        printf
211            ("testXmlwriterFilename: Error at xmlTextWriterStartElement\n");
212        return;
213    }
214
215    /* Start an element named "ENTRY" as child of ENTRIES. */
216    rc = xmlTextWriterStartElement(writer, BAD_CAST "ENTRY");
217    if (rc < 0) {
218        printf
219            ("testXmlwriterFilename: Error at xmlTextWriterStartElement\n");
220        return;
221    }
222
223    /* Write an element named "ARTICLE" as child of ENTRY. */
224    rc = xmlTextWriterWriteElement(writer, BAD_CAST "ARTICLE",
225                                   BAD_CAST "<Test>");
226    if (rc < 0) {
227        printf
228            ("testXmlwriterFilename: Error at xmlTextWriterWriteElement\n");
229        return;
230    }
231
232    /* Write an element named "ENTRY_NO" as child of ENTRY. */
233    rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "ENTRY_NO", "%d",
234                                         10);
235    if (rc < 0) {
236        printf
237            ("testXmlwriterFilename: Error at xmlTextWriterWriteFormatElement\n");
238        return;
239    }
240
241    /* Close the element named ENTRY. */
242    rc = xmlTextWriterEndElement(writer);
243    if (rc < 0) {
244        printf
245            ("testXmlwriterFilename: Error at xmlTextWriterEndElement\n");
246        return;
247    }
248
249    /* Start an element named "ENTRY" as child of ENTRIES. */
250    rc = xmlTextWriterStartElement(writer, BAD_CAST "ENTRY");
251    if (rc < 0) {
252        printf
253            ("testXmlwriterFilename: Error at xmlTextWriterStartElement\n");
254        return;
255    }
256
257    /* Write an element named "ARTICLE" as child of ENTRY. */
258    rc = xmlTextWriterWriteElement(writer, BAD_CAST "ARTICLE",
259                                   BAD_CAST "<Test 2>");
260    if (rc < 0) {
261        printf
262            ("testXmlwriterFilename: Error at xmlTextWriterWriteElement\n");
263        return;
264    }
265
266    /* Write an element named "ENTRY_NO" as child of ENTRY. */
267    rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "ENTRY_NO", "%d",
268                                         20);
269    if (rc < 0) {
270        printf
271            ("testXmlwriterFilename: Error at xmlTextWriterWriteFormatElement\n");
272        return;
273    }
274
275    /* Close the element named ENTRY. */
276    rc = xmlTextWriterEndElement(writer);
277    if (rc < 0) {
278        printf
279            ("testXmlwriterFilename: Error at xmlTextWriterEndElement\n");
280        return;
281    }
282
283    /* Close the element named ENTRIES. */
284    rc = xmlTextWriterEndElement(writer);
285    if (rc < 0) {
286        printf
287            ("testXmlwriterFilename: Error at xmlTextWriterEndElement\n");
288        return;
289    }
290
291    /* Start an element named "FOOTER" as child of ORDER. */
292    rc = xmlTextWriterStartElement(writer, BAD_CAST "FOOTER");
293    if (rc < 0) {
294        printf
295            ("testXmlwriterFilename: Error at xmlTextWriterStartElement\n");
296        return;
297    }
298
299    /* Write an element named "TEXT" as child of FOOTER. */
300    rc = xmlTextWriterWriteElement(writer, BAD_CAST "TEXT",
301                                   BAD_CAST "This is a text.");
302    if (rc < 0) {
303        printf
304            ("testXmlwriterFilename: Error at xmlTextWriterWriteElement\n");
305        return;
306    }
307
308    /* Close the element named FOOTER. */
309    rc = xmlTextWriterEndElement(writer);
310    if (rc < 0) {
311        printf
312            ("testXmlwriterFilename: Error at xmlTextWriterEndElement\n");
313        return;
314    }
315
316    /* Here we could close the elements ORDER and EXAMPLE using the
317     * function xmlTextWriterEndElement, but since we do not want to
318     * write any other elements, we simply call xmlTextWriterEndDocument,
319     * which will do all the work. */
320    rc = xmlTextWriterEndDocument(writer);
321    if (rc < 0) {
322        printf
323            ("testXmlwriterFilename: Error at xmlTextWriterEndDocument\n");
324        return;
325    }
326
327    xmlFreeTextWriter(writer);
328}
329
330/**
331 * testXmlwriterMemory:
332 * @file: the output file
333 *
334 * test the xmlWriter interface when writing to memory
335 */
336void
337testXmlwriterMemory(const char *file)
338{
339    int rc;
340    xmlTextWriterPtr writer;
341    xmlBufferPtr buf;
342    xmlChar *tmp;
343    FILE *fp;
344
345    /* Create a new XML buffer, to which the XML document will be
346     * written */
347    buf = xmlBufferCreate();
348    if (buf == NULL) {
349        printf("testXmlwriterMemory: Error creating the xml buffer\n");
350        return;
351    }
352
353    /* Create a new XmlWriter for memory, with no compression.
354     * Remark: there is no compression for this kind of xmlTextWriter */
355    writer = xmlNewTextWriterMemory(buf, 0);
356    if (writer == NULL) {
357        printf("testXmlwriterMemory: Error creating the xml writer\n");
358        return;
359    }
360
361    /* Start the document with the xml default for the version,
362     * encoding ISO 8859-1 and the default for the standalone
363     * declaration. */
364    rc = xmlTextWriterStartDocument(writer, NULL, MY_ENCODING, NULL);
365    if (rc < 0) {
366        printf
367            ("testXmlwriterMemory: Error at xmlTextWriterStartDocument\n");
368        return;
369    }
370
371    /* Start an element named "EXAMPLE". Since thist is the first
372     * element, this will be the root element of the document. */
373    rc = xmlTextWriterStartElement(writer, BAD_CAST "EXAMPLE");
374    if (rc < 0) {
375        printf
376            ("testXmlwriterMemory: Error at xmlTextWriterStartElement\n");
377        return;
378    }
379
380    /* Write a comment as child of EXAMPLE.
381     * Please observe, that the input to the xmlTextWriter functions
382     * HAS to be in UTF-8, even if the output XML is encoded
383     * in iso-8859-1 */
384    tmp = ConvertInput("This is a comment with special chars: <���>",
385                       MY_ENCODING);
386    rc = xmlTextWriterWriteComment(writer, tmp);
387    if (rc < 0) {
388        printf
389            ("testXmlwriterMemory: Error at xmlTextWriterWriteComment\n");
390        return;
391    }
392    if (tmp != NULL) xmlFree(tmp);
393
394    /* Start an element named "ORDER" as child of EXAMPLE. */
395    rc = xmlTextWriterStartElement(writer, BAD_CAST "ORDER");
396    if (rc < 0) {
397        printf
398            ("testXmlwriterMemory: Error at xmlTextWriterStartElement\n");
399        return;
400    }
401
402    /* Add an attribute with name "version" and value "1.0" to ORDER. */
403    rc = xmlTextWriterWriteAttribute(writer, BAD_CAST "version",
404                                     BAD_CAST "1.0");
405    if (rc < 0) {
406        printf
407            ("testXmlwriterMemory: Error at xmlTextWriterWriteAttribute\n");
408        return;
409    }
410
411    /* Add an attribute with name "xml:lang" and value "de" to ORDER. */
412    rc = xmlTextWriterWriteAttribute(writer, BAD_CAST "xml:lang",
413                                     BAD_CAST "de");
414    if (rc < 0) {
415        printf
416            ("testXmlwriterMemory: Error at xmlTextWriterWriteAttribute\n");
417        return;
418    }
419
420    /* Write a comment as child of ORDER */
421    tmp = ConvertInput("<���>", MY_ENCODING);
422    rc = xmlTextWriterWriteFormatComment(writer,
423		     "This is another comment with special chars: %s",
424                                         tmp);
425    if (rc < 0) {
426        printf
427            ("testXmlwriterMemory: Error at xmlTextWriterWriteFormatComment\n");
428        return;
429    }
430    if (tmp != NULL) xmlFree(tmp);
431
432    /* Start an element named "HEADER" as child of ORDER. */
433    rc = xmlTextWriterStartElement(writer, BAD_CAST "HEADER");
434    if (rc < 0) {
435        printf
436            ("testXmlwriterMemory: Error at xmlTextWriterStartElement\n");
437        return;
438    }
439
440    /* Write an element named "X_ORDER_ID" as child of HEADER. */
441    rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "X_ORDER_ID",
442                                         "%010d", 53535);
443    if (rc < 0) {
444        printf
445            ("testXmlwriterMemory: Error at xmlTextWriterWriteFormatElement\n");
446        return;
447    }
448
449    /* Write an element named "CUSTOMER_ID" as child of HEADER. */
450    rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "CUSTOMER_ID",
451                                         "%d", 1010);
452    if (rc < 0) {
453        printf
454            ("testXmlwriterMemory: Error at xmlTextWriterWriteFormatElement\n");
455        return;
456    }
457
458    /* Write an element named "NAME_1" as child of HEADER. */
459    tmp = ConvertInput("M�ller", MY_ENCODING);
460    rc = xmlTextWriterWriteElement(writer, BAD_CAST "NAME_1", tmp);
461    if (rc < 0) {
462        printf
463            ("testXmlwriterMemory: Error at xmlTextWriterWriteElement\n");
464        return;
465    }
466    if (tmp != NULL) xmlFree(tmp);
467
468    /* Write an element named "NAME_2" as child of HEADER. */
469    tmp = ConvertInput("J�rg", MY_ENCODING);
470    rc = xmlTextWriterWriteElement(writer, BAD_CAST "NAME_2", tmp);
471
472    if (rc < 0) {
473        printf
474            ("testXmlwriterMemory: Error at xmlTextWriterWriteElement\n");
475        return;
476    }
477    if (tmp != NULL) xmlFree(tmp);
478
479    /* Close the element named HEADER. */
480    rc = xmlTextWriterEndElement(writer);
481    if (rc < 0) {
482        printf("testXmlwriterMemory: Error at xmlTextWriterEndElement\n");
483        return;
484    }
485
486    /* Start an element named "ENTRIES" as child of ORDER. */
487    rc = xmlTextWriterStartElement(writer, BAD_CAST "ENTRIES");
488    if (rc < 0) {
489        printf
490            ("testXmlwriterMemory: Error at xmlTextWriterStartElement\n");
491        return;
492    }
493
494    /* Start an element named "ENTRY" as child of ENTRIES. */
495    rc = xmlTextWriterStartElement(writer, BAD_CAST "ENTRY");
496    if (rc < 0) {
497        printf
498            ("testXmlwriterMemory: Error at xmlTextWriterStartElement\n");
499        return;
500    }
501
502    /* Write an element named "ARTICLE" as child of ENTRY. */
503    rc = xmlTextWriterWriteElement(writer, BAD_CAST "ARTICLE",
504                                   BAD_CAST "<Test>");
505    if (rc < 0) {
506        printf
507            ("testXmlwriterMemory: Error at xmlTextWriterWriteElement\n");
508        return;
509    }
510
511    /* Write an element named "ENTRY_NO" as child of ENTRY. */
512    rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "ENTRY_NO", "%d",
513                                         10);
514    if (rc < 0) {
515        printf
516            ("testXmlwriterMemory: Error at xmlTextWriterWriteFormatElement\n");
517        return;
518    }
519
520    /* Close the element named ENTRY. */
521    rc = xmlTextWriterEndElement(writer);
522    if (rc < 0) {
523        printf("testXmlwriterMemory: Error at xmlTextWriterEndElement\n");
524        return;
525    }
526
527    /* Start an element named "ENTRY" as child of ENTRIES. */
528    rc = xmlTextWriterStartElement(writer, BAD_CAST "ENTRY");
529    if (rc < 0) {
530        printf
531            ("testXmlwriterMemory: Error at xmlTextWriterStartElement\n");
532        return;
533    }
534
535    /* Write an element named "ARTICLE" as child of ENTRY. */
536    rc = xmlTextWriterWriteElement(writer, BAD_CAST "ARTICLE",
537                                   BAD_CAST "<Test 2>");
538    if (rc < 0) {
539        printf
540            ("testXmlwriterMemory: Error at xmlTextWriterWriteElement\n");
541        return;
542    }
543
544    /* Write an element named "ENTRY_NO" as child of ENTRY. */
545    rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "ENTRY_NO", "%d",
546                                         20);
547    if (rc < 0) {
548        printf
549            ("testXmlwriterMemory: Error at xmlTextWriterWriteFormatElement\n");
550        return;
551    }
552
553    /* Close the element named ENTRY. */
554    rc = xmlTextWriterEndElement(writer);
555    if (rc < 0) {
556        printf("testXmlwriterMemory: Error at xmlTextWriterEndElement\n");
557        return;
558    }
559
560    /* Close the element named ENTRIES. */
561    rc = xmlTextWriterEndElement(writer);
562    if (rc < 0) {
563        printf("testXmlwriterMemory: Error at xmlTextWriterEndElement\n");
564        return;
565    }
566
567    /* Start an element named "FOOTER" as child of ORDER. */
568    rc = xmlTextWriterStartElement(writer, BAD_CAST "FOOTER");
569    if (rc < 0) {
570        printf
571            ("testXmlwriterMemory: Error at xmlTextWriterStartElement\n");
572        return;
573    }
574
575    /* Write an element named "TEXT" as child of FOOTER. */
576    rc = xmlTextWriterWriteElement(writer, BAD_CAST "TEXT",
577                                   BAD_CAST "This is a text.");
578    if (rc < 0) {
579        printf
580            ("testXmlwriterMemory: Error at xmlTextWriterWriteElement\n");
581        return;
582    }
583
584    /* Close the element named FOOTER. */
585    rc = xmlTextWriterEndElement(writer);
586    if (rc < 0) {
587        printf("testXmlwriterMemory: Error at xmlTextWriterEndElement\n");
588        return;
589    }
590
591    /* Here we could close the elements ORDER and EXAMPLE using the
592     * function xmlTextWriterEndElement, but since we do not want to
593     * write any other elements, we simply call xmlTextWriterEndDocument,
594     * which will do all the work. */
595    rc = xmlTextWriterEndDocument(writer);
596    if (rc < 0) {
597        printf("testXmlwriterMemory: Error at xmlTextWriterEndDocument\n");
598        return;
599    }
600
601    xmlFreeTextWriter(writer);
602
603    fp = fopen(file, "w");
604    if (fp == NULL) {
605        printf("testXmlwriterMemory: Error at fopen\n");
606        return;
607    }
608
609    fprintf(fp, "%s", (const char *) buf->content);
610
611    fclose(fp);
612
613    xmlBufferFree(buf);
614}
615
616/**
617 * testXmlwriterDoc:
618 * @file: the output file
619 *
620 * test the xmlWriter interface when creating a new document
621 */
622void
623testXmlwriterDoc(const char *file)
624{
625    int rc;
626    xmlTextWriterPtr writer;
627    xmlChar *tmp;
628    xmlDocPtr doc;
629
630
631    /* Create a new XmlWriter for DOM, with no compression. */
632    writer = xmlNewTextWriterDoc(&doc, 0);
633    if (writer == NULL) {
634        printf("testXmlwriterDoc: Error creating the xml writer\n");
635        return;
636    }
637
638    /* Start the document with the xml default for the version,
639     * encoding ISO 8859-1 and the default for the standalone
640     * declaration. */
641    rc = xmlTextWriterStartDocument(writer, NULL, MY_ENCODING, NULL);
642    if (rc < 0) {
643        printf("testXmlwriterDoc: Error at xmlTextWriterStartDocument\n");
644        return;
645    }
646
647    /* Start an element named "EXAMPLE". Since thist is the first
648     * element, this will be the root element of the document. */
649    rc = xmlTextWriterStartElement(writer, BAD_CAST "EXAMPLE");
650    if (rc < 0) {
651        printf("testXmlwriterDoc: Error at xmlTextWriterStartElement\n");
652        return;
653    }
654
655    /* Write a comment as child of EXAMPLE.
656     * Please observe, that the input to the xmlTextWriter functions
657     * HAS to be in UTF-8, even if the output XML is encoded
658     * in iso-8859-1 */
659    tmp = ConvertInput("This is a comment with special chars: <���>",
660                       MY_ENCODING);
661    rc = xmlTextWriterWriteComment(writer, tmp);
662    if (rc < 0) {
663        printf("testXmlwriterDoc: Error at xmlTextWriterWriteComment\n");
664        return;
665    }
666    if (tmp != NULL) xmlFree(tmp);
667
668    /* Start an element named "ORDER" as child of EXAMPLE. */
669    rc = xmlTextWriterStartElement(writer, BAD_CAST "ORDER");
670    if (rc < 0) {
671        printf("testXmlwriterDoc: Error at xmlTextWriterStartElement\n");
672        return;
673    }
674
675    /* Add an attribute with name "version" and value "1.0" to ORDER. */
676    rc = xmlTextWriterWriteAttribute(writer, BAD_CAST "version",
677                                     BAD_CAST "1.0");
678    if (rc < 0) {
679        printf("testXmlwriterDoc: Error at xmlTextWriterWriteAttribute\n");
680        return;
681    }
682
683    /* Add an attribute with name "xml:lang" and value "de" to ORDER. */
684    rc = xmlTextWriterWriteAttribute(writer, BAD_CAST "xml:lang",
685                                     BAD_CAST "de");
686    if (rc < 0) {
687        printf("testXmlwriterDoc: Error at xmlTextWriterWriteAttribute\n");
688        return;
689    }
690
691    /* Write a comment as child of ORDER */
692    tmp = ConvertInput("<���>", MY_ENCODING);
693    rc = xmlTextWriterWriteFormatComment(writer,
694		 "This is another comment with special chars: %s",
695		                         tmp);
696    if (rc < 0) {
697        printf
698            ("testXmlwriterDoc: Error at xmlTextWriterWriteFormatComment\n");
699        return;
700    }
701    if (tmp != NULL) xmlFree(tmp);
702
703    /* Start an element named "HEADER" as child of ORDER. */
704    rc = xmlTextWriterStartElement(writer, BAD_CAST "HEADER");
705    if (rc < 0) {
706        printf("testXmlwriterDoc: Error at xmlTextWriterStartElement\n");
707        return;
708    }
709
710    /* Write an element named "X_ORDER_ID" as child of HEADER. */
711    rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "X_ORDER_ID",
712                                         "%010d", 53535);
713    if (rc < 0) {
714        printf
715            ("testXmlwriterDoc: Error at xmlTextWriterWriteFormatElement\n");
716        return;
717    }
718
719    /* Write an element named "CUSTOMER_ID" as child of HEADER. */
720    rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "CUSTOMER_ID",
721                                         "%d", 1010);
722    if (rc < 0) {
723        printf
724            ("testXmlwriterDoc: Error at xmlTextWriterWriteFormatElement\n");
725        return;
726    }
727
728    /* Write an element named "NAME_1" as child of HEADER. */
729    tmp = ConvertInput("M�ller", MY_ENCODING);
730    rc = xmlTextWriterWriteElement(writer, BAD_CAST "NAME_1", tmp);
731    if (rc < 0) {
732        printf("testXmlwriterDoc: Error at xmlTextWriterWriteElement\n");
733        return;
734    }
735    if (tmp != NULL) xmlFree(tmp);
736
737    /* Write an element named "NAME_2" as child of HEADER. */
738    tmp = ConvertInput("J�rg", MY_ENCODING);
739    rc = xmlTextWriterWriteElement(writer, BAD_CAST "NAME_2", tmp);
740    if (rc < 0) {
741        printf("testXmlwriterDoc: Error at xmlTextWriterWriteElement\n");
742        return;
743    }
744    if (tmp != NULL) xmlFree(tmp);
745
746    /* Close the element named HEADER. */
747    rc = xmlTextWriterEndElement(writer);
748    if (rc < 0) {
749        printf("testXmlwriterDoc: Error at xmlTextWriterEndElement\n");
750        return;
751    }
752
753    /* Start an element named "ENTRIES" as child of ORDER. */
754    rc = xmlTextWriterStartElement(writer, BAD_CAST "ENTRIES");
755    if (rc < 0) {
756        printf("testXmlwriterDoc: Error at xmlTextWriterStartElement\n");
757        return;
758    }
759
760    /* Start an element named "ENTRY" as child of ENTRIES. */
761    rc = xmlTextWriterStartElement(writer, BAD_CAST "ENTRY");
762    if (rc < 0) {
763        printf("testXmlwriterDoc: Error at xmlTextWriterStartElement\n");
764        return;
765    }
766
767    /* Write an element named "ARTICLE" as child of ENTRY. */
768    rc = xmlTextWriterWriteElement(writer, BAD_CAST "ARTICLE",
769                                   BAD_CAST "<Test>");
770    if (rc < 0) {
771        printf("testXmlwriterDoc: Error at xmlTextWriterWriteElement\n");
772        return;
773    }
774
775    /* Write an element named "ENTRY_NO" as child of ENTRY. */
776    rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "ENTRY_NO", "%d",
777                                         10);
778    if (rc < 0) {
779        printf
780            ("testXmlwriterDoc: Error at xmlTextWriterWriteFormatElement\n");
781        return;
782    }
783
784    /* Close the element named ENTRY. */
785    rc = xmlTextWriterEndElement(writer);
786    if (rc < 0) {
787        printf("testXmlwriterDoc: Error at xmlTextWriterEndElement\n");
788        return;
789    }
790
791    /* Start an element named "ENTRY" as child of ENTRIES. */
792    rc = xmlTextWriterStartElement(writer, BAD_CAST "ENTRY");
793    if (rc < 0) {
794        printf("testXmlwriterDoc: Error at xmlTextWriterStartElement\n");
795        return;
796    }
797
798    /* Write an element named "ARTICLE" as child of ENTRY. */
799    rc = xmlTextWriterWriteElement(writer, BAD_CAST "ARTICLE",
800                                   BAD_CAST "<Test 2>");
801    if (rc < 0) {
802        printf("testXmlwriterDoc: Error at xmlTextWriterWriteElement\n");
803        return;
804    }
805
806    /* Write an element named "ENTRY_NO" as child of ENTRY. */
807    rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "ENTRY_NO", "%d",
808                                         20);
809    if (rc < 0) {
810        printf
811            ("testXmlwriterDoc: Error at xmlTextWriterWriteFormatElement\n");
812        return;
813    }
814
815    /* Close the element named ENTRY. */
816    rc = xmlTextWriterEndElement(writer);
817    if (rc < 0) {
818        printf("testXmlwriterDoc: Error at xmlTextWriterEndElement\n");
819        return;
820    }
821
822    /* Close the element named ENTRIES. */
823    rc = xmlTextWriterEndElement(writer);
824    if (rc < 0) {
825        printf("testXmlwriterDoc: Error at xmlTextWriterEndElement\n");
826        return;
827    }
828
829    /* Start an element named "FOOTER" as child of ORDER. */
830    rc = xmlTextWriterStartElement(writer, BAD_CAST "FOOTER");
831    if (rc < 0) {
832        printf("testXmlwriterDoc: Error at xmlTextWriterStartElement\n");
833        return;
834    }
835
836    /* Write an element named "TEXT" as child of FOOTER. */
837    rc = xmlTextWriterWriteElement(writer, BAD_CAST "TEXT",
838                                   BAD_CAST "This is a text.");
839    if (rc < 0) {
840        printf("testXmlwriterDoc: Error at xmlTextWriterWriteElement\n");
841        return;
842    }
843
844    /* Close the element named FOOTER. */
845    rc = xmlTextWriterEndElement(writer);
846    if (rc < 0) {
847        printf("testXmlwriterDoc: Error at xmlTextWriterEndElement\n");
848        return;
849    }
850
851    /* Here we could close the elements ORDER and EXAMPLE using the
852     * function xmlTextWriterEndElement, but since we do not want to
853     * write any other elements, we simply call xmlTextWriterEndDocument,
854     * which will do all the work. */
855    rc = xmlTextWriterEndDocument(writer);
856    if (rc < 0) {
857        printf("testXmlwriterDoc: Error at xmlTextWriterEndDocument\n");
858        return;
859    }
860
861    xmlFreeTextWriter(writer);
862
863    xmlSaveFileEnc(file, doc, MY_ENCODING);
864
865    xmlFreeDoc(doc);
866}
867
868/**
869 * testXmlwriterTree:
870 * @file: the output file
871 *
872 * test the xmlWriter interface when writing to a subtree
873 */
874void
875testXmlwriterTree(const char *file)
876{
877    int rc;
878    xmlTextWriterPtr writer;
879    xmlDocPtr doc;
880    xmlNodePtr node;
881    xmlChar *tmp;
882
883    /* Create a new XML DOM tree, to which the XML document will be
884     * written */
885    doc = xmlNewDoc(BAD_CAST XML_DEFAULT_VERSION);
886    if (doc == NULL) {
887        printf
888            ("testXmlwriterTree: Error creating the xml document tree\n");
889        return;
890    }
891
892    /* Create a new XML node, to which the XML document will be
893     * appended */
894    node = xmlNewDocNode(doc, NULL, BAD_CAST "EXAMPLE", NULL);
895    if (node == NULL) {
896        printf("testXmlwriterTree: Error creating the xml node\n");
897        return;
898    }
899
900    /* Make ELEMENT the root node of the tree */
901    xmlDocSetRootElement(doc, node);
902
903    /* Create a new XmlWriter for DOM tree, with no compression. */
904    writer = xmlNewTextWriterTree(doc, node, 0);
905    if (writer == NULL) {
906        printf("testXmlwriterTree: Error creating the xml writer\n");
907        return;
908    }
909
910    /* Start the document with the xml default for the version,
911     * encoding ISO 8859-1 and the default for the standalone
912     * declaration. */
913    rc = xmlTextWriterStartDocument(writer, NULL, MY_ENCODING, NULL);
914    if (rc < 0) {
915        printf("testXmlwriterTree: Error at xmlTextWriterStartDocument\n");
916        return;
917    }
918
919    /* Write a comment as child of EXAMPLE.
920     * Please observe, that the input to the xmlTextWriter functions
921     * HAS to be in UTF-8, even if the output XML is encoded
922     * in iso-8859-1 */
923    tmp = ConvertInput("This is a comment with special chars: <���>",
924                       MY_ENCODING);
925    rc = xmlTextWriterWriteComment(writer, tmp);
926    if (rc < 0) {
927        printf("testXmlwriterTree: Error at xmlTextWriterWriteComment\n");
928        return;
929    }
930    if (tmp != NULL) xmlFree(tmp);
931
932    /* Start an element named "ORDER" as child of EXAMPLE. */
933    rc = xmlTextWriterStartElement(writer, BAD_CAST "ORDER");
934    if (rc < 0) {
935        printf("testXmlwriterTree: Error at xmlTextWriterStartElement\n");
936        return;
937    }
938
939    /* Add an attribute with name "version" and value "1.0" to ORDER. */
940    rc = xmlTextWriterWriteAttribute(writer, BAD_CAST "version",
941                                     BAD_CAST "1.0");
942    if (rc < 0) {
943        printf
944            ("testXmlwriterTree: Error at xmlTextWriterWriteAttribute\n");
945        return;
946    }
947
948    /* Add an attribute with name "xml:lang" and value "de" to ORDER. */
949    rc = xmlTextWriterWriteAttribute(writer, BAD_CAST "xml:lang",
950                                     BAD_CAST "de");
951    if (rc < 0) {
952        printf
953            ("testXmlwriterTree: Error at xmlTextWriterWriteAttribute\n");
954        return;
955    }
956
957    /* Write a comment as child of ORDER */
958    tmp = ConvertInput("<���>", MY_ENCODING);
959    rc = xmlTextWriterWriteFormatComment(writer,
960			 "This is another comment with special chars: %s",
961					  tmp);
962    if (rc < 0) {
963        printf
964            ("testXmlwriterTree: Error at xmlTextWriterWriteFormatComment\n");
965        return;
966    }
967    if (tmp != NULL) xmlFree(tmp);
968
969    /* Start an element named "HEADER" as child of ORDER. */
970    rc = xmlTextWriterStartElement(writer, BAD_CAST "HEADER");
971    if (rc < 0) {
972        printf("testXmlwriterTree: Error at xmlTextWriterStartElement\n");
973        return;
974    }
975
976    /* Write an element named "X_ORDER_ID" as child of HEADER. */
977    rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "X_ORDER_ID",
978                                         "%010d", 53535);
979    if (rc < 0) {
980        printf
981            ("testXmlwriterTree: Error at xmlTextWriterWriteFormatElement\n");
982        return;
983    }
984
985    /* Write an element named "CUSTOMER_ID" as child of HEADER. */
986    rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "CUSTOMER_ID",
987                                         "%d", 1010);
988    if (rc < 0) {
989        printf
990            ("testXmlwriterTree: Error at xmlTextWriterWriteFormatElement\n");
991        return;
992    }
993
994    /* Write an element named "NAME_1" as child of HEADER. */
995    tmp = ConvertInput("M�ller", MY_ENCODING);
996    rc = xmlTextWriterWriteElement(writer, BAD_CAST "NAME_1", tmp);
997    if (rc < 0) {
998        printf("testXmlwriterTree: Error at xmlTextWriterWriteElement\n");
999        return;
1000    }
1001    if (tmp != NULL) xmlFree(tmp);
1002
1003    /* Write an element named "NAME_2" as child of HEADER. */
1004    tmp = ConvertInput("J�rg", MY_ENCODING);
1005    rc = xmlTextWriterWriteElement(writer, BAD_CAST "NAME_2", tmp);
1006    if (rc < 0) {
1007        printf("testXmlwriterTree: Error at xmlTextWriterWriteElement\n");
1008        return;
1009    }
1010    if (tmp != NULL) xmlFree(tmp);
1011
1012    /* Close the element named HEADER. */
1013    rc = xmlTextWriterEndElement(writer);
1014    if (rc < 0) {
1015        printf("testXmlwriterTree: Error at xmlTextWriterEndElement\n");
1016        return;
1017    }
1018
1019    /* Start an element named "ENTRIES" as child of ORDER. */
1020    rc = xmlTextWriterStartElement(writer, BAD_CAST "ENTRIES");
1021    if (rc < 0) {
1022        printf("testXmlwriterTree: Error at xmlTextWriterStartElement\n");
1023        return;
1024    }
1025
1026    /* Start an element named "ENTRY" as child of ENTRIES. */
1027    rc = xmlTextWriterStartElement(writer, BAD_CAST "ENTRY");
1028    if (rc < 0) {
1029        printf("testXmlwriterTree: Error at xmlTextWriterStartElement\n");
1030        return;
1031    }
1032
1033    /* Write an element named "ARTICLE" as child of ENTRY. */
1034    rc = xmlTextWriterWriteElement(writer, BAD_CAST "ARTICLE",
1035                                   BAD_CAST "<Test>");
1036    if (rc < 0) {
1037        printf("testXmlwriterTree: Error at xmlTextWriterWriteElement\n");
1038        return;
1039    }
1040
1041    /* Write an element named "ENTRY_NO" as child of ENTRY. */
1042    rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "ENTRY_NO", "%d",
1043                                         10);
1044    if (rc < 0) {
1045        printf
1046            ("testXmlwriterTree: Error at xmlTextWriterWriteFormatElement\n");
1047        return;
1048    }
1049
1050    /* Close the element named ENTRY. */
1051    rc = xmlTextWriterEndElement(writer);
1052    if (rc < 0) {
1053        printf("testXmlwriterTree: Error at xmlTextWriterEndElement\n");
1054        return;
1055    }
1056
1057    /* Start an element named "ENTRY" as child of ENTRIES. */
1058    rc = xmlTextWriterStartElement(writer, BAD_CAST "ENTRY");
1059    if (rc < 0) {
1060        printf("testXmlwriterTree: Error at xmlTextWriterStartElement\n");
1061        return;
1062    }
1063
1064    /* Write an element named "ARTICLE" as child of ENTRY. */
1065    rc = xmlTextWriterWriteElement(writer, BAD_CAST "ARTICLE",
1066                                   BAD_CAST "<Test 2>");
1067    if (rc < 0) {
1068        printf("testXmlwriterTree: Error at xmlTextWriterWriteElement\n");
1069        return;
1070    }
1071
1072    /* Write an element named "ENTRY_NO" as child of ENTRY. */
1073    rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "ENTRY_NO", "%d",
1074                                         20);
1075    if (rc < 0) {
1076        printf
1077            ("testXmlwriterTree: Error at xmlTextWriterWriteFormatElement\n");
1078        return;
1079    }
1080
1081    /* Close the element named ENTRY. */
1082    rc = xmlTextWriterEndElement(writer);
1083    if (rc < 0) {
1084        printf("testXmlwriterTree: Error at xmlTextWriterEndElement\n");
1085        return;
1086    }
1087
1088    /* Close the element named ENTRIES. */
1089    rc = xmlTextWriterEndElement(writer);
1090    if (rc < 0) {
1091        printf("testXmlwriterTree: Error at xmlTextWriterEndElement\n");
1092        return;
1093    }
1094
1095    /* Start an element named "FOOTER" as child of ORDER. */
1096    rc = xmlTextWriterStartElement(writer, BAD_CAST "FOOTER");
1097    if (rc < 0) {
1098        printf("testXmlwriterTree: Error at xmlTextWriterStartElement\n");
1099        return;
1100    }
1101
1102    /* Write an element named "TEXT" as child of FOOTER. */
1103    rc = xmlTextWriterWriteElement(writer, BAD_CAST "TEXT",
1104                                   BAD_CAST "This is a text.");
1105    if (rc < 0) {
1106        printf("testXmlwriterTree: Error at xmlTextWriterWriteElement\n");
1107        return;
1108    }
1109
1110    /* Close the element named FOOTER. */
1111    rc = xmlTextWriterEndElement(writer);
1112    if (rc < 0) {
1113        printf("testXmlwriterTree: Error at xmlTextWriterEndElement\n");
1114        return;
1115    }
1116
1117    /* Here we could close the elements ORDER and EXAMPLE using the
1118     * function xmlTextWriterEndElement, but since we do not want to
1119     * write any other elements, we simply call xmlTextWriterEndDocument,
1120     * which will do all the work. */
1121    rc = xmlTextWriterEndDocument(writer);
1122    if (rc < 0) {
1123        printf("testXmlwriterTree: Error at xmlTextWriterEndDocument\n");
1124        return;
1125    }
1126
1127    xmlFreeTextWriter(writer);
1128
1129    xmlSaveFileEnc(file, doc, MY_ENCODING);
1130
1131    xmlFreeDoc(doc);
1132}
1133
1134/**
1135 * ConvertInput:
1136 * @in: string in a given encoding
1137 * @encoding: the encoding used
1138 *
1139 * Converts @in into UTF-8 for processing with libxml2 APIs
1140 *
1141 * Returns the converted UTF-8 string, or NULL in case of error.
1142 */
1143xmlChar *
1144ConvertInput(const char *in, const char *encoding)
1145{
1146    xmlChar *out;
1147    int ret;
1148    int size;
1149    int out_size;
1150    int temp;
1151    xmlCharEncodingHandlerPtr handler;
1152
1153    if (in == 0)
1154        return 0;
1155
1156    handler = xmlFindCharEncodingHandler(encoding);
1157
1158    if (!handler) {
1159        printf("ConvertInput: no encoding handler found for '%s'\n",
1160               encoding ? encoding : "");
1161        return 0;
1162    }
1163
1164    size = (int) strlen(in) + 1;
1165    out_size = size * 2 - 1;
1166    out = (unsigned char *) xmlMalloc((size_t) out_size);
1167
1168    if (out != 0) {
1169        temp = size - 1;
1170        ret = handler->input(out, &out_size, (const xmlChar *) in, &temp);
1171        if ((ret < 0) || (temp - size + 1)) {
1172            if (ret < 0) {
1173                printf("ConvertInput: conversion wasn't successful.\n");
1174            } else {
1175                printf
1176                    ("ConvertInput: conversion wasn't successful. converted: %i octets.\n",
1177                     temp);
1178            }
1179
1180            xmlFree(out);
1181            out = 0;
1182        } else {
1183            out = (unsigned char *) xmlRealloc(out, out_size + 1);
1184            out[out_size] = 0;  /*null terminating out */
1185        }
1186    } else {
1187        printf("ConvertInput: no mem\n");
1188    }
1189
1190    return out;
1191}
1192
1193#else
1194int main(void) {
1195    fprintf(stderr, "Writer or output support not compiled in\n");
1196    exit(1);
1197}
1198#endif
1199