From 598f6ebb94b00e6583f4b330dcad08ab3a0c5a36 Mon Sep 17 00:00:00 2001 From: MDT 2002 John Fleck Date: Tue, 4 Jun 2002 15:10:36 +0000 Subject: [PATCH] apa.html apb.html apc.html apd.html ar01s02.html ar01s03.html ar01s04.html Tue Jun 4 09:09:18 MDT 2002 John Fleck * added doc/tutorial, including: apa.html apb.html apc.html apd.html ar01s02.html ar01s03.html ar01s04.html ar01s05.html ar01s06.html includeaddattribute.c includeaddkeyword.c includekeyword.c includestory.xml index.html xmltutorial.xml libxml tutorial, including generated html --- ChangeLog | 20 ++ doc/tutorial/apa.html | 15 ++ doc/tutorial/apb.html | 78 ++++++ doc/tutorial/apc.html | 77 ++++++ doc/tutorial/apd.html | 67 ++++++ doc/tutorial/ar01s02.html | 11 + doc/tutorial/ar01s03.html | 33 +++ doc/tutorial/ar01s04.html | 50 ++++ doc/tutorial/ar01s05.html | 34 +++ doc/tutorial/ar01s06.html | 30 +++ doc/tutorial/includeaddattribute.c | 63 +++++ doc/tutorial/includeaddkeyword.c | 73 ++++++ doc/tutorial/includekeyword.c | 74 ++++++ doc/tutorial/includestory.xml | 14 ++ doc/tutorial/index.html | 16 ++ doc/tutorial/xmltutorial.xml | 372 +++++++++++++++++++++++++++++ 16 files changed, 1027 insertions(+) create mode 100644 doc/tutorial/apa.html create mode 100644 doc/tutorial/apb.html create mode 100644 doc/tutorial/apc.html create mode 100644 doc/tutorial/apd.html create mode 100644 doc/tutorial/ar01s02.html create mode 100644 doc/tutorial/ar01s03.html create mode 100644 doc/tutorial/ar01s04.html create mode 100644 doc/tutorial/ar01s05.html create mode 100644 doc/tutorial/ar01s06.html create mode 100644 doc/tutorial/includeaddattribute.c create mode 100644 doc/tutorial/includeaddkeyword.c create mode 100644 doc/tutorial/includekeyword.c create mode 100644 doc/tutorial/includestory.xml create mode 100644 doc/tutorial/index.html create mode 100644 doc/tutorial/xmltutorial.xml diff --git a/ChangeLog b/ChangeLog index 6c2d490c..553e2ea0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,23 @@ +Tue Jun 4 09:09:18 MDT 2002 John Fleck + + * added doc/tutorial, including: + apa.html + apb.html + apc.html + apd.html + ar01s02.html + ar01s03.html + ar01s04.html + ar01s05.html + ar01s06.html + includeaddattribute.c + includeaddkeyword.c + includekeyword.c + includestory.xml + index.html + xmltutorial.xml + libxml tutorial, including generated html + Mon Jun 3 21:21:26 2002 Aleksey Sanin * result/c14n/exc-without-comments/merlin-c14n-two-* diff --git a/doc/tutorial/apa.html b/doc/tutorial/apa.html new file mode 100644 index 00000000..d01ea2ed --- /dev/null +++ b/doc/tutorial/apa.html @@ -0,0 +1,15 @@ + +A. Sample Document

A. Sample Document

+<?xml version="1.0"?>
+<story>
+  <storyinfo>
+    <author>John Fleck</author>
+    <datewritten>June 2, 2002</datewritten>
+    <keyword>example keyword</keyword>
+  </storyinfo>
+  <body>
+    <headline>This is the headline</headline>
+    <para>This is the body text.</para>
+  </body>
+</story>
+
diff --git a/doc/tutorial/apb.html b/doc/tutorial/apb.html new file mode 100644 index 00000000..e3b119ff --- /dev/null +++ b/doc/tutorial/apb.html @@ -0,0 +1,78 @@ + +B. Code for Keyword Example

B. Code for Keyword Example

+

