1: /*
2: * Copyright (C) 2007 Martin Willi
3: * HSR Hochschule fuer Technik Rapperswil
4: *
5: * This program is free software; you can redistribute it and/or modify it
6: * under the terms of the GNU General Public License as published by the
7: * Free Software Foundation; either version 2 of the License, or (at your
8: * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
9: *
10: * This program is distributed in the hope that it will be useful, but
11: * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12: * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13: * for more details.
14: */
15:
16: #include <string.h>
17:
18: #include "xml.h"
19:
20: #include <libxml/parser.h>
21: #include <libxml/tree.h>
22:
23:
24: typedef struct private_xml_t private_xml_t;
25:
26: /**
27: * private data of xml
28: */
29: struct private_xml_t {
30:
31: /**
32: * public functions
33: */
34: xml_t public;
35:
36: /**
37: * root node of this xml (part)
38: */
39: xmlNode *node;
40:
41: /**
42: * document, only for root xml_t
43: */
44: xmlDoc *doc;
45:
46: /**
47: * Root xml_t*
48: */
49: private_xml_t *root;
50:
51: /**
52: * number of enumerator instances
53: */
54: int enums;
55: };
56:
57: /**
58: * child element enumerator
59: */
60: typedef struct {
61: /** enumerator interface */
62: enumerator_t e;
63: /** current child context (returned to enumerate() caller) */
64: private_xml_t child;
65: /** currently processing node */
66: xmlNode *node;
67: } child_enum_t;
68:
69: METHOD(enumerator_t, child_enumerate, bool,
70: child_enum_t *e, va_list args)
71: {
72: private_xml_t **child;
73: char **name, **value;
74:
75: VA_ARGS_VGET(args, child, name, value);
76:
77: while (e->node && e->node->type != XML_ELEMENT_NODE)
78: {
79: e->node = e->node->next;
80: }
81: if (e->node)
82: {
83: xmlNode *text;
84:
85: text = e->node->children;
86: *value = NULL;
87:
88: while (text && text->type != XML_TEXT_NODE)
89: {
90: text = text->next;
91: }
92: if (text)
93: {
94: *value = text->content;
95: }
96: *name = (char*)e->node->name;
97: *child = &e->child;
98: e->child.node = e->node->children;
99: e->node = e->node->next;
100: return TRUE;
101: }
102: return FALSE;
103: }
104:
105: METHOD(xml_t, get_attribute, char*,
106: private_xml_t *this, char *name)
107: {
108: return NULL;
109: }
110:
111: METHOD(enumerator_t, child_destroy, void,
112: child_enum_t *this)
113: {
114: if (--this->child.root->enums == 0)
115: {
116: xmlFreeDoc(this->child.root->doc);
117: free(this->child.root);
118: }
119: free(this);
120: }
121:
122: METHOD(xml_t, children, enumerator_t*,
123: private_xml_t *this)
124: {
125: child_enum_t *ce;
126: INIT(ce,
127: .e = {
128: .enumerate = enumerator_enumerate_default,
129: .venumerate = _child_enumerate,
130: .destroy = _child_destroy,
131: },
132: .child = {
133: .public = {
134: .get_attribute = _get_attribute,
135: .children = _children,
136: },
137: .doc = this->doc,
138: .root = this->root,
139: },
140: .node = this->node,
141: );
142: this->root->enums++;
143: return &ce->e;
144: }
145:
146: /*
147: * see header file
148: */
149: xml_t *xml_create(char *xml)
150: {
151: private_xml_t *this;
152:
153: INIT(this,
154: .public = {
155: .get_attribute = _get_attribute,
156: .children = _children,
157: },
158: .doc = xmlReadMemory(xml, strlen(xml), NULL, NULL, 0),
159: );
160:
161: if (!this->doc)
162: {
163: free(this);
164: return NULL;
165: }
166:
167: this->node = xmlDocGetRootElement(this->doc);
168: this->root = this;
169:
170: return &this->public;
171: }
172:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>