2 * XML wrapper for libxml2
3 * Copyright (c) 2012-2013, Qualcomm Atheros, Inc.
5 * This software may be distributed under the terms of the BSD license.
6 * See README for more details.
10 #define LIBXML_VALID_ENABLED
11 #include <libxml/tree.h>
12 #include <libxml/xmlschemastypes.h>
16 #include "xml-utils.h"
31 static void add_str(void *ctx_ptr
, const char *fmt
, ...)
33 struct str_buf
*str
= ctx_ptr
;
38 n
= os_realloc(str
->buf
, str
->len
+ MAX_STR
+ 2);
44 len
= vsnprintf(str
->buf
+ str
->len
, MAX_STR
, fmt
, ap
);
49 str
->buf
[str
->len
] = '\0';
53 int xml_validate(struct xml_node_ctx
*ctx
, xml_node_t
*node
,
54 const char *xml_schema_fname
, char **ret_err
)
58 xmlSchemaParserCtxtPtr pctx
;
59 xmlSchemaValidCtxtPtr vctx
;
62 struct str_buf errors
;
67 doc
= xmlNewDoc((xmlChar
*) "1.0");
70 n
= xmlDocCopyNode((xmlNodePtr
) node
, doc
, 1);
75 xmlDocSetRootElement(doc
, n
);
77 os_memset(&errors
, 0, sizeof(errors
));
79 pctx
= xmlSchemaNewParserCtxt(xml_schema_fname
);
80 xmlSchemaSetParserErrors(pctx
, (xmlSchemaValidityErrorFunc
) add_str
,
81 (xmlSchemaValidityWarningFunc
) add_str
,
83 schema
= xmlSchemaParse(pctx
);
84 xmlSchemaFreeParserCtxt(pctx
);
86 vctx
= xmlSchemaNewValidCtxt(schema
);
87 xmlSchemaSetValidErrors(vctx
, (xmlSchemaValidityErrorFunc
) add_str
,
88 (xmlSchemaValidityWarningFunc
) add_str
,
91 ret
= xmlSchemaValidateDoc(vctx
, doc
);
92 xmlSchemaFreeValidCtxt(vctx
);
94 xmlSchemaFree(schema
);
101 *ret_err
= errors
.buf
;
107 *ret_err
= errors
.buf
;
115 int xml_validate_dtd(struct xml_node_ctx
*ctx
, xml_node_t
*node
,
116 const char *dtd_fname
, char **ret_err
)
123 struct str_buf errors
;
128 doc
= xmlNewDoc((xmlChar
*) "1.0");
131 n
= xmlDocCopyNode((xmlNodePtr
) node
, doc
, 1);
136 xmlDocSetRootElement(doc
, n
);
138 os_memset(&errors
, 0, sizeof(errors
));
140 dtd
= xmlParseDTD(NULL
, (const xmlChar
*) dtd_fname
);
146 os_memset(&vctx
, 0, sizeof(vctx
));
147 vctx
.userData
= &errors
;
148 vctx
.error
= add_str
;
149 vctx
.warning
= add_str
;
150 ret
= xmlValidateDtd(&vctx
, doc
, dtd
);
159 *ret_err
= errors
.buf
;
167 void xml_node_free(struct xml_node_ctx
*ctx
, xml_node_t
*node
)
169 xmlFreeNode((xmlNodePtr
) node
);
173 xml_node_t
* xml_node_get_parent(struct xml_node_ctx
*ctx
, xml_node_t
*node
)
175 return (xml_node_t
*) ((xmlNodePtr
) node
)->parent
;
179 xml_node_t
* xml_node_from_buf(struct xml_node_ctx
*ctx
, const char *buf
)
184 doc
= xmlParseMemory(buf
, strlen(buf
));
187 node
= xmlDocGetRootElement(doc
);
188 node
= xmlCopyNode(node
, 1);
191 return (xml_node_t
*) node
;
195 const char * xml_node_get_localname(struct xml_node_ctx
*ctx
,
198 return (const char *) ((xmlNodePtr
) node
)->name
;
202 char * xml_node_to_str(struct xml_node_ctx
*ctx
, xml_node_t
*node
)
207 xmlNodePtr n
= (xmlNodePtr
) node
;
210 doc
= xmlNewDoc((xmlChar
*) "1.0");
211 n
= xmlDocCopyNode(n
, doc
, 1);
212 xmlDocSetRootElement(doc
, n
);
213 xmlDocDumpFormatMemory(doc
, &buf
, &bufsiz
, 0);
218 if (strncmp(pos
, "<?xml", 5) == 0) {
219 pos
= strchr(pos
, '>');
222 while (pos
&& (*pos
== '\r' || *pos
== '\n'))
226 ret
= os_strdup(pos
);
237 while (pos
>= ret
&& *pos
== '\n')
245 void xml_node_detach(struct xml_node_ctx
*ctx
, xml_node_t
*node
)
247 xmlUnlinkNode((xmlNodePtr
) node
);
251 void xml_node_add_child(struct xml_node_ctx
*ctx
, xml_node_t
*parent
,
254 xmlAddChild((xmlNodePtr
) parent
, (xmlNodePtr
) child
);
258 xml_node_t
* xml_node_create_root(struct xml_node_ctx
*ctx
, const char *ns_uri
,
259 const char *ns_prefix
,
260 xml_namespace_t
**ret_ns
, const char *name
)
265 node
= xmlNewNode(NULL
, (const xmlChar
*) name
);
269 ns
= xmlNewNs(node
, (const xmlChar
*) ns_uri
,
270 (const xmlChar
*) ns_prefix
);
275 *ret_ns
= (xml_namespace_t
*) ns
;
277 return (xml_node_t
*) node
;
281 xml_node_t
* xml_node_create(struct xml_node_ctx
*ctx
, xml_node_t
*parent
,
282 xml_namespace_t
*ns
, const char *name
)
285 node
= xmlNewChild((xmlNodePtr
) parent
, (xmlNsPtr
) ns
,
286 (const xmlChar
*) name
, NULL
);
287 return (xml_node_t
*) node
;
291 xml_node_t
* xml_node_create_text(struct xml_node_ctx
*ctx
,
292 xml_node_t
*parent
, xml_namespace_t
*ns
,
293 const char *name
, const char *value
)
296 node
= xmlNewTextChild((xmlNodePtr
) parent
, (xmlNsPtr
) ns
,
297 (const xmlChar
*) name
, (const xmlChar
*) value
);
298 return (xml_node_t
*) node
;
302 xml_node_t
* xml_node_create_text_ns(struct xml_node_ctx
*ctx
,
303 xml_node_t
*parent
, const char *ns_uri
,
304 const char *name
, const char *value
)
309 node
= xmlNewTextChild((xmlNodePtr
) parent
, NULL
,
310 (const xmlChar
*) name
, (const xmlChar
*) value
);
311 ns
= xmlNewNs(node
, (const xmlChar
*) ns_uri
, NULL
);
313 return (xml_node_t
*) node
;
317 void xml_node_set_text(struct xml_node_ctx
*ctx
, xml_node_t
*node
,
320 /* TODO: escape XML special chars in value */
321 xmlNodeSetContent((xmlNodePtr
) node
, (xmlChar
*) value
);
325 int xml_node_add_attr(struct xml_node_ctx
*ctx
, xml_node_t
*node
,
326 xml_namespace_t
*ns
, const char *name
, const char *value
)
331 attr
= xmlNewNsProp((xmlNodePtr
) node
, (xmlNsPtr
) ns
,
332 (const xmlChar
*) name
,
333 (const xmlChar
*) value
);
335 attr
= xmlNewProp((xmlNodePtr
) node
, (const xmlChar
*) name
,
336 (const xmlChar
*) value
);
339 return attr
? 0 : -1;
343 char * xml_node_get_attr_value(struct xml_node_ctx
*ctx
, xml_node_t
*node
,
346 return (char *) xmlGetNoNsProp((xmlNodePtr
) node
,
347 (const xmlChar
*) name
);
351 char * xml_node_get_attr_value_ns(struct xml_node_ctx
*ctx
, xml_node_t
*node
,
352 const char *ns_uri
, char *name
)
354 return (char *) xmlGetNsProp((xmlNodePtr
) node
, (const xmlChar
*) name
,
355 (const xmlChar
*) ns_uri
);
359 void xml_node_get_attr_value_free(struct xml_node_ctx
*ctx
, char *val
)
362 xmlFree((xmlChar
*) val
);
366 xml_node_t
* xml_node_first_child(struct xml_node_ctx
*ctx
,
369 return (xml_node_t
*) ((xmlNodePtr
) parent
)->children
;
373 xml_node_t
* xml_node_next_sibling(struct xml_node_ctx
*ctx
,
376 return (xml_node_t
*) ((xmlNodePtr
) node
)->next
;
380 int xml_node_is_element(struct xml_node_ctx
*ctx
, xml_node_t
*node
)
382 return ((xmlNodePtr
) node
)->type
== XML_ELEMENT_NODE
;
386 char * xml_node_get_text(struct xml_node_ctx
*ctx
, xml_node_t
*node
)
388 if (xmlChildElementCount((xmlNodePtr
) node
) > 0)
390 return (char *) xmlNodeGetContent((xmlNodePtr
) node
);
394 void xml_node_get_text_free(struct xml_node_ctx
*ctx
, char *val
)
397 xmlFree((xmlChar
*) val
);
401 char * xml_node_get_base64_text(struct xml_node_ctx
*ctx
, xml_node_t
*node
,
408 txt
= xml_node_get_text(ctx
, node
);
412 ret
= base64_decode((unsigned char *) txt
, strlen(txt
), &len
);
415 xml_node_get_text_free(ctx
, txt
);
418 txt
= os_malloc(len
+ 1);
423 os_memcpy(txt
, ret
, len
);
429 xml_node_t
* xml_node_copy(struct xml_node_ctx
*ctx
, xml_node_t
*node
)
433 return (xml_node_t
*) xmlCopyNode((xmlNodePtr
) node
, 1);
437 struct xml_node_ctx
* xml_node_init_ctx(void *upper_ctx
,
440 struct xml_node_ctx
*xctx
;
442 xctx
= os_zalloc(sizeof(*xctx
));
445 xctx
->ctx
= upper_ctx
;
453 void xml_node_deinit_ctx(struct xml_node_ctx
*ctx
)
455 xmlSchemaCleanupTypes();