[libvirt] [PATCH] Detailed XML errors version 4

Richard W.M. Jones rjones at redhat.com
Wed Jul 30 16:53:18 UTC 2008


Updated to report only the first error, as suggested by Dan.

Rich.

-- 
Richard Jones, Emerging Technologies, Red Hat  http://et.redhat.com/~rjones
virt-p2v converts physical machines to virtual machines.  Boot with a
live CD or over the network (PXE) and turn machines into Xen guests.
http://et.redhat.com/~rjones/virt-p2v
-------------- next part --------------
Index: src/domain_conf.c
===================================================================
RCS file: /data/cvs/libvirt/src/domain_conf.c,v
retrieving revision 1.10
diff -u -r1.10 domain_conf.c
--- src/domain_conf.c	28 Jul 2008 14:06:54 -0000	1.10
+++ src/domain_conf.c	30 Jul 2008 16:52:54 -0000
@@ -1838,32 +1838,65 @@
     return NULL;
 }
 
+/* Called from SAX on parsing errors in the XML. */
+static void
+catchXMLError (void *ctx, const char *msg ATTRIBUTE_UNUSED, ...)
+{
+    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
+
+    if (ctxt) {
+        virConnectPtr conn = ctxt->_private;
+
+        if (conn &&
+            conn->err.code == VIR_ERR_NONE &&
+            ctxt->lastError.level == XML_ERR_FATAL &&
+            ctxt->lastError.message != NULL) {
+            virDomainReportError (conn, VIR_ERR_XML_DETAIL,
+                                  _("at line %d: %s"),
+                                  ctxt->lastError.line,
+                                  ctxt->lastError.message);
+        }
+    }
+}
 
 virDomainDefPtr virDomainDefParseString(virConnectPtr conn,
                                         virCapsPtr caps,
                                         const char *xmlStr)
 {
-    xmlDocPtr xml;
+    xmlParserCtxtPtr pctxt;
+    xmlDocPtr xml = NULL;
     xmlNodePtr root;
     virDomainDefPtr def = NULL;
 
-    if (!(xml = xmlReadDoc(BAD_CAST xmlStr, "domain.xml", NULL,
-                           XML_PARSE_NOENT | XML_PARSE_NONET |
-                           XML_PARSE_NOERROR | XML_PARSE_NOWARNING))) {
-        virDomainReportError(conn, VIR_ERR_XML_ERROR, NULL);
-        return NULL;
+    /* Set up a parser context so we can catch the details of XML errors. */
+    pctxt = xmlNewParserCtxt ();
+    if (!pctxt || !pctxt->sax)
+        goto cleanup;
+    pctxt->sax->error = catchXMLError;
+    pctxt->_private = conn;
+
+    if (conn) virResetError (&conn->err);
+    xml = xmlCtxtReadDoc (pctxt, BAD_CAST xmlStr, "domain.xml", NULL,
+                          XML_PARSE_NOENT | XML_PARSE_NONET |
+                          XML_PARSE_NOWARNING);
+    if (!xml) {
+        if (conn && conn->err.code == VIR_ERR_NONE)
+              virDomainReportError(conn, VIR_ERR_XML_ERROR,
+                                   _("failed to parse xml document"));
+        goto cleanup;
     }
 
     if ((root = xmlDocGetRootElement(xml)) == NULL) {
         virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
                               "%s", _("missing root element"));
-        xmlFreeDoc(xml);
-        return NULL;
+        goto cleanup;
     }
 
     def = virDomainDefParseNode(conn, caps, xml, root);
 
-    xmlFreeDoc(xml);
+cleanup:
+    xmlFreeParserCtxt (pctxt);
+    xmlFreeDoc (xml);
     return def;
 }
 
