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 
23 void testXmlwriterFilename(const char *uri);
24 void testXmlwriterMemory(const char *file);
25 void testXmlwriterDoc(const char *file);
26 void testXmlwriterTree(const char *file);
27 xmlChar *ConvertInput(const char *in, const char *encoding);
28 
29 int
main(void)30 main(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  */
68 void
testXmlwriterFilename(const char * uri)69 testXmlwriterFilename(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 this 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: <\xE4\xF6\xFC>",
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("<\xE4\xF6\xFC>", 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\xFCller", 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\xF6rg", 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  */
336 void
testXmlwriterMemory(const char * file)337 testXmlwriterMemory(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 this 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: <\xE4\xF6\xFC>",
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("<\xE4\xF6\xFC>", 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\xFCller", 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\xF6rg", 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  */
622 void
testXmlwriterDoc(const char * file)623 testXmlwriterDoc(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 this 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: <\xE4\xF6\xFC>",
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("<\xE4\xF6\xFC>", 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\xFCller", 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\xF6rg", 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  */
874 void
testXmlwriterTree(const char * file)875 testXmlwriterTree(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: <\xE4\xF6\xFC>",
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("<\xE4\xF6\xFC>", 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\xFCller", 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\xF6rg", 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  */
1143 xmlChar *
ConvertInput(const char * in,const char * encoding)1144 ConvertInput(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
main(void)1194 int main(void) {
1195     fprintf(stderr, "Writer or output support not compiled in\n");
1196     exit(1);
1197 }
1198 #endif
1199