+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <libxml/xmlmemory.h>
+#include <libxml/parser.h>
+
+void
+parseStory (xmlDocPtr doc, xmlNodePtr cur) {
+
+	cur = cur->xmlChildrenNode;
+	while (cur != NULL) {
+	    if ((!xmlStrcmp(cur->name, (const xmlChar *)"keyword"))) {
+		    printf("keyword: %s\n", xmlNodeListGetString(doc, cur->xmlChildrenNode, 1));
+	    }
+	cur = cur->next;
+	}
+    return;
+}
+
+static void
+parseDoc(char *docname) {
+
+	xmlDocPtr doc;
+	xmlNodePtr cur;
+
+	doc = xmlParseFile(docname);
+	
+	if (doc == NULL ) {
+		fprintf(stderr,"Document not parsed successfully. \n");
+		return;
+	}
+	
+	cur = xmlDocGetRootElement(doc);
+	
+	if (cur == NULL) {
+		fprintf(stderr,"empty document\n");
+		xmlFreeDoc(doc);
+		return;
+	}
+	
+	if (xmlStrcmp(cur->name, (const xmlChar *) "story")) {
+		fprintf(stderr,"document of the wrong type, root node != story");
+		xmlFreeDoc(doc);
+		return;
+	}
+	
+	cur = cur->xmlChildrenNode;
+	while (cur != NULL) {
+		if ((!xmlStrcmp(cur->name, (const xmlChar *)"storyinfo"))){
+			parseStory (doc, cur);
+		}
+		 
+	cur = cur->next;
+	}
+       
+}
+
+int
+main(int argc, char **argv) {
+
+	char *docname;
+		
+	if (argc <= 1) {
+		printf("Usage: %s docname\n", argv[0]);
+		return(0);
+	}
+
+	docname = argv[1];
+	parseDoc (docname);
+
+	return (1);
+}
+
+
+

diff --git a/doc/tutorial/apc.html b/doc/tutorial/apc.html new file mode 100644 index 00000000..62ca6b28 --- /dev/null +++ b/doc/tutorial/apc.html @@ -0,0 +1,77 @@ + +C. Code for Add Keyword Example

C. Code for Add Keyword Example

+

+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <libxml/xmlmemory.h>
+#include <libxml/parser.h>
+
+void
+parseStory (xmlDocPtr doc, xmlNodePtr cur, char *keyword) {
+
+	xmlNewTextChild (cur, NULL, "keyword", keyword);
+    return;
+}
+
+xmlDocPtr
+parseDoc(char *docname, char *keyword) {
+
+	xmlDocPtr doc;
+	xmlNodePtr cur;
+
+	doc = xmlParseFile(docname);
+	
+	if (doc == NULL ) {
+		fprintf(stderr,"Document not parsed successfully. \n");
+		return (NULL);
+	}
+	
+	cur = xmlDocGetRootElement(doc);
+	
+	if (cur == NULL) {
+		fprintf(stderr,"empty document\n");
+		xmlFreeDoc(doc);
+		return (NULL);
+	}
+	
+	if (xmlStrcmp(cur->name, (const xmlChar *) "story")) {
+		fprintf(stderr,"document of the wrong type, root node != story");
+		xmlFreeDoc(doc);
+		return (NULL);
+	}
+	
+	cur = cur->xmlChildrenNode;
+	while (cur != NULL) {
+		if ((!xmlStrcmp(cur->name, (const xmlChar *)"storyinfo"))){
+			parseStory (doc, cur, keyword);
+		}
+		 
+	cur = cur->next;
+	}
+	return(doc);
+}
+
+int
+main(int argc, char **argv) {
+
+	char *docname;
+	char *keyword;
+	xmlDocPtr doc;
+
+	if (argc <= 2) {
+		printf("Usage: %s docname, keyword\n", argv[0]);
+		return(0);
+	}
+
+	docname = argv[1];
+	keyword = argv[2];
+	doc = parseDoc (docname, keyword);
+	if (doc != NULL) {
+		xmlSaveFormatFile (docname, doc, 0);
+	}
+	return (1);
+}
+
+
+

diff --git a/doc/tutorial/apd.html b/doc/tutorial/apd.html new file mode 100644 index 00000000..66cddfe3 --- /dev/null +++ b/doc/tutorial/apd.html @@ -0,0 +1,67 @@ + +D. Code for Add Attribute Example

D. Code for Add Attribute Example

+