@@ -1871,27 +1904,40 @@
                                       virCapsPtr caps,
                                       const char *filename)
 {
-    xmlDocPtr xml;
+    xmlParserCtxtPtr pctxt;
+    xmlDocPtr xml = NULL;
     xmlNodePtr root;
     virDomainDefPtr def = NULL;
 
-    if (!(xml = xmlReadFile(filename, NULL,
-                            XML_PARSE_NOENT | XML_PARSE_NONET |
-                            XML_PARSE_NOERROR | XML_PARSE_NOWARNING))) {
-        virDomainReportError(conn, VIR_ERR_XML_ERROR, NULL);
-        return NULL;
+    /* Set up a parser context so we can catch the details of XML errors. */
+    pctxt = xmlNewParserCtxt ();
+    if (!pctxt || !pctxt->sax)
+        goto cleanup;
+    pctxt->sax->error = catchXMLError;
+    pctxt->_private = conn;
+
+    if (conn) virResetError (&conn->err);
+    xml = xmlCtxtReadFile (pctxt, filename, NULL,
+                           XML_PARSE_NOENT | XML_PARSE_NONET |
+                           XML_PARSE_NOWARNING);
+    if (!xml) {
+        if (conn && conn->err.code == VIR_ERR_NONE)
+              virDomainReportError(conn, VIR_ERR_XML_ERROR,
+                                   _("failed to parse xml document"));
+        goto cleanup;
     }
 
     if ((root = xmlDocGetRootElement(xml)) == NULL) {
         virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
                               "%s", _("missing root element"));
-        xmlFreeDoc(xml);
-        return NULL;
+        goto cleanup;
     }
 
     def = virDomainDefParseNode(conn, caps, xml, root);
 
-    xmlFreeDoc(xml);
+cleanup:
+    xmlFreeParserCtxt (pctxt);
+    xmlFreeDoc (xml);
     return def;
 }
 
Index: src/network_conf.c
===================================================================
RCS file: /data/cvs/libvirt/src/network_conf.c,v
retrieving revision 1.3
diff -u -r1.3 network_conf.c
--- src/network_conf.c	25 Jul 2008 14:27:25 -0000	1.3
+++ src/network_conf.c	30 Jul 2008 16:52:54 -0000
@@ -348,57 +348,104 @@
     return NULL;
 }
 
