[Libvir] [PATCH] XPath accessors cleanup
Daniel Veillard
veillard at redhat.com
Fri Mar 30 09:38:21 UTC 2007
It a long time cleanup TODO, the XML parsing code of xml.c
is invaded with libxml2 specific XPath lookup code, this patch
defines 5 clearly isolated accessor functions and then fixes all
the src/xml.c code to use those. IMHO this clearly improve readability
and maintanability and I think I also found a couple of bugs in the
process.
The patch enclosed only fixes xml.c and xml.h, the next step is
to chase other modules to apply the same treatment if needed.
Daniel
--
Red Hat Virtualization group http://redhat.com/virtualization/
Daniel Veillard | virtualization library http://libvirt.org/
veillard at redhat.com | libxml GNOME XML XSLT toolkit http://xmlsoft.org/
http://veillard.com/ | Rpmfind RPM search engine http://rpmfind.net/
-------------- next part --------------
Index: src/xml.c
===================================================================
RCS file: /data/cvs/libxen/src/xml.c,v
retrieving revision 1.68
diff -u -p -r1.68 xml.c
--- src/xml.c 21 Mar 2007 15:24:56 -0000 1.68
+++ src/xml.c 30 Mar 2007 09:30:04 -0000
@@ -17,9 +17,6 @@
#ifdef WITH_XEN
#include <xs.h>
#endif
-#include <libxml/parser.h>
-#include <libxml/tree.h>
-#include <libxml/xpath.h>
#include <math.h> /* for isnan() */
#include "internal.h"
#include "hash.h"
@@ -27,6 +24,15 @@
#include "xml.h"
#include "xs_internal.h" /* for xenStoreDomainGetNetworkID */
+/**
+ * virXMLError:
+ * @conn: a connection if any
+ * @error: the error number
+ * @info: information/format string
+ * @value: extra integer parameter for the error string
+ *
+ * Report an error coming from the XML module.
+ */
static void
virXMLError(virConnectPtr conn, virErrorNumber error, const char *info, int value)
{
@@ -40,6 +46,173 @@ virXMLError(virConnectPtr conn, virError
errmsg, info, NULL, value, 0, errmsg, info, value);
}
+#ifndef PROXY
+/**
+ * virXPathString:
+ * @xpath: the XPath string to evaluate
+ * @ctxt: an XPath context
+ *
+ * Convenience function to evaluate an XPath string
+ *
+ * Returns a new string which must be deallocated by the caller or NULL
+ * if the evaluation failed.
+ */
+char *
+virXPathString(const char *xpath, xmlXPathContextPtr ctxt) {
+ xmlXPathObjectPtr obj;
+ char *ret;
+
+ if ((ctxt == NULL) || (xpath == NULL)) {
+ virXMLError(NULL, VIR_ERR_INTERNAL_ERROR,
+ "Invalid parameter to virXPathString()", 0);
+ return(NULL);
+ }
+ obj = xmlXPathEval(BAD_CAST xpath, ctxt);
+ if ((obj == NULL) || (obj->type != XPATH_STRING) ||
+ (obj->stringval == NULL) || (obj->stringval[0] == 0))
+ return(NULL);
+ ret = (char *) obj->stringval;
+ obj->stringval = NULL;
+ xmlXPathFreeObject(obj);
+ return(ret);
+}
+
+/**
+ * virXPathNumber:
+ * @xpath: the XPath string to evaluate
+ * @ctxt: an XPath context
+ * @value: the returned double value
+ *
+ * Convenience function to evaluate an XPath number
+ *
+ * Returns 0 in case of success in which case @value is set,
+ * or -1 if the evaluation failed.
+ */
+int
+virXPathNumber(const char *xpath, xmlXPathContextPtr ctxt, double *value) {
+ xmlXPathObjectPtr obj;
+
+ if ((ctxt == NULL) || (xpath == NULL) || (value == NULL)) {
+ virXMLError(NULL, VIR_ERR_INTERNAL_ERROR,
+ "Invalid parameter to virXPathNumber()", 0);
+ return(-1);
+ }
+ obj = xmlXPathEval(BAD_CAST xpath, ctxt);
+ if ((obj == NULL) || (obj->type != XPATH_NUMBER) ||
+ (isnan(obj->floatval))) {
+ xmlXPathFreeObject(obj);
+ return(-1);
+ }
+
+ *value = obj->floatval;
+ xmlXPathFreeObject(obj);
+ return(0);
+}
+
+/**
+ * virXPathBoolean:
+ * @xpath: the XPath string to evaluate
+ * @ctxt: an XPath context
+ *
+ * Convenience function to evaluate an XPath boolean
+ *
+ * Returns 0 if false, 1 if true, or -1 if the evaluation failed.
+ */
+int
+virXPathBoolean(const char *xpath, xmlXPathContextPtr ctxt) {
+ xmlXPathObjectPtr obj;
+ int ret;
+
+ if ((ctxt == NULL) || (xpath == NULL)) {
+ virXMLError(NULL, VIR_ERR_INTERNAL_ERROR,
+ "Invalid parameter to virXPathBoolean()", 0);
+ return(-1);
+ }
+ obj = xmlXPathEval(BAD_CAST xpath, ctxt);
+ if ((obj == NULL) || (obj->type != XPATH_BOOLEAN) ||
+ (obj->boolval < 0) || (obj->boolval > 1)) {
+ xmlXPathFreeObject(obj);
+ return(-1);
+ }
+ ret = obj->boolval;
+
+ xmlXPathFreeObject(obj);
+ return(ret);
+}
+
+/**
+ * virXPathNode:
+ * @xpath: the XPath string to evaluate
+ * @ctxt: an XPath context
+ *
+ * Convenience function to evaluate an XPath node set and returning
+ * only one node, the first one in the set if any
+ *
+ * Returns a pointer to the node or NULL if the evaluation failed.
+ */
+xmlNodePtr
+virXPathNode(const char *xpath, xmlXPathContextPtr ctxt) {
+ xmlXPathObjectPtr obj;
+ xmlNodePtr ret;
+
+ if ((ctxt == NULL) || (xpath == NULL)) {
+ virXMLError(NULL, VIR_ERR_INTERNAL_ERROR,
+ "Invalid parameter to virXPathNode()", 0);
+ return(NULL);
+ }
+ obj = xmlXPathEval(BAD_CAST xpath, ctxt);
+ if ((obj == NULL) || (obj->type != XPATH_NODESET) ||
+ (obj->nodesetval == NULL) || (obj->nodesetval->nodeNr <= 0) ||
+ (obj->nodesetval->nodeTab == NULL)) {
+ xmlXPathFreeObject(obj);
+ return(NULL);
+ }
+
+ ret = obj->nodesetval->nodeTab[0];
+ xmlXPathFreeObject(obj);
+ return(ret);
+}
+/**
+ * virXPathNodeSet:
+ * @xpath: the XPath string to evaluate
+ * @ctxt: an XPath context
+ * @list: the returned list of nodes (or NULL if only count matters)
+ *
+ * Convenience function to evaluate an XPath node set
+ *
+ * Returns the number of nodes found in which case @list is set (and
+ * must be freed) or -1 if the evaluation failed.
+ */
+int
+virXPathNodeSet(const char *xpath, xmlXPathContextPtr ctxt, xmlNodePtr **list) {
+ xmlXPathObjectPtr obj;
+ int ret;
+
+ if ((ctxt == NULL) || (xpath == NULL)) {
+ virXMLError(NULL, VIR_ERR_INTERNAL_ERROR,
+ "Invalid parameter to virXPathNodeSet()", 0);
+ return(-1);
+ }
+ obj = xmlXPathEval(BAD_CAST xpath, ctxt);
+ if ((obj == NULL) || (obj->type != XPATH_NODESET) ||
+ (obj->nodesetval == NULL) || (obj->nodesetval->nodeNr <= 0) ||
+ (obj->nodesetval->nodeTab == NULL)) {
+ xmlXPathFreeObject(obj);
+ if (list != NULL)
+ *list = NULL;
+ return(-1);
+ }
+
+ if (list != NULL) {
+ *list = obj->nodesetval->nodeTab;
+ obj->nodesetval->nodeTab = NULL;
+ }
+ ret = obj->nodesetval->nodeNr;
+ xmlXPathFreeObject(obj);
+ return(ret);
+}
+#endif /* !PROXY */
+
/**
* virBufferGrow:
* @buf: the buffer
@@ -360,12 +533,12 @@ static int virDomainParseXMLGraphicsDesc
static int
virDomainParseXMLOSDescHVM(virConnectPtr conn, xmlNodePtr node, virBufferPtr buf, xmlXPathContextPtr ctxt, int vcpus, int xendConfigVersion)
{
- xmlXPathObjectPtr obj = NULL;
xmlNodePtr cur, txt;
xmlChar *type = NULL;
xmlChar *loader = NULL;
xmlChar *boot_dev = NULL;
int res;
+ char *str;
cur = node->children;
while (cur != NULL) {
@@ -403,16 +576,13 @@ virDomainParseXMLOSDescHVM(virConnectPtr
}
/* get the device emulation model */
- obj = xmlXPathEval(BAD_CAST "string(/domain/devices/emulator[1])", ctxt);
- if ((obj == NULL) || (obj->type != XPATH_STRING) ||
- (obj->stringval == NULL) || (obj->stringval[0] == 0)) {
+ str = virXPathString("string(/domain/devices/emulator[1])", ctxt);
+ if (str == NULL) {
virXMLError(conn, VIR_ERR_NO_KERNEL, NULL, 0); /* TODO: error */
goto error;
}
- virBufferVSprintf(buf, "(device_model '%s')",
- (const char *) obj->stringval);
- xmlXPathFreeObject(obj);
- obj = NULL;
+ virBufferVSprintf(buf, "(device_model '%s')", str);
+ xmlFree(str);
virBufferVSprintf(buf, "(vcpus %d)", vcpus);
@@ -429,102 +599,78 @@ virDomainParseXMLOSDescHVM(virConnectPtr
}
/* get the 1st floppy device file */
- obj = xmlXPathEval(BAD_CAST "/domain/devices/disk[@device='floppy' and target/@dev='fda']/source", ctxt);
- if ((obj != NULL) && (obj->type == XPATH_NODESET) &&
- (obj->nodesetval != NULL) && (obj->nodesetval->nodeNr == 1)) {
- cur = obj->nodesetval->nodeTab[0];
- virBufferVSprintf(buf, "(fda '%s')",
- (const char *) xmlGetProp(cur, BAD_CAST "file"));
- cur = NULL;
- }
- if (obj) {
- xmlXPathFreeObject(obj);
- obj = NULL;
+ cur = virXPathNode(
+ "/domain/devices/disk[@device='floppy' and target/@dev='fda']/source",
+ ctxt);
+ if (cur != NULL) {
+ xmlChar *fdfile;
+
+ fdfile = xmlGetProp(cur, BAD_CAST "file");
+ if (fdfile != NULL) {
+ virBufferVSprintf(buf, "(fda '%s')", fdfile);
+ free(fdfile);
+ }
}
/* get the 2nd floppy device file */
- obj = xmlXPathEval(BAD_CAST "/domain/devices/disk[@device='floppy' and target/@dev='fdb']/source", ctxt);
- if ((obj != NULL) && (obj->type == XPATH_NODESET) &&
- (obj->nodesetval != NULL) && (obj->nodesetval->nodeNr == 1)) {
- xmlChar *fdfile = NULL;
- cur = obj->nodesetval->nodeTab[0];
+ cur = virXPathNode(
+ "/domain/devices/disk[@device='floppy' and target/@dev='fdb']/source",
+ ctxt);
+ if (cur != NULL) {
+ xmlChar *fdfile;
+
fdfile = xmlGetProp(cur, BAD_CAST "file");
- virBufferVSprintf(buf, "(fdb '%s')",
- (const char *) fdfile);
- xmlFree(fdfile);
- cur = NULL;
- }
- if (obj) {
- xmlXPathFreeObject(obj);
- obj = NULL;
+ if (fdfile != NULL) {
+ virBufferVSprintf(buf, "(fdb '%s')", fdfile);
+ free(fdfile);
+ }
}
/* get the cdrom device file */
/* Only XenD <= 3.0.2 wants cdrom config here */
if (xendConfigVersion == 1) {
- obj = xmlXPathEval(BAD_CAST "/domain/devices/disk[@device='cdrom' and target/@dev='hdc']/source", ctxt);
- if ((obj != NULL) && (obj->type == XPATH_NODESET) &&
- (obj->nodesetval != NULL) && (obj->nodesetval->nodeNr == 1)) {
- xmlChar *cdfile = NULL;
- cur = obj->nodesetval->nodeTab[0];
+ cur = virXPathNode(
+ "/domain/devices/disk[@device='cdrom' and target/@dev='hdc']/source",
+ ctxt);
+ if (cur != NULL) {
+ xmlChar *cdfile;
+
cdfile = xmlGetProp(cur, BAD_CAST "file");
- virBufferVSprintf(buf, "(cdrom '%s')",
- (const char *)cdfile);
- xmlFree(cdfile);
- cur = NULL;
- }
- if (obj) {
- xmlXPathFreeObject(obj);
- obj = NULL;
+ if (cdfile != NULL) {
+ virBufferVSprintf(buf, "(cdrom '%s')",
+ (const char *)cdfile);
+ xmlFree(cdfile);
+ }
}
}
- obj = xmlXPathEval(BAD_CAST "/domain/features/acpi", ctxt);
- if ((obj != NULL) && (obj->type == XPATH_NODESET) &&
- (obj->nodesetval != NULL) && (obj->nodesetval->nodeNr == 1)) {
+ if (virXPathNode("/domain/features/acpi", ctxt) != NULL)
virBufferAdd(buf, "(acpi 1)", 8);
- }
- if (obj)
- xmlXPathFreeObject(obj);
- obj = xmlXPathEval(BAD_CAST "/domain/features/apic", ctxt);
- if ((obj != NULL) && (obj->type == XPATH_NODESET) &&
- (obj->nodesetval != NULL) && (obj->nodesetval->nodeNr == 1)) {
+ if (virXPathNode("/domain/features/apic", ctxt) != NULL)
virBufferAdd(buf, "(apic 1)", 8);
- }
- if (obj)
- xmlXPathFreeObject(obj);
- obj = xmlXPathEval(BAD_CAST "/domain/features/pae", ctxt);
- if ((obj != NULL) && (obj->type == XPATH_NODESET) &&
- (obj->nodesetval != NULL) && (obj->nodesetval->nodeNr == 1)) {
+ if (virXPathNode("/domain/features/pae", ctxt) != NULL)
virBufferAdd(buf, "(pae 1)", 7);
- }
- if (obj)
- xmlXPathFreeObject(obj);
- obj = NULL;
}
- obj = xmlXPathEval(BAD_CAST "count(domain/devices/console) > 0", ctxt);
- if ((obj == NULL) || (obj->type != XPATH_BOOLEAN)) {
+ res = virXPathBoolean("count(domain/devices/console) > 0", ctxt);
+ if (res < 0) {
virXMLError(conn, VIR_ERR_XML_ERROR, NULL, 0);
goto error;
}
- if (obj->boolval) {
+ if (res) {
virBufferAdd(buf, "(serial pty)", 12);
}
- xmlXPathFreeObject(obj);
- obj = NULL;
/* Is a graphics device specified? */
- obj = xmlXPathEval(BAD_CAST "/domain/devices/graphics[1]", ctxt);
- if ((obj != NULL) && (obj->type == XPATH_NODESET) &&
- (obj->nodesetval != NULL) && (obj->nodesetval->nodeNr > 0)) {
- res = virDomainParseXMLGraphicsDescImage(conn, obj->nodesetval->nodeTab[0], buf, xendConfigVersion);
+ cur = virXPathNode("/domain/devices/graphics[1]", ctxt);
+ if (cur != NULL) {
+ res = virDomainParseXMLGraphicsDescImage(conn, cur, buf,
+ xendConfigVersion);
if (res != 0) {
goto error;
}
}
- xmlXPathFreeObject(obj);
virBufferAdd(buf, "))", 2);
@@ -535,8 +681,6 @@ virDomainParseXMLOSDescHVM(virConnectPtr
error:
if (boot_dev)
xmlFree(boot_dev);
- if (obj != NULL)
- xmlXPathFreeObject(obj);
return(-1);
}
@@ -559,7 +703,6 @@ static int
virDomainParseXMLOSDescPV(virConnectPtr conn, xmlNodePtr node, virBufferPtr buf, xmlXPathContextPtr ctxt, int xendConfigVersion)
{
xmlNodePtr cur, txt;
- xmlXPathObjectPtr obj = NULL;
const xmlChar *type = NULL;
const xmlChar *root = NULL;
const xmlChar *kernel = NULL;
@@ -626,15 +769,14 @@ virDomainParseXMLOSDescPV(virConnectPtr
/* Is a graphics device specified? */
/* Old style config before merge of PVFB */
if (xendConfigVersion < 3) {
- obj = xmlXPathEval(BAD_CAST "/domain/devices/graphics[1]", ctxt);
- if ((obj != NULL) && (obj->type == XPATH_NODESET) &&
- (obj->nodesetval != NULL) && (obj->nodesetval->nodeNr > 0)) {
- res = virDomainParseXMLGraphicsDescImage(conn, obj->nodesetval->nodeTab[0], buf, xendConfigVersion);
+ cur = virXPathNode("/domain/devices/graphics[1]", ctxt);
+ if (cur != NULL) {
+ res = virDomainParseXMLGraphicsDescImage(conn, cur, buf,
+ xendConfigVersion);
if (res != 0) {
goto error;
}
}
- xmlXPathFreeObject(obj);
}
error:
@@ -958,14 +1100,16 @@ virDomainParseXMLDesc(virConnectPtr conn
virBuffer buf;
xmlChar *prop;
xmlParserCtxtPtr pctxt;
- xmlXPathObjectPtr obj = NULL;
- xmlXPathObjectPtr tmpobj = NULL;
xmlXPathContextPtr ctxt = NULL;
int i, res;
int bootloader = 0;
int hvm = 0;
unsigned int vcpus = 1;
unsigned long mem = 0, max_mem = 0;
+ char *str;
+ double f;
+ xmlNodePtr *nodes;
+ int nb_nodes;
if (name != NULL)
*name = NULL;
@@ -1012,117 +1156,90 @@ virDomainParseXMLDesc(virConnectPtr conn
/*
* extract some of the basics, name, memory, cpus ...
*/
- obj = xmlXPathEval(BAD_CAST "string(/domain/name[1])", ctxt);
- if ((obj == NULL) || (obj->type != XPATH_STRING) ||
- (obj->stringval == NULL) || (obj->stringval[0] == 0)) {
- virXMLError(conn, VIR_ERR_NO_NAME, xmldesc, 0);
- goto error;
- }
- virBufferVSprintf(&buf, "(name '%s')", obj->stringval);
- nam = strdup((const char *) obj->stringval);
+ nam = virXPathString("string(/domain/name[1])", ctxt);
if (nam == NULL) {
- virXMLError(conn, VIR_ERR_NO_MEMORY, "copying name", 0);
+ virXMLError(conn, VIR_ERR_NO_NAME, xmldesc, 0);
goto error;
}
- xmlXPathFreeObject(obj);
+ virBufferVSprintf(&buf, "(name '%s')", nam);
- obj = xmlXPathEval(BAD_CAST "number(/domain/memory[1])", ctxt);
- if ((obj == NULL) || (obj->type != XPATH_NUMBER) ||
- (isnan(obj->floatval)) || (obj->floatval < MIN_XEN_GUEST_SIZE * 1024)) {
+ if ((virXPathNumber("number(/domain/memory[1])", ctxt, &f) < 0) ||
+ (f < MIN_XEN_GUEST_SIZE * 1024)) {
max_mem = 128;
} else {
- max_mem = (obj->floatval / 1024);
+ max_mem = (f / 1024);
}
- xmlXPathFreeObject(obj);
- obj = xmlXPathEval(BAD_CAST "number(/domain/currentMemory[1])", ctxt);
- if ((obj == NULL) || (obj->type != XPATH_NUMBER) ||
- (isnan(obj->floatval)) || (obj->floatval < MIN_XEN_GUEST_SIZE * 1024)) {
+
+ if ((virXPathNumber("number(/domain/currentMemory[1])", ctxt, &f) < 0) ||
+ (f < MIN_XEN_GUEST_SIZE * 1024)) {
mem = max_mem;
} else {
- mem = (obj->floatval / 1024);
+ mem = (f / 1024);
if (mem > max_mem) {
max_mem = mem;
}
}
- xmlXPathFreeObject(obj);
virBufferVSprintf(&buf, "(memory %lu)(maxmem %lu)", mem, max_mem);
- obj = xmlXPathEval(BAD_CAST "number(/domain/vcpu[1])", ctxt);
- if ((obj != NULL) && (obj->type == XPATH_NUMBER) &&
- (!isnan(obj->floatval)) && (obj->floatval > 0)) {
- vcpus = (unsigned int) obj->floatval;
+ if ((virXPathNumber("number(/domain/vcpu[1])", ctxt, &f) == 0) &&
+ (f > 0)) {
+ vcpus = (unsigned int) f;
}
virBufferVSprintf(&buf, "(vcpus %u)", vcpus);
- xmlXPathFreeObject(obj);
- obj = xmlXPathEval(BAD_CAST "string(/domain/uuid[1])", ctxt);
- if ((obj == NULL) || ((obj->type == XPATH_STRING) &&
- (obj->stringval != NULL) && (obj->stringval[0] != 0))) {
- virBufferVSprintf(&buf, "(uuid '%s')", obj->stringval);
+ str = virXPathString("string(/domain/uuid[1])", ctxt);
+ if (str != NULL) {
+ virBufferVSprintf(&buf, "(uuid '%s')", str);
+ free(str);
}
- xmlXPathFreeObject(obj);
- obj = xmlXPathEval(BAD_CAST "string(/domain/bootloader[1])", ctxt);
- if ((obj != NULL) && (obj->type == XPATH_STRING) &&
- (obj->stringval != NULL) && (obj->stringval[0] != 0)) {
- virBufferVSprintf(&buf, "(bootloader '%s')", obj->stringval);
+ str = virXPathString("string(/domain/bootloader[1])", ctxt);
+ if (str != NULL) {
+ virBufferVSprintf(&buf, "(bootloader '%s')", str);
/*
* if using pygrub, the kernel and initrd strings are not
* significant and should be discarded
*/
- if (xmlStrstr(obj->stringval, BAD_CAST "pygrub"))
+ if (strstr(str, "pygrub"))
bootloader = 2;
else
bootloader = 1;
+ free(str);
}
- xmlXPathFreeObject(obj);
- obj = xmlXPathEval(BAD_CAST "string(/domain/on_poweroff[1])", ctxt);
- if ((obj != NULL) && (obj->type == XPATH_STRING) &&
- (obj->stringval != NULL) && (obj->stringval[0] != 0)) {
- virBufferVSprintf(&buf, "(on_poweroff '%s')", obj->stringval);
+ str = virXPathString("string(/domain/on_poweroff[1])", ctxt);
+ if (str != NULL) {
+ virBufferVSprintf(&buf, "(on_poweroff '%s')", str);
+ free(str);
}
- xmlXPathFreeObject(obj);
- obj = xmlXPathEval(BAD_CAST "string(/domain/on_reboot[1])", ctxt);
- if ((obj != NULL) && (obj->type == XPATH_STRING) &&
- (obj->stringval != NULL) && (obj->stringval[0] != 0)) {
- virBufferVSprintf(&buf, "(on_reboot '%s')", obj->stringval);
+ str = virXPathString("string(/domain/on_reboot[1])", ctxt);
+ if (str != NULL) {
+ virBufferVSprintf(&buf, "(on_reboot '%s')", str);
+ free(str);
}
- xmlXPathFreeObject(obj);
- obj = xmlXPathEval(BAD_CAST "string(/domain/on_crash[1])", ctxt);
- if ((obj != NULL) && (obj->type == XPATH_STRING) &&
- (obj->stringval != NULL) && (obj->stringval[0] != 0)) {
- virBufferVSprintf(&buf, "(on_crash '%s')", obj->stringval);
+ str = virXPathString("string(/domain/on_crash[1])", ctxt);
+ if (str != NULL) {
+ virBufferVSprintf(&buf, "(on_crash '%s')", str);
+ free(str);
}
- xmlXPathFreeObject(obj);
if (bootloader != 2) {
- obj = xmlXPathEval(BAD_CAST "/domain/os[1]", ctxt);
- if ((obj != NULL) && (obj->type == XPATH_NODESET) &&
- (obj->nodesetval != NULL) && (obj->nodesetval->nodeNr == 1)) {
+ if ((node = virXPathNode("/domain/os[1]", ctxt)) != NULL) {
/* Analyze of the os description, based on HVM or PV. */
- tmpobj = xmlXPathEval(BAD_CAST "string(/domain/os/type[1])", ctxt);
- if ((tmpobj != NULL) &&
- ((tmpobj->type != XPATH_STRING) || (tmpobj->stringval == NULL)
- || (tmpobj->stringval[0] == 0))) {
- xmlXPathFreeObject(tmpobj);
- virXMLError(conn, VIR_ERR_OS_TYPE, nam, 0);
- goto error;
- }
+ str = virXPathString("string(/domain/os/type[1])", ctxt);
- if ((tmpobj == NULL)
- || !xmlStrEqual(tmpobj->stringval, BAD_CAST "hvm")) {
- res = virDomainParseXMLOSDescPV(conn, obj->nodesetval->nodeTab[0],
+ if ((str == NULL) || (strcmp(str, "hvm"))) {
+ res = virDomainParseXMLOSDescPV(conn, node,
&buf, ctxt, xendConfigVersion);
} else {
hvm = 1;
- res = virDomainParseXMLOSDescHVM(conn, obj->nodesetval->nodeTab[0],
- &buf, ctxt, vcpus, xendConfigVersion);
+ res = virDomainParseXMLOSDescHVM(conn, node, &buf, ctxt,
+ vcpus, xendConfigVersion);
}
- xmlXPathFreeObject(tmpobj);
+ if (str != NULL) free(str);
if (res != 0)
goto error;
@@ -1130,49 +1247,49 @@ virDomainParseXMLDesc(virConnectPtr conn
virXMLError(conn, VIR_ERR_NO_OS, nam, 0);
goto error;
}
- xmlXPathFreeObject(obj);
}
/* analyze of the devices */
- obj = xmlXPathEval(BAD_CAST "/domain/devices/disk", ctxt);
- if ((obj != NULL) && (obj->type == XPATH_NODESET) &&
- (obj->nodesetval != NULL) && (obj->nodesetval->nodeNr >= 0)) {
- for (i = 0; i < obj->nodesetval->nodeNr; i++) {
- res = virDomainParseXMLDiskDesc(conn, obj->nodesetval->nodeTab[i], &buf, hvm, xendConfigVersion);
+ nb_nodes = virXPathNodeSet("/domain/devices/disk", ctxt, &nodes);
+ if (nb_nodes > 0) {
+ for (i = 0; i < nb_nodes; i++) {
+ res = virDomainParseXMLDiskDesc(conn, nodes[i], &buf,
+ hvm, xendConfigVersion);
if (res != 0) {
+ free(nodes);
goto error;
}
}
+ free(nodes);
}
- xmlXPathFreeObject(obj);
- obj = xmlXPathEval(BAD_CAST "/domain/devices/interface", ctxt);
- if ((obj != NULL) && (obj->type == XPATH_NODESET) &&
- (obj->nodesetval != NULL) && (obj->nodesetval->nodeNr >= 0)) {
- for (i = 0; i < obj->nodesetval->nodeNr; i++) {
+ nb_nodes = virXPathNodeSet("/domain/devices/interface", ctxt, &nodes);
+ if (nb_nodes > 0) {
+ for (i = 0; i < nb_nodes; i++) {
virBufferAdd(&buf, "(device ", 8);
- res = virDomainParseXMLIfDesc(conn, obj->nodesetval->nodeTab[i], &buf, hvm);
+ res = virDomainParseXMLIfDesc(conn, nodes[i], &buf, hvm);
if (res != 0) {
+ free(nodes);
goto error;
}
virBufferAdd(&buf, ")", 1);
}
+ free(nodes);
}
- xmlXPathFreeObject(obj);
/* New style PVFB config - 3.0.4 merge */
if (xendConfigVersion >= 3 && !hvm) {
- obj = xmlXPathEval(BAD_CAST "/domain/devices/graphics", ctxt);
- if ((obj != NULL) && (obj->type == XPATH_NODESET) &&
- (obj->nodesetval != NULL) && (obj->nodesetval->nodeNr >= 0)) {
- for (i = 0; i < obj->nodesetval->nodeNr; i++) {
- res = virDomainParseXMLGraphicsDescVFB(conn, obj->nodesetval->nodeTab[i], &buf);
+ nb_nodes = virXPathNodeSet("/domain/devices/graphics", ctxt, &nodes);
+ if (nb_nodes > 0) {
+ for (i = 0; i < nb_nodes; i++) {
+ res = virDomainParseXMLGraphicsDescVFB(conn, nodes[i], &buf);
if (res != 0) {
+ free(nodes);
goto error;
}
}
+ free(nodes);
}
- xmlXPathFreeObject(obj);
}
@@ -1195,8 +1312,6 @@ virDomainParseXMLDesc(virConnectPtr conn
free(nam);
if (name != NULL)
*name = NULL;
- if (obj != NULL)
- xmlXPathFreeObject(obj);
if (ctxt != NULL)
xmlXPathFreeContext(ctxt);
if (xml != NULL)
Index: src/xml.h
===================================================================
RCS file: /data/cvs/libxen/src/xml.h,v
retrieving revision 1.13
diff -u -p -r1.13 xml.h
--- src/xml.h 16 Mar 2007 15:03:21 -0000 1.13
+++ src/xml.h 30 Mar 2007 09:30:04 -0000
@@ -1,5 +1,5 @@
/*
- * internal.h: internal definitions just used by code from the library
+ * xml.h: internal definitions used for XML parsing routines.
*/
#ifndef __VIR_XML_H__
@@ -8,6 +8,9 @@
#include "libvirt/libvirt.h"
#include "internal.h"
+#include <libxml/parser.h>
+#include <libxml/tree.h>
+#include <libxml/xpath.h>
#ifdef __cplusplus
extern "C" {
#endif
@@ -32,6 +35,19 @@ int virBufferVSprintf(virBufferPtr buf,
ATTRIBUTE_FORMAT(printf, 2, 3);
int virBufferStrcat(virBufferPtr buf, ...);
+int virXPathBoolean (const char *xpath,
+ xmlXPathContextPtr ctxt);
+char * virXPathString (const char *xpath,
+ xmlXPathContextPtr ctxt);
+int virXPathNumber (const char *xpath,
+ xmlXPathContextPtr ctxt,
+ double *value);
+xmlNodePtr virXPathNode (const char *xpath,
+ xmlXPathContextPtr ctxt);
+int virXPathNodeSet (const char *xpath,
+ xmlXPathContextPtr ctxt,
+ xmlNodePtr **list);
+
char *virDomainParseXMLDesc(virConnectPtr conn, const char *xmldesc, char **name, int xendConfigVersion);
unsigned char *virParseUUID(char **ptr, const char *uuid);
char *virParseXMLDevice(virConnectPtr conn, char *xmldesc, int hvm, int xendConfigVersion);
More information about the libvir-list
mailing list