+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <libxml/xmlmemory.h>
+#include <libxml/parser.h>
+
+
+xmlDocPtr
+parseDoc(char *docname, char *uri) {
+
+	xmlDocPtr doc;
+	xmlNodePtr cur;
+	xmlNodePtr newnode;
+	xmlAttrPtr newattr;
+
+	doc = xmlParseFile(docname);
+	
+	if (doc == NULL ) {
+		fprintf(stderr,"Document not parsed successfully. \n");
+		return (NULL);
+	}
+	
+	cur = xmlDocGetRootElement(doc);
+	
+	if (cur == NULL) {
+		fprintf(stderr,"empty document\n");
+		xmlFreeDoc(doc);
+		return (NULL);
+	}
+	
+	if (xmlStrcmp(cur->name, (const xmlChar *) "story")) {
+		fprintf(stderr,"document of the wrong type, root node != story");
+		xmlFreeDoc(doc);
+		return (NULL);
+	}
+	
+	newnode = xmlNewTextChild (cur, NULL, "reference", NULL);
+	newattr = xmlNewProp (newnode, "uri", uri);
+	return(doc);
+}
+
+int
+main(int argc, char **argv) {
+
+	char *docname;
+	char *uri;
+	xmlDocPtr doc;
+
+	if (argc <= 2) {
+		printf("Usage: %s docname, uri\n", argv[0]);
+		return(0);
+	}
+
+	docname = argv[1];
+	uri = argv[2];
+	doc = parseDoc (docname, uri);
+	if (doc != NULL) {
+		xmlSaveFormatFile (docname, doc, 1);
+	}
+	return (1);
+}
+
+
+

diff --git a/doc/tutorial/ar01s02.html b/doc/tutorial/ar01s02.html new file mode 100644 index 00000000..ba390211 --- /dev/null +++ b/doc/tutorial/ar01s02.html @@ -0,0 +1,11 @@ + +Data Types

Data Types

Libxml declares a number of datatypes we + will encounter repeatedly, hiding the messy stuff so you do not have to deal + with it unless you have some specific need.

+

xmlChar

A basic replacement for char, a byte in a UTF-8 encoded + string.

+ xmlDoc

A structure containing the tree created by a parsed doc. xmlDocPtr + is a pointer to the structure.

xmlNodePtr + and xmlNode

A structure containing a single node. xmlNodePtr + is a pointer to the structure, and is used in traversing the document tree.

+

diff --git a/doc/tutorial/ar01s03.html b/doc/tutorial/ar01s03.html new file mode 100644 index 00000000..62429fa1 --- /dev/null +++ b/doc/tutorial/ar01s03.html @@ -0,0 +1,33 @@ + +Parsing the file

Parsing the file

Parsing the file requires only the name of the file and a single + function call, plus error checking. Full code: Appendix B

+

+        1 xmlDocPtr doc;
+	2 xmlNodePtr cur;
+
+	3 doc = xmlParseFile(docname);
+	
+	4 if (doc == NULL ) {
+		fprintf(stderr,"Document not parsed successfully. \n");
+		return;
+	}
+
+	5 cur = xmlDocGetRootElement(doc);
+	
+	6 if (cur == NULL) {
+		fprintf(stderr,"empty document\n");
+		xmlFreeDoc(doc);
+		return;
+	}
+	
+	7 if (xmlStrcmp(cur->name, (const xmlChar *) "story")) {
+		fprintf(stderr,"document of the wrong type, root node != story");
+		xmlFreeDoc(doc);
+		return;
+	}
+
+    
+
1

Declare the pointer that will point to your parsed document.

2

Declare a node pointer (you'll need this in order to + interact with individual nodes).

4

Check to see that the document was successfully parsed.

5

Retrieve the document's root element.

6

Check to make sure the document actually contains something.

7

In our case, we need to make sure the document is the right + type. "story" is the root type of my documents.

+

diff --git a/doc/tutorial/ar01s04.html b/doc/tutorial/ar01s04.html new file mode 100644 index 00000000..8a9867d0 --- /dev/null +++ b/doc/tutorial/ar01s04.html @@ -0,0 +1,50 @@ + +Retrieving Element Content

Retrieving Element Content

Retrieving the content of an element involves traversing the document + tree until you find what you are looking for. In this case, we are looking + for an element called "keyword" contained within element called "story". The + process to find the node we are interested in involves tediously walking the + tree. We assume you already have an xmlDocPtr called doc + and an xmlNodPtr called cur.

+

+	1 cur = cur->xmlChildrenNode;
+	2 while (cur != NULL) {
+		if ((!xmlStrcmp(cur->name, (const xmlChar *)"storyinfo"))){
+			parseStory (doc, cur);
+		}
+		 
+	cur = cur->next;
+	}
+
+      
+ +
1

Get the first child node of cur. At this + point, cur points at the document root, which is + the element "story".

2

This loop iterates through the elements that are children of + "story", looking for one called "storyinfo". That + is the element that will contain the "keywords" we are + looking for. It uses the libxml string + comparison + function, xmlStrcmp. If there is a match, it calls the function parseStory.

+

+

+void
+parseStory (xmlDocPtr doc, xmlNodePtr cur) {
+
+	1 cur = cur->xmlChildrenNode;
+	2 while (cur != NULL) {
+	    if ((!xmlStrcmp(cur->name, (const xmlChar *)"keyword"))) {
+	3	    printf("keyword: %s\n", xmlNodeListGetString(doc, cur->xmlChildrenNode, 1));
+	    }
+	cur = cur->next;
+	}
+    return;
+}
+      
+
1

Again we get the first child node.

2

Like the loop above, we then iterate through the nodes, looking + for one that matches the element we're interested in, in this case + "keyword".

3

When we find the "keyword" element, we need to print + its contents. Remember that in XML, the text + contained within an element is a child node of that element, so we + turn to cur->xmlChildrenNode. To retrieve it, we + use the function xmlNodeListGetString, which also takes the doc pointer as an argument. In this case, we just print it out.

+

diff --git a/doc/tutorial/ar01s05.html b/doc/tutorial/ar01s05.html new file mode 100644 index 00000000..5f90af87 --- /dev/null +++ b/doc/tutorial/ar01s05.html @@ -0,0 +1,34 @@ + +Writing element content

Writing element content

Writing element content uses many of the same steps we used above + — parsing the document and walking the tree. We parse the document, + then traverse the tree to find the place we want to insert our element. For + this example, we want to again find the "storyinfo" element and + this time insert a keyword. Then we'll write the file to disk. Full code: + Appendix C

+ The main difference in this example is in + parseStory: + +

+void
+parseStory (xmlDocPtr doc, xmlNodePtr cur, char *keyword) {
+
+	1 xmlNewTextChild (cur, NULL, "keyword", keyword);
+    return;
+}
+      
+
1

The xmlNewTextChild + function adds a new child element at the + current node pointer's location in the + tree, specificied by cur.

+

+ Once the node has been added, we would like to write the document to + file. Is you want the element to have a namespace, you can add it here as + well. In our case, the namespace is NULL. +

+	xmlSaveFormatFile (docname, doc, 1);
+      
+ The first parameter is the name of the file to be written. You'll notice + it is the same as the file we just read. In this case, we just write over + the old file. The second parameter is a pointer to the xmlDoc + structure. Setting the third parameter equal to one ensures indenting on output. +

diff --git a/doc/tutorial/ar01s06.html b/doc/tutorial/ar01s06.html new file mode 100644 index 00000000..8d2afd15 --- /dev/null +++ b/doc/tutorial/ar01s06.html @@ -0,0 +1,30 @@ + +Writing Attribute

Writing Attribute

Writing an attribute is similar to writing text to a new element. In + this case, we'll add a reference URI to our + document. Full code:Appendix D.

+ A reference is a child of the story + element, so finding the place to put our new element and attribute is + simple. As soon as we do the error-checking test in our + parseDoc, we are in the right spot to add our + element. But before we do that, we need to make a declaration using a + datatype we have not seen yet: +

+	xmlAttrPtr newattr;
+      
+ We also need an extra xmlNodePtr: +
+	xmlNodePtr newnode;
+      
+

+ The rest of parseDoc is the same as before until we + check to see if our root element is story. If it is, + then we know we are at the right spot to add our element: + +

+	1 newnode = xmlNewTextChild (cur, NULL, "reference", NULL);
+	2 newattr = xmlNewProp (newnode, "uri", uri);	
+      
+
1

First we add a new node at the location of the current node + pointer, cur. using the xmlNewTextChild function.

+

Once the node is added, the file is written to disk just as in the + previous example in which we added an element with text content.

diff --git a/doc/tutorial/includeaddattribute.c b/doc/tutorial/includeaddattribute.c new file mode 100644 index 00000000..45321b3f --- /dev/null +++ b/doc/tutorial/includeaddattribute.c @@ -0,0 +1,63 @@ + +#include +#include +#include +#include + + +xmlDocPtr +parseDoc(char *docname, char *uri) { + + xmlDocPtr doc; + xmlNodePtr cur; + xmlNodePtr newnode; + xmlAttrPtr newattr; + + doc = xmlParseFile(docname); + + if (doc == NULL ) { + fprintf(stderr,"Document not parsed successfully. \n"); + return (NULL); + } + + cur = xmlDocGetRootElement(doc); + + if (cur == NULL) { + fprintf(stderr,"empty document\n"); + xmlFreeDoc(doc); + return (NULL); + } + + if (xmlStrcmp(cur->name, (const xmlChar *) "story")) { + fprintf(stderr,"document of the wrong type, root node != story"); + xmlFreeDoc(doc); + return (NULL); + } + + newnode = xmlNewTextChild (cur, NULL, "reference", NULL); + newattr = xmlNewProp (newnode, "uri", uri); + return(doc); +} + +int +main(int argc, char **argv) { + + char *docname; + char *uri; + xmlDocPtr doc; + + if (argc <= 2) { + printf("Usage: %s docname, uri\n", argv[0]); + return(0); + } + + docname = argv[1]; + uri = argv[2]; + doc = parseDoc (docname, uri); + if (doc != NULL) { + xmlSaveFormatFile (docname, doc, 1); + } + return (1); +} +]]> diff --git a/doc/tutorial/includeaddkeyword.c b/doc/tutorial/includeaddkeyword.c new file mode 100644 index 00000000..8f5de904 --- /dev/null +++ b/doc/tutorial/includeaddkeyword.c @@ -0,0 +1,73 @@ + +#include +#include +#include +#include + +void +parseStory (xmlDocPtr doc, xmlNodePtr cur, char *keyword) { + + xmlNewTextChild (cur, NULL, "keyword", keyword); + return; +} + +xmlDocPtr +parseDoc(char *docname, char *keyword) { + + xmlDocPtr doc; + xmlNodePtr cur; + + doc = xmlParseFile(docname); + + if (doc == NULL ) { + fprintf(stderr,"Document not parsed successfully. \n"); + return (NULL); + } + + cur = xmlDocGetRootElement(doc); + + if (cur == NULL) { + fprintf(stderr,"empty document\n"); + xmlFreeDoc(doc); + return (NULL); + } + + if (xmlStrcmp(cur->name, (const xmlChar *) "story")) { + fprintf(stderr,"document of the wrong type, root node != story"); + xmlFreeDoc(doc); + return (NULL); + } + + cur = cur->xmlChildrenNode; + while (cur != NULL) { + if ((!xmlStrcmp(cur->name, (const xmlChar *)"storyinfo"))){ + parseStory (doc, cur, keyword); + } + + cur = cur->next; + } + return(doc); +} + +int +main(int argc, char **argv) { + + char *docname; + char *keyword; + xmlDocPtr doc; + + if (argc <= 2) { + printf("Usage: %s docname, keyword\n", argv[0]); + return(0); + } + + docname = argv[1]; + keyword = argv[2]; + doc = parseDoc (docname, keyword); + if (doc != NULL) { + xmlSaveFormatFile (docname, doc, 0); + } + return (1); +} +]]> diff --git a/doc/tutorial/includekeyword.c b/doc/tutorial/includekeyword.c new file mode 100644 index 00000000..af2627d4 --- /dev/null +++ b/doc/tutorial/includekeyword.c @@ -0,0 +1,74 @@ + +#include +#include +#include +#include + +void +parseStory (xmlDocPtr doc, xmlNodePtr cur) { + + cur = cur->xmlChildrenNode; + while (cur != NULL) { + if ((!xmlStrcmp(cur->name, (const xmlChar *)"keyword"))) { + printf("keyword: %s\n", xmlNodeListGetString(doc, cur->xmlChildrenNode, 1)); + } + cur = cur->next; + } + return; +} + +static void +parseDoc(char *docname) { + + xmlDocPtr doc; + xmlNodePtr cur; + + doc = xmlParseFile(docname); + + if (doc == NULL ) { + fprintf(stderr,"Document not parsed successfully. \n"); + return; + } + + cur = xmlDocGetRootElement(doc); + + if (cur == NULL) { + fprintf(stderr,"empty document\n"); + xmlFreeDoc(doc); + return; + } + + if (xmlStrcmp(cur->name, (const xmlChar *) "story")) { + fprintf(stderr,"document of the wrong type, root node != story"); + xmlFreeDoc(doc); + return; + } + + cur = cur->xmlChildrenNode; + while (cur != NULL) { + if ((!xmlStrcmp(cur->name, (const xmlChar *)"storyinfo"))){ + parseStory (doc, cur); + } + + cur = cur->next; + } + +} + +int +main(int argc, char **argv) { + + char *docname; + + if (argc <= 1) { + printf("Usage: %s docname\n", argv[0]); + return(0); + } + + docname = argv[1]; + parseDoc (docname); + + return (1); +} +]]> diff --git a/doc/tutorial/includestory.xml b/doc/tutorial/includestory.xml new file mode 100644 index 00000000..2a22c899 --- /dev/null +++ b/doc/tutorial/includestory.xml @@ -0,0 +1,14 @@ + + + + John Fleck + June 2, 2002 + example keyword + + + This is the headline + This is the body text. + + +]]> \ No newline at end of file diff --git a/doc/tutorial/index.html b/doc/tutorial/index.html new file mode 100644 index 00000000..eef00e37 --- /dev/null +++ b/doc/tutorial/index.html @@ -0,0 +1,16 @@ + +Libxml Tutorial

Libxml Tutorial

John Fleck

Revision History
Revision 1June 4,2002

Abstract

Libxml is a freely licensed C language library for handling + XML, portable across a large number of platforms. This + tutorial provides examples of its basic functions.

Introduction

Libxml is a C language library implementing functions for reading, + creating and manipulating XML data. This tutorial + provides example code and explanations of its basic functionality.

Libxml and more details about its use are available on the project home page. Included there is complete + API documentation. This tutorial is not meant + to substitute for that complete documentation, but to illustrate the + functions needed to use the library to perform basic operations. + +

The tutorial is based on a simple XML application I + use for articles I write. The format includes metadata and the body + of the article.

The example code in this tutorial demonstrates how to: +

  • Parse the document.

  • Extract the text within a specified element.

  • Add an element and its content.

  • Extract the value of an attribute.

  • Add an attribute.

+ +

Full code for the examples is included in the appendices.

diff --git a/doc/tutorial/xmltutorial.xml b/doc/tutorial/xmltutorial.xml new file mode 100644 index 00000000..be9a1ba3 --- /dev/null +++ b/doc/tutorial/xmltutorial.xml @@ -0,0 +1,372 @@ + + + + + +]> +
+ + Libxml Tutorial + + John + Fleck + + + 2002 + John Fleck + + + + 1 + June 4,2002 + + + + + Libxml is a freely licensed C language library for handling + XML, portable across a large number of platforms. This + tutorial provides examples of its basic functions. + + + Introduction + Libxml is a C language library implementing functions for reading, + creating and manipulating XML data. This tutorial + provides example code and explanations of its basic functionality. + Libxml and more details about its use are available on the project home page. Included there is complete + API documentation. This tutorial is not meant + to substitute for that complete documentation, but to illustrate the + functions needed to use the library to perform basic operations. + + + The tutorial is based on a simple XML application I + use for articles I write. The format includes metadata and the body + of the article. + The example code in this tutorial demonstrates how to: + + + Parse the document. + + + Extract the text within a specified element. + + + Add an element and its content. + + + Extract the value of an attribute. + + + Add an attribute. + + + + + Full code for the examples is included in the appendices. + + + + + Data Types + Libxml declares a number of datatypes we + will encounter repeatedly, hiding the messy stuff so you do not have to deal + with it unless you have some specific need. + + + + xmlChar + + A basic replacement for char, a byte in a UTF-8 encoded + string. + + + + + xmlDoc + + A structure containing the tree created by a parsed doc. xmlDocPtr + is a pointer to the structure. + + + + xmlNodePtr + and xmlNode + + A structure containing a single node. xmlNodePtr + is a pointer to the structure, and is used in traversing the document tree. + + + + + + + + + Parsing the file + Parsing the file requires only the name of the file and a single + function call, plus error checking. Full code: + + + xmlDocPtr doc; + xmlNodePtr cur; + + doc = xmlParseFile(docname); + + if (doc == NULL ) { + fprintf(stderr,"Document not parsed successfully. \n"); + return; + } + + cur = xmlDocGetRootElement(doc); + + if (cur == NULL) { + fprintf(stderr,"empty document\n"); + xmlFreeDoc(doc); + return; + } + + if (xmlStrcmp(cur->name, (const xmlChar *) "story")) { + fprintf(stderr,"document of the wrong type, root node != story"); + xmlFreeDoc(doc); + return; + } + + + + + Declare the pointer that will point to your parsed document. + + + Declare a node pointer (you'll need this in order to + interact with individual nodes). + + + Check to see that the document was successfully parsed. + + + Retrieve the document's root element. + + + Check to make sure the document actually contains something. + + + In our case, we need to make sure the document is the right + type. "story" is the root type of my documents. + + + + + + + Retrieving Element Content + Retrieving the content of an element involves traversing the document + tree until you find what you are looking for. In this case, we are looking + for an element called "keyword" contained within element called "story". The + process to find the node we are interested in involves tediously walking the + tree. We assume you already have an xmlDocPtr called doc + and an xmlNodPtr called cur. + + + + cur = cur->xmlChildrenNode; + while (cur != NULL) { + if ((!xmlStrcmp(cur->name, (const xmlChar *)"storyinfo"))){ + parseStory (doc, cur); + } + + cur = cur->next; + } + + + + + + Get the first child node of cur. At this + point, cur points at the document root, which is + the element "story". + + + This loop iterates through the elements that are children of + "story", looking for one called "storyinfo". That + is the element that will contain the "keywords" we are + looking for. It uses the libxml string + comparison + function, xmlStrcmp. If there is a match, it calls the function parseStory. + + + + + + +void +parseStory (xmlDocPtr doc, xmlNodePtr cur) { + + cur = cur->xmlChildrenNode; + while (cur != NULL) { + if ((!xmlStrcmp(cur->name, (const xmlChar *)"keyword"))) { + printf("keyword: %s\n", xmlNodeListGetString(doc, cur->xmlChildrenNode, 1)); + } + cur = cur->next; + } + return; +} + + + + Again we get the first child node. + + + Like the loop above, we then iterate through the nodes, looking + for one that matches the element we're interested in, in this case + "keyword". + + + When we find the "keyword" element, we need to print + its contents. Remember that in XML, the text + contained within an element is a child node of that element, so we + turn to cur->xmlChildrenNode. To retrieve it, we + use the function xmlNodeListGetString, which also takes the doc pointer as an argument. In this case, we just print it out. + + + + + + + + Writing element content + Writing element content uses many of the same steps we used above + — parsing the document and walking the tree. We parse the document, + then traverse the tree to find the place we want to insert our element. For + this example, we want to again find the "storyinfo" element and + this time insert a keyword. Then we'll write the file to disk. Full code: + + + + The main difference in this example is in + parseStory: + + +void +parseStory (xmlDocPtr doc, xmlNodePtr cur, char *keyword) { + + xmlNewTextChild (cur, NULL, "keyword", keyword); + return; +} + + + + The xmlNewTextChild + function adds a new child element at the + current node pointer's location in the + tree, specificied by cur. + + + + + + Once the node has been added, we would like to write the document to + file. Is you want the element to have a namespace, you can add it here as + well. In our case, the namespace is NULL. + + xmlSaveFormatFile (docname, doc, 1); + + The first parameter is the name of the file to be written. You'll notice + it is the same as the file we just read. In this case, we just write over + the old file. The second parameter is a pointer to the xmlDoc + structure. Setting the third parameter equal to one ensures indenting on output. + + + + + + + + Writing Attribute + Writing an attribute is similar to writing text to a new element. In + this case, we'll add a reference URI to our + document. Full code:. + + A reference is a child of the story + element, so finding the place to put our new element and attribute is + simple. As soon as we do the error-checking test in our + parseDoc, we are in the right spot to add our + element. But before we do that, we need to make a declaration using a + datatype we have not seen yet: + + xmlAttrPtr newattr; + + We also need an extra xmlNodePtr: + + xmlNodePtr newnode; + + + + The rest of parseDoc is the same as before until we + check to see if our root element is story. If it is, + then we know we are at the right spot to add our element: + + + newnode = xmlNewTextChild (cur, NULL, "reference", NULL); + newattr = xmlNewProp (newnode, "uri", uri); + + + + First we add a new node at the location of the current node + pointer, cur. using the xmlNewTextChild function. + + + + + Once the node is added, the file is written to disk just as in the + previous example in which we added an element with text content. + + + + + + Sample Document + &STORY; + + + Code for Keyword Example + + &KEYWORD; + + + + Code for Add Keyword Example + + &ADDKEYWORD; + + + + Code for Add Attribute Example + + &ADDATTRIBUTE; + + +