+/* Called from SAX on parsing errors in the XML. */
+static void
+catchXMLError (void *ctx, const char *msg ATTRIBUTE_UNUSED, ...)
+{
+    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
+
+    if (ctxt) {
+        virConnectPtr conn = ctxt->_private;
+
+        if (conn &&
+            conn->err.code == VIR_ERR_NONE &&
+            ctxt->lastError.level == XML_ERR_FATAL &&
+            ctxt->lastError.message != NULL) {
+            virNetworkReportError (conn, VIR_ERR_XML_DETAIL,
+                                   _("at line %d: %s"),
+                                   ctxt->lastError.line,
+                                   ctxt->lastError.message);
+        }
+    }
+}
+
 virNetworkDefPtr virNetworkDefParseString(virConnectPtr conn,
                                           const char *xmlStr)
 {
-    xmlDocPtr xml;
+    xmlParserCtxtPtr pctxt;
+    xmlDocPtr xml = NULL;
     xmlNodePtr root;
-    virNetworkDefPtr def;
+    virNetworkDefPtr def = NULL;
 
-    if (!(xml = xmlReadDoc(BAD_CAST xmlStr, "network.xml", NULL,
-                           XML_PARSE_NOENT | XML_PARSE_NONET |
-                           XML_PARSE_NOERROR | XML_PARSE_NOWARNING))) {
-        virNetworkReportError(conn, VIR_ERR_XML_ERROR, NULL);
-        return NULL;
+    /* Set up a parser context so we can catch the details of XML errors. */
+    pctxt = xmlNewParserCtxt ();
+    if (!pctxt || !pctxt->sax)
+        goto cleanup;
+    pctxt->sax->error = catchXMLError;
+    pctxt->_private = conn;
+
+    if (conn) virResetError (&conn->err);
+    xml = xmlCtxtReadDoc (pctxt, BAD_CAST xmlStr, "network.xml", NULL,
+                          XML_PARSE_NOENT | XML_PARSE_NONET |
+                          XML_PARSE_NOWARNING);
+    if (!xml) {
+        if (conn && conn->err.code == VIR_ERR_NONE)
+              virNetworkReportError(conn, VIR_ERR_XML_ERROR,
+                                    _("failed to parse xml document"));
+        goto cleanup;
     }
 
     if ((root = xmlDocGetRootElement(xml)) == NULL) {
         virNetworkReportError(conn, VIR_ERR_INTERNAL_ERROR,
                               "%s", _("missing root element"));
-        xmlFreeDoc(xml);
-        return NULL;
+        goto cleanup;
     }
 
     def = virNetworkDefParseNode(conn, xml, root);
 
-    xmlFreeDoc(xml);
+cleanup:
+    xmlFreeParserCtxt (pctxt);
+    xmlFreeDoc (xml);
     return def;
 }
 
 virNetworkDefPtr virNetworkDefParseFile(virConnectPtr conn,
                                         const char *filename)
 {
-    xmlDocPtr xml;
+    xmlParserCtxtPtr pctxt;
+    xmlDocPtr xml = NULL;
     xmlNodePtr root;
-    virNetworkDefPtr def;
+    virNetworkDefPtr def = NULL;
 
-    if (!(xml = xmlReadFile(filename, NULL,
-                            XML_PARSE_NOENT | XML_PARSE_NONET |
-                            XML_PARSE_NOERROR | XML_PARSE_NOWARNING))) {
-        virNetworkReportError(conn, VIR_ERR_XML_ERROR, NULL);
-        return NULL;
+    /* Set up a parser context so we can catch the details of XML errors. */
+    pctxt = xmlNewParserCtxt ();
+    if (!pctxt || !pctxt->sax)
+        goto cleanup;
+    pctxt->sax->error = catchXMLError;
+    pctxt->_private = conn;
+
+    if (conn) virResetError (&conn->err);
+    xml = xmlCtxtReadFile (pctxt, filename, NULL,
+                           XML_PARSE_NOENT | XML_PARSE_NONET |
+                           XML_PARSE_NOWARNING);
+    if (!xml) {
+        if (conn && conn->err.code == VIR_ERR_NONE)
+              virNetworkReportError(conn, VIR_ERR_XML_ERROR,
+                                    _("failed to parse xml document"));
+        goto cleanup;
     }
 
     if ((root = xmlDocGetRootElement(xml)) == NULL) {
         virNetworkReportError(conn, VIR_ERR_INTERNAL_ERROR,
                               "%s", _("missing root element"));
-        xmlFreeDoc(xml);
-        return NULL;
+        goto cleanup;
     }
 
     def = virNetworkDefParseNode(conn, xml, root);
 
-    xmlFreeDoc(xml);
+cleanup:
+    xmlFreeParserCtxt (pctxt);
+    xmlFreeDoc (xml);
     return def;
 }
 
Index: src/storage_conf.c
===================================================================
RCS file: /data/cvs/libvirt/src/storage_conf.c,v
retrieving revision 1.10
diff -u -r1.10 storage_conf.c
--- src/storage_conf.c	25 Jul 2008 14:27:25 -0000	1.10
+++ src/storage_conf.c	30 Jul 2008 16:52:55 -0000
@@ -361,22 +361,53 @@
     return NULL;
 }
 
+/* Called from SAX on parsing errors in the XML. */
+static void
+catchXMLError (void *ctx, const char *msg ATTRIBUTE_UNUSED, ...)
+{
+    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
+
+    if (ctxt) {
+        virConnectPtr conn = ctxt->_private;
+
+        if (conn &&
+            conn->err.code == VIR_ERR_NONE &&
+            ctxt->lastError.level == XML_ERR_FATAL &&
+            ctxt->lastError.message != NULL) {
+            virStorageReportError (conn, VIR_ERR_XML_DETAIL,
+                                   _("at line %d: %s"),
+                                   ctxt->lastError.line,
+                                   ctxt->lastError.message);
+        }
+    }
+}
+
 virStoragePoolDefPtr
 virStoragePoolDefParse(virConnectPtr conn,
                        const char *xmlStr,
                        const char *filename) {
     virStoragePoolDefPtr ret = NULL;
+    xmlParserCtxtPtr pctxt;
     xmlDocPtr xml = NULL;
     xmlNodePtr node = NULL;
     xmlXPathContextPtr ctxt = NULL;
 
-    if (!(xml = xmlReadDoc(BAD_CAST xmlStr,
-                           filename ? filename : "storage.xml",
-                           NULL,
-                           XML_PARSE_NOENT | XML_PARSE_NONET |
-                           XML_PARSE_NOERROR | XML_PARSE_NOWARNING))) {
-        virStorageReportError(conn, VIR_ERR_XML_ERROR,
-                              "%s", _("malformed xml document"));
+    /* Set up a parser context so we can catch the details of XML errors. */
+    pctxt = xmlNewParserCtxt ();
+    if (!pctxt || !pctxt->sax)
+        goto cleanup;
+    pctxt->sax->error = catchXMLError;
+    pctxt->_private = conn;
+
+    if (conn) virResetError (&conn->err);
+    xml = xmlCtxtReadDoc (pctxt, BAD_CAST xmlStr,
+                          filename ? filename : "storage.xml", NULL,
+                          XML_PARSE_NOENT | XML_PARSE_NONET |
+                          XML_PARSE_NOWARNING);
+    if (!xml) {
+        if (conn && conn->err.code == VIR_ERR_NONE)
+              virStorageReportError(conn, VIR_ERR_XML_ERROR,
+                                    _("failed to parse xml document"));
         goto cleanup;
     }
 
@@ -396,12 +427,14 @@
 
     ret = virStoragePoolDefParseDoc(conn, ctxt, node);
 
+    xmlFreeParserCtxt (pctxt);
     xmlXPathFreeContext(ctxt);
     xmlFreeDoc(xml);
 
     return ret;
 
  cleanup:
+    xmlFreeParserCtxt (pctxt);
     xmlXPathFreeContext(ctxt);
     xmlFreeDoc(xml);
     return NULL;
@@ -725,15 +758,27 @@
                       const char *xmlStr,
                       const char *filename) {
     virStorageVolDefPtr ret = NULL;
+    xmlParserCtxtPtr pctxt;
     xmlDocPtr xml = NULL;
     xmlNodePtr node = NULL;
     xmlXPathContextPtr ctxt = NULL;
 
-    if (!(xml = xmlReadDoc(BAD_CAST xmlStr, filename ? filename : "storage.xml", NULL,
-                           XML_PARSE_NOENT | XML_PARSE_NONET |
-                           XML_PARSE_NOERROR | XML_PARSE_NOWARNING))) {
-        virStorageReportError(conn, VIR_ERR_XML_ERROR,
-                              "%s", _("malformed xml document"));
+    /* Set up a parser context so we can catch the details of XML errors. */
+    pctxt = xmlNewParserCtxt ();
+    if (!pctxt || !pctxt->sax)
+        goto cleanup;
+    pctxt->sax->error = catchXMLError;
+    pctxt->_private = conn;
+
+    if (conn) virResetError (&conn->err);
+    xml = xmlCtxtReadDoc (pctxt, BAD_CAST xmlStr,
+                          filename ? filename : "storage.xml", NULL,
+                          XML_PARSE_NOENT | XML_PARSE_NONET |
+                          XML_PARSE_NOWARNING);
+    if (!xml) {
+        if (conn && conn->err.code == VIR_ERR_NONE)
+              virStorageReportError(conn, VIR_ERR_XML_ERROR,
+                                    _("failed to parse xml document"));
         goto cleanup;
     }
 
@@ -753,12 +798,14 @@
 
     ret = virStorageVolDefParseDoc(conn, pool, ctxt, node);
 
+    xmlFreeParserCtxt (pctxt);
     xmlXPathFreeContext(ctxt);
     xmlFreeDoc(xml);
 
     return ret;
 
  cleanup:
+    xmlFreeParserCtxt (pctxt);
     xmlXPathFreeContext(ctxt);
     xmlFreeDoc(xml);
     return NULL;


More information about the libvir-list mailing list