Asterisk - The Open Source Telephony Project GIT-master-a358458
xml.c
Go to the documentation of this file.
1/*
2 * Asterisk -- An open source telephony toolkit.
3 *
4 * Copyright (C) 2008, Eliel C. Sardanons (LU1ALY) <eliels@gmail.com>
5 *
6 * See http://www.asterisk.org for more information about
7 * the Asterisk project. Please do not directly contact
8 * any of the maintainers of this project for assistance;
9 * the project provides a web site, mailing lists and IRC
10 * channels for your use.
11 *
12 * This program is free software, distributed under the terms of
13 * the GNU General Public License Version 2. See the LICENSE file
14 * at the top of the source tree.
15 */
16
17/*! \file
18 *
19 * \brief XML abstraction layer
20 *
21 * \author Eliel C. Sardanons (LU1ALY) <eliels@gmail.com>
22 */
23
24/*** MODULEINFO
25 <support_level>core</support_level>
26 ***/
27
28#include "asterisk.h"
29#include "asterisk/xml.h"
30#include "asterisk/logger.h"
31#include "asterisk/utils.h"
32#include "asterisk/autoconfig.h"
33
34#if defined(HAVE_LIBXML2)
35#include <libxml/parser.h>
36#include <libxml/tree.h>
37#include <libxml/xinclude.h>
38#include <libxml/xpath.h>
39#include <libxml/xpathInternals.h>
40/* libxml2 ast_xml implementation. */
41#ifdef HAVE_LIBXSLT
42 #include <libxslt/xsltInternals.h>
43 #include <libxslt/transform.h>
44 #include <libxslt/xsltutils.h>
45#endif /* HAVE_LIBXSLT */
46
47
48int ast_xml_init(void)
49{
50 LIBXML_TEST_VERSION
51#ifdef HAVE_LIBXSLT
52 xsltInit();
53#endif
54 return 0;
55}
56
58{
59 xmlCleanupParser();
60#ifdef HAVE_LIBXSLT
61#ifdef HAVE_LIBXSLT_CLEANUP
62 xsltCleanupGlobals();
63#else
64 xsltUninit();
65#endif
66#endif
67
68 return 0;
69}
70
71/*!
72 * \internal
73 * \brief Process XML Inclusions (XInclude).
74 *
75 * XIncludes can result in new includes being inserted, so we need to reprocess
76 * until no changes are made or we encounter an error.
77 *
78 * \param doc the document to process
79 *
80 * \retval 0 if XInclude processing concluded successfully
81 * \retval -1 if an error occurred during XInclude processing
82 */
83static int process_xincludes(xmlDoc *doc)
84{
85 int res;
86
87 do {
88 res = xmlXIncludeProcess(doc);
89 } while (res > 0);
90
91 return res;
92}
93
94struct ast_xml_doc *ast_xml_open(char *filename)
95{
96 xmlDoc *doc;
97
98 if (!filename) {
99 return NULL;
100 }
101
102 xmlSubstituteEntitiesDefault(1);
103
104 doc = xmlReadFile(filename, NULL, XML_PARSE_RECOVER);
105 if (!doc) {
106 return NULL;
107 }
108
109 /* process xinclude elements. */
110 if (process_xincludes(doc) < 0) {
111 xmlFreeDoc(doc);
112 return NULL;
113 }
114
115#ifdef HAVE_LIBXSLT
116 {
117 xsltStylesheetPtr xslt = xsltLoadStylesheetPI(doc);
118 if (xslt) {
119 xmlDocPtr tmpdoc = xsltApplyStylesheet(xslt, doc, NULL);
120 xsltFreeStylesheet(xslt);
121 xmlFreeDoc(doc);
122 if (!tmpdoc) {
123 return NULL;
124 }
125 doc = tmpdoc;
126 }
127 }
128#else /* no HAVE_LIBXSLT */
129 ast_log(LOG_NOTICE, "XSLT support not found. XML documentation may be incomplete.\n");
130#endif /* HAVE_LIBXSLT */
131
132 /* Optimize for XPath */
133 xmlXPathOrderDocElems(doc);
134
135 return (struct ast_xml_doc *) doc;
136}
137
138struct ast_xml_doc *ast_xml_new(void)
139{
140 xmlDoc *doc;
141
142 doc = xmlNewDoc((const xmlChar *) "1.0");
143 return (struct ast_xml_doc *) doc;
144}
145
146struct ast_xml_node *ast_xml_new_node(const char *name)
147{
148 xmlNode *node;
149 if (!name) {
150 return NULL;
151 }
152
153 node = xmlNewNode(NULL, (const xmlChar *) name);
154
155 return (struct ast_xml_node *) node;
156}
157
158struct ast_xml_node *ast_xml_new_child(struct ast_xml_node *parent, const char *child_name)
159{
160 xmlNode *child;
161
162 if (!parent || !child_name) {
163 return NULL;
164 }
165
166 child = xmlNewChild((xmlNode *) parent, NULL, (const xmlChar *) child_name, NULL);
167 return (struct ast_xml_node *) child;
168}
169
170struct ast_xml_node *ast_xml_add_child(struct ast_xml_node *parent, struct ast_xml_node *child)
171{
172 if (!parent || !child) {
173 return NULL;
174 }
175 return (struct ast_xml_node *) xmlAddChild((xmlNode *) parent, (xmlNode *) child);
176}
177
178struct ast_xml_node *ast_xml_add_child_list(struct ast_xml_node *parent, struct ast_xml_node *child)
179{
180 if (!parent || !child) {
181 return NULL;
182 }
183 return (struct ast_xml_node *) xmlAddChildList((xmlNode *) parent, (xmlNode *) child);
184}
185
186struct ast_xml_node *ast_xml_copy_node_list(struct ast_xml_node *list)
187{
188 if (!list) {
189 return NULL;
190 }
191 return (struct ast_xml_node *) xmlCopyNodeList((xmlNode *) list);
192}
193
194struct ast_xml_doc *ast_xml_read_memory(char *buffer, size_t size)
195{
196 xmlDoc *doc;
197
198 if (!buffer) {
199 return NULL;
200 }
201
202 if (!(doc = xmlParseMemory(buffer, (int) size))) {
203 /* process xinclude elements. */
204 if (process_xincludes(doc) < 0) {
205 xmlFreeDoc(doc);
206 return NULL;
207 }
208 }
209
210 return (struct ast_xml_doc *) doc;
211}
212
213void ast_xml_close(struct ast_xml_doc *doc)
214{
215 if (!doc) {
216 return;
217 }
218
219 xmlFreeDoc((xmlDoc *) doc);
220 doc = NULL;
221}
222
223void ast_xml_set_root(struct ast_xml_doc *doc, struct ast_xml_node *node)
224{
225 if (!doc || !node) {
226 return;
227 }
228
229 xmlDocSetRootElement((xmlDoc *) doc, (xmlNode *) node);
230}
231
232struct ast_xml_node *ast_xml_get_root(struct ast_xml_doc *doc)
233{
234 xmlNode *root_node;
235
236 if (!doc) {
237 return NULL;
238 }
239
240 root_node = xmlDocGetRootElement((xmlDoc *) doc);
241
242 return (struct ast_xml_node *) root_node;
243}
244
245void ast_xml_free_node(struct ast_xml_node *node)
246{
247 if (!node) {
248 return;
249 }
250
251 xmlFreeNode((xmlNode *) node);
252 node = NULL;
253}
254
255void ast_xml_free_attr(const char *attribute)
256{
257 if (attribute) {
258 xmlFree((char *) attribute);
259 }
260}
261
262void ast_xml_free_text(const char *text)
263{
264 if (text) {
265 xmlFree((char *) text);
266 }
267}
268
269const char *ast_xml_get_attribute(struct ast_xml_node *node, const char *attrname)
270{
271 xmlChar *attrvalue;
272
273 if (!node) {
274 return NULL;
275 }
276
277 if (!attrname) {
278 return NULL;
279 }
280
281 attrvalue = xmlGetProp((xmlNode *) node, (xmlChar *) attrname);
282
283 return (const char *) attrvalue;
284}
285
286int ast_xml_set_attribute(struct ast_xml_node *node, const char *name, const char *value)
287{
288 if (!name || !value) {
289 return -1;
290 }
291
292 if (!xmlSetProp((xmlNode *) node, (xmlChar *) name, (xmlChar *) value)) {
293 return -1;
294 }
295
296 return 0;
297}
298
299struct ast_xml_node *ast_xml_find_element(struct ast_xml_node *root_node, const char *name, const char *attrname, const char *attrvalue)
300{
301 struct ast_xml_node *cur;
302 const char *attr;
303
304 if (!root_node) {
305 return NULL;
306 }
307
308 for (cur = root_node; cur; cur = ast_xml_node_get_next(cur)) {
309 /* Check if the name matchs */
310 if (strcmp(ast_xml_node_get_name(cur), name)) {
311 continue;
312 }
313 /* We need to check for a specific attribute name? */
314 if (!attrname || !attrvalue) {
315 return cur;
316 }
317 /* Get the attribute, we need to compare it. */
318 if ((attr = ast_xml_get_attribute(cur, attrname))) {
319 /* does attribute name/value matches? */
320 if (!strcmp(attr, attrvalue)) {
321 ast_xml_free_attr(attr);
322 return cur;
323 }
324 ast_xml_free_attr(attr);
325 }
326 }
327
328 return NULL;
329}
330
331struct ast_xml_doc *ast_xml_get_doc(struct ast_xml_node *node)
332{
333 if (!node) {
334 return NULL;
335 }
336
337 return (struct ast_xml_doc *) ((xmlNode *)node)->doc;
338}
339
340struct ast_xml_ns *ast_xml_find_namespace(struct ast_xml_doc *doc, struct ast_xml_node *node, const char *ns_name) {
341 xmlNsPtr ns = xmlSearchNs((xmlDocPtr) doc, (xmlNodePtr) node, (xmlChar *) ns_name);
342 return (struct ast_xml_ns *) ns;
343}
344
345const char *ast_xml_get_ns_prefix(struct ast_xml_ns *ns)
346{
347 return (const char *) ((xmlNsPtr) ns)->prefix;
348}
349
350const char *ast_xml_get_ns_href(struct ast_xml_ns *ns)
351{
352 return (const char *) ((xmlNsPtr) ns)->href;
353}
354
355const char *ast_xml_get_text(struct ast_xml_node *node)
356{
357 if (!node) {
358 return NULL;
359 }
360
361 return (const char *) xmlNodeGetContent((xmlNode *) node);
362}
363
364void ast_xml_set_text(struct ast_xml_node *node, const char *content)
365{
366 if (!node || !content) {
367 return;
368 }
369
370 xmlNodeSetContent((xmlNode *) node, (const xmlChar *) content);
371}
372
373void ast_xml_set_name(struct ast_xml_node *node, const char *name)
374{
375 if (!node || !name) {
376 return;
377 }
378
379 xmlNodeSetName((xmlNode *) node, (const xmlChar *) name);
380}
381
382int ast_xml_doc_dump_file(FILE *output, struct ast_xml_doc *doc)
383{
384 return xmlDocDump(output, (xmlDocPtr)doc);
385}
386
387void ast_xml_doc_dump_memory(struct ast_xml_doc *doc, char **buffer, int *length)
388{
389 xmlDocDumpFormatMemory((xmlDocPtr)doc, (xmlChar **)buffer, length, 1);
390}
391
392const char *ast_xml_node_get_name(struct ast_xml_node *node)
393{
394 return (const char *) ((xmlNode *) node)->name;
395}
396
397struct ast_xml_node *ast_xml_node_get_children(struct ast_xml_node *node)
398{
399 return (struct ast_xml_node *) ((xmlNode *) node)->children;
400}
401
402struct ast_xml_node *ast_xml_node_get_next(struct ast_xml_node *node)
403{
404 return (struct ast_xml_node *) ((xmlNode *) node)->next;
405}
406
407struct ast_xml_node *ast_xml_node_get_prev(struct ast_xml_node *node)
408{
409 return (struct ast_xml_node *) ((xmlNode *) node)->prev;
410}
411
412struct ast_xml_node *ast_xml_node_get_parent(struct ast_xml_node *node)
413{
414 return (struct ast_xml_node *) ((xmlNode *) node)->parent;
415}
416
417struct ast_xml_node *ast_xml_xpath_get_first_result(struct ast_xml_xpath_results *results)
418{
419 return (struct ast_xml_node *) ((xmlXPathObjectPtr) results)->nodesetval->nodeTab[0];
420}
421
422struct ast_xml_node *ast_xml_xpath_get_result(struct ast_xml_xpath_results *results, int i)
423{
424 return (struct ast_xml_node *) ((xmlXPathObjectPtr) results)->nodesetval->nodeTab[i];
425}
426
427void ast_xml_xpath_results_free(struct ast_xml_xpath_results *results)
428{
429 if (!results) {
430 return;
431 }
432 xmlXPathFreeObject((xmlXPathObjectPtr) results);
433}
434
435int ast_xml_xpath_num_results(struct ast_xml_xpath_results *results)
436{
437 if (!results) {
438 return 0;
439 }
440 return ((xmlXPathObjectPtr) results)->nodesetval->nodeNr;
441}
442
443struct ast_xml_xpath_results *ast_xml_query(struct ast_xml_doc *doc, const char *xpath_str)
444{
445 xmlXPathContextPtr context;
446 xmlXPathObjectPtr result;
447 if (!(context = xmlXPathNewContext((xmlDoc *) doc))) {
448 ast_log(LOG_ERROR, "Could not create XPath context!\n");
449 return NULL;
450 }
451 result = xmlXPathEvalExpression((xmlChar *) xpath_str, context);
452 xmlXPathFreeContext(context);
453 if (!result) {
454 ast_log(LOG_WARNING, "Error for query: %s\n", xpath_str);
455 return NULL;
456 }
457 if (xmlXPathNodeSetIsEmpty(result->nodesetval)) {
458 xmlXPathFreeObject(result);
459 ast_debug(5, "No results for query: %s\n", xpath_str);
460 return NULL;
461 }
462 return (struct ast_xml_xpath_results *) result;
463}
464
465struct ast_xml_xpath_results *ast_xml_query_with_namespaces(struct ast_xml_doc *doc, const char *xpath_str,
466 struct ast_xml_namespace_def_vector *namespaces)
467{
468 xmlXPathContextPtr context;
469 xmlXPathObjectPtr result;
470 int i;
471
472 if (!(context = xmlXPathNewContext((xmlDoc *) doc))) {
473 ast_log(LOG_ERROR, "Could not create XPath context!\n");
474 return NULL;
475 }
476
477 for (i = 0; i < AST_VECTOR_SIZE(namespaces); i++) {
478 struct ast_xml_namespace_def ns = AST_VECTOR_GET(namespaces, i);
479 if (xmlXPathRegisterNs(context, (xmlChar *)ns.prefix,
480 (xmlChar *)ns.href) != 0) {
481 xmlXPathFreeContext(context);
482 ast_log(LOG_ERROR, "Could not register namespace %s:%s\n",
483 ns.prefix, ns.href);
484 return NULL;
485 }
486 }
487
488 result = xmlXPathEvalExpression((xmlChar *) xpath_str, context);
489 xmlXPathFreeContext(context);
490 if (!result) {
491 ast_log(LOG_WARNING, "Error for query: %s\n", xpath_str);
492 return NULL;
493 }
494 if (xmlXPathNodeSetIsEmpty(result->nodesetval)) {
495 xmlXPathFreeObject(result);
496 ast_debug(5, "No results for query: %s\n", xpath_str);
497 return NULL;
498 }
499 return (struct ast_xml_xpath_results *) result;
500}
501
502#ifdef HAVE_LIBXSLT
503struct ast_xslt_doc *ast_xslt_open(char *filename)
504{
505 xsltStylesheet *xslt;
506 xmlDoc *xml;
507
508 xmlSubstituteEntitiesDefault(1);
509
510 xml = xmlReadFile(filename, NULL, XML_PARSE_RECOVER);
511 if (!xml) {
512 return NULL;
513 }
514
515 if (process_xincludes(xml) < 0) {
516 xmlFreeDoc(xml);
517 return NULL;
518 }
519 xmlXPathOrderDocElems(xml);
520
521 if (!(xslt = xsltParseStylesheetDoc(xml))) {
522 xmlFreeDoc(xml);
523 return NULL;
524 }
525
526 return (struct ast_xslt_doc *) xslt;
527}
528
529struct ast_xslt_doc *ast_xslt_read_memory(char *buffer, size_t size)
530{
531 xsltStylesheet *xslt;
532 xmlDoc *doc;
533
534 if (!buffer) {
535 return NULL;
536 }
537
538 xmlSubstituteEntitiesDefault(1);
539
540 if (!(doc = xmlParseMemory(buffer, (int) size))) {
541 return NULL;
542 }
543
544 if (process_xincludes(doc) < 0) {
545 xmlFreeDoc(doc);
546 return NULL;
547 }
548
549 if (!(xslt = xsltParseStylesheetDoc(doc))) {
550 xmlFreeDoc(doc);
551 return NULL;
552 }
553
554 return (struct ast_xslt_doc *) xslt;
555}
556
557void ast_xslt_close(struct ast_xslt_doc *axslt)
558{
559 if (!axslt) {
560 return;
561 }
562
563 xsltFreeStylesheet((xsltStylesheet *) axslt);
564}
565
566struct ast_xml_doc *ast_xslt_apply(struct ast_xslt_doc *axslt, struct ast_xml_doc *axml, const char **params)
567{
568 xsltStylesheet *xslt = (xsltStylesheet *)axslt;
569 xmlDoc *xml = (xmlDoc *)axml;
570 xmlDoc *res;
571 xsltTransformContextPtr ctxt;
572 xmlNs *ns;
573 int options = XSLT_PARSE_OPTIONS;
574
575 /*
576 * Normally we could just call xsltApplyStylesheet() without creating
577 * our own transform context but passing parameters to it that have
578 * namespace prefixes isn't supported. Instead we have to create a
579 * transform context, iterate over the namespace declarations in the
580 * stylesheet (not the incoming xml document), add them to the
581 * transform context's xpath context, and call xsltApplyStylesheetUser.
582 *
583 * Since this is a bit involved and libxslt apparently doesn't completely
584 * clean up after itself in this situation, we'll only do that dance
585 * if there are parameters passed in. Otherwise we just call the simpler
586 * xsltApplyStylesheet.
587 *
588 */
589
590 if (!params) {
591 res = xsltApplyStylesheet(xslt, xml, params);
592 return (struct ast_xml_doc *)res;
593 }
594
595 ctxt = xsltNewTransformContext(xslt, xml);
596 xsltSetCtxtParseOptions(ctxt, options);
597
598 for (ns = xslt->doc->children->nsDef; ns; ns = ns->next) {
599 if (xmlXPathRegisterNs(ctxt->xpathCtxt, ns->prefix, ns->href) != 0) {
600 xsltFreeTransformContext(ctxt);
601 return NULL;
602 }
603 }
604
605 res = xsltApplyStylesheetUser(xslt, xml, params, NULL, NULL, ctxt);
606 xmlXPathFreeContext(ctxt->xpathCtxt);
607 ctxt->xpathCtxt = NULL;
608 xsltFreeTransformContext(ctxt);
609
610 return (struct ast_xml_doc *)res;
611}
612
613int ast_xslt_save_result_to_string(char **buffer, int *length, struct ast_xml_doc *result,
614 struct ast_xslt_doc *axslt)
615{
616 return xsltSaveResultToString((xmlChar **)buffer, length, (xmlDoc *)result, (xsltStylesheet *)axslt);
617}
618
619#endif /* defined(HAVE_LIBXSLT) */
620#endif /* defined(HAVE_LIBXML2) */
char * text
Definition: app_queue.c:1639
Asterisk main include file. File version handling, generic pbx functions.
#define ast_log
Definition: astobj2.c:42
static PGresult * result
Definition: cel_pgsql.c:84
static const char name[]
Definition: format_mp3.c:68
Support for logging to various files, console and syslog Configuration in file logger....
#define ast_debug(level,...)
Log a DEBUG message.
#define LOG_ERROR
#define LOG_NOTICE
#define LOG_WARNING
#define NULL
Definition: resample.c:96
Namespace definition.
Definition: xml.h:325
const char * prefix
Definition: xml.h:326
const char * href
Definition: xml.h:327
Definition: test_heap.c:38
int value
Definition: syslog.c:37
static struct test_options options
Utility functions.
#define AST_VECTOR_SIZE(vec)
Get the number of elements in a vector.
Definition: vector.h:609
#define AST_VECTOR_GET(vec, idx)
Get an element from a vector.
Definition: vector.h:680
struct ast_xml_node * ast_xml_copy_node_list(struct ast_xml_node *list)
Create a copy of a n ode list.
Definition: xml.c:186
struct ast_xml_node * ast_xml_add_child(struct ast_xml_node *parent, struct ast_xml_node *child)
Add a child node, to a specified parent node.
Definition: xml.c:170
struct ast_xml_node * ast_xml_node_get_children(struct ast_xml_node *node)
Get the node's children.
Definition: xml.c:397
const char * ast_xml_get_attribute(struct ast_xml_node *node, const char *attrname)
Get a node attribute by name.
Definition: xml.c:269
struct ast_xml_node * ast_xml_xpath_get_result(struct ast_xml_xpath_results *results, int i)
Return a specific result node of an XPath query.
Definition: xml.c:422
const char * ast_xml_get_text(struct ast_xml_node *node)
Get an element content string.
Definition: xml.c:355
struct ast_xml_ns * ast_xml_find_namespace(struct ast_xml_doc *doc, struct ast_xml_node *node, const char *ns_name)
Definition: xml.c:340
struct ast_xml_xpath_results * ast_xml_query_with_namespaces(struct ast_xml_doc *doc, const char *xpath_str, struct ast_xml_namespace_def_vector *namespaces)
Execute an XPath query on an XML document with namespaces.
Definition: xml.c:465
const char * ast_xml_get_ns_href(struct ast_xml_ns *ns)
Get the href of a namespace.
Definition: xml.c:350
struct ast_xml_node * ast_xml_new_child(struct ast_xml_node *parent, const char *child_name)
Add a child node inside a passed parent node.
Definition: xml.c:158
int ast_xml_xpath_num_results(struct ast_xml_xpath_results *results)
Return the number of results from an XPath query.
Definition: xml.c:435
struct ast_xml_node * ast_xml_new_node(const char *name)
Create a XML node.
Definition: xml.c:146
struct ast_xml_node * ast_xml_xpath_get_first_result(struct ast_xml_xpath_results *results)
Return the first result node of an XPath query.
Definition: xml.c:417
static int process_xincludes(xmlDoc *doc)
Definition: xml.c:83
void ast_xml_close(struct ast_xml_doc *doc)
Close an already open document and free the used structure.
Definition: xml.c:213
void ast_xml_doc_dump_memory(struct ast_xml_doc *doc, char **buffer, int *length)
Dump the specified document to a buffer.
Definition: xml.c:387
const char * ast_xml_node_get_name(struct ast_xml_node *node)
Get the name of a node.
Definition: xml.c:392
int ast_xml_finish(void)
Cleanup library allocated global data.
Definition: xml.c:57
void ast_xml_free_attr(const char *attribute)
Free an attribute returned by ast_xml_get_attribute()
Definition: xml.c:255
int ast_xml_doc_dump_file(FILE *output, struct ast_xml_doc *doc)
Dump the specified document to a file.
Definition: xml.c:382
struct ast_xml_node * ast_xml_node_get_next(struct ast_xml_node *node)
Get the next node in the same level.
Definition: xml.c:402
struct ast_xml_xpath_results * ast_xml_query(struct ast_xml_doc *doc, const char *xpath_str)
Execute an XPath query on an XML document.
Definition: xml.c:443
struct ast_xml_node * ast_xml_node_get_prev(struct ast_xml_node *node)
Get the previous node in the same leve.
Definition: xml.c:407
void ast_xml_xpath_results_free(struct ast_xml_xpath_results *results)
Free the XPath results.
Definition: xml.c:427
struct ast_xml_doc * ast_xml_new(void)
Create a XML document.
Definition: xml.c:138
int ast_xml_set_attribute(struct ast_xml_node *node, const char *name, const char *value)
Set an attribute to a node.
Definition: xml.c:286
void ast_xml_set_text(struct ast_xml_node *node, const char *content)
Set an element content string.
Definition: xml.c:364
struct ast_xml_node * ast_xml_add_child_list(struct ast_xml_node *parent, struct ast_xml_node *child)
Add a list of child nodes, to a specified parent node.
Definition: xml.c:178
void ast_xml_free_text(const char *text)
Free a content element that was returned by ast_xml_get_text()
Definition: xml.c:262
int ast_xml_init(void)
Initialize the XML library implementation. This function is used to setup everything needed to start ...
Definition: xml.c:48
void ast_xml_set_root(struct ast_xml_doc *doc, struct ast_xml_node *node)
Specify the root node of a XML document.
Definition: xml.c:223
struct ast_xml_node * ast_xml_node_get_parent(struct ast_xml_node *node)
Get the parent of a specified node.
Definition: xml.c:412
struct ast_xml_doc * ast_xml_read_memory(char *buffer, size_t size)
Open an XML document that resides in memory.
Definition: xml.c:194
struct ast_xml_node * ast_xml_find_element(struct ast_xml_node *root_node, const char *name, const char *attrname, const char *attrvalue)
Find a node element by name.
Definition: xml.c:299
struct ast_xml_doc * ast_xml_open(char *filename)
Open an XML document.
Definition: xml.c:94
void ast_xml_set_name(struct ast_xml_node *node, const char *name)
Set or reset an element's name.
Definition: xml.c:373
struct ast_xml_doc * ast_xml_get_doc(struct ast_xml_node *node)
Get the document based on a node.
Definition: xml.c:331
void ast_xml_free_node(struct ast_xml_node *node)
Free node.
Definition: xml.c:245
struct ast_xml_node * ast_xml_get_root(struct ast_xml_doc *doc)
Get the document root node.
Definition: xml.c:232
const char * ast_xml_get_ns_prefix(struct ast_xml_ns *ns)
Get the prefix of a namespace.
Definition: xml.c:345
Asterisk XML abstraction layer.