Add virXMLValidateAgainstSchema helper method

Add a helper method that can validate an XML document against
an RNG schema
This commit is contained in:
Daniel P. Berrange 2014-11-18 14:50:05 +00:00
parent c5b6a4a5cb
commit 6d06b0d89b
6 changed files with 96 additions and 0 deletions

View File

@ -304,6 +304,7 @@ typedef enum {
VIR_ERR_STORAGE_VOL_EXIST = 90, /* the storage vol already exists */
VIR_ERR_CPU_INCOMPATIBLE = 91, /* given CPU is incompatible with host
CPU*/
VIR_ERR_XML_INVALID_SCHEMA = 92, /* XML document doens't validate against schema */
} virErrorNumber;
/**

View File

@ -234,11 +234,15 @@
# define VIR_WARNINGS_NO_CAST_ALIGN \
_Pragma ("GCC diagnostic push") \
_Pragma ("GCC diagnostic ignored \"-Wcast-align\"")
# define VIR_WARNINGS_NO_PRINTF \
_Pragma ("GCC diagnostic push") \
_Pragma ("GCC diagnostic ignored \"-Wsuggest-attribute=format\"")
# define VIR_WARNINGS_RESET \
_Pragma ("GCC diagnostic pop")
# else
# define VIR_WARNINGS_NO_CAST_ALIGN
# define VIR_WARNINGS_NO_PRINTF
# define VIR_WARNINGS_RESET
# endif

View File

@ -2252,6 +2252,7 @@ virXMLParseHelper;
virXMLPickShellSafeComment;
virXMLPropString;
virXMLSaveFile;
virXMLValidateAgainstSchema;
virXPathBoolean;
virXPathInt;
virXPathLong;

View File

@ -1285,6 +1285,12 @@ virErrorMsg(virErrorNumber error, const char *info)
else
errmsg = _("the CPU is incompatible with host CPU: %s");
break;
case VIR_ERR_XML_INVALID_SCHEMA:
if (info == NULL)
errmsg = _("XML document failed to validate against schema");
else
errmsg = _("XML document failed to validate against schema: %s");
break;
}
return errmsg;
}

View File

@ -1082,3 +1082,82 @@ virXMLInjectNamespace(xmlNodePtr node,
return 0;
}
static void catchRNGError(void *ctx,
const char *msg,
...)
{
virBufferPtr buf = ctx;
va_list args;
va_start(args, msg);
VIR_WARNINGS_NO_PRINTF;
virBufferVasprintf(buf, msg, args);
VIR_WARNINGS_RESET;
va_end(args);
}
static void ignoreRNGError(void *ctx ATTRIBUTE_UNUSED,
const char *msg ATTRIBUTE_UNUSED,
...)
{}
int
virXMLValidateAgainstSchema(const char *schemafile,
xmlDocPtr doc)
{
xmlRelaxNGParserCtxtPtr rngParser = NULL;
xmlRelaxNGPtr rng = NULL;
xmlRelaxNGValidCtxtPtr rngValid = NULL;
virBuffer buf = VIR_BUFFER_INITIALIZER;
int ret = -1;
if (!(rngParser = xmlRelaxNGNewParserCtxt(schemafile))) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("Unable to create RNG parser for %s"),
schemafile);
goto cleanup;
}
xmlRelaxNGSetParserErrors(rngParser,
catchRNGError,
ignoreRNGError,
&buf);
if (!(rng = xmlRelaxNGParse(rngParser))) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("Unable to parse RNG %s: %s"),
schemafile, virBufferCurrentContent(&buf));
goto cleanup;
}
if (!(rngValid = xmlRelaxNGNewValidCtxt(rng))) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("Unable to create RNG validation context %s"),
schemafile);
goto cleanup;
}
xmlRelaxNGSetValidErrors(rngValid,
catchRNGError,
ignoreRNGError,
&buf);
if (xmlRelaxNGValidateDoc(rngValid, doc) != 0) {
virReportError(VIR_ERR_XML_INVALID_SCHEMA,
_("Unable to validate doc against %s\n%s"),
schemafile, virBufferCurrentContent(&buf));
goto cleanup;
}
ret = 0;
cleanup:
virBufferFreeAndReset(&buf);
xmlRelaxNGFreeParserCtxt(rngParser);
xmlRelaxNGFreeValidCtxt(rngValid);
xmlRelaxNGFree(rng);
return ret;
}

View File

@ -28,6 +28,7 @@
# include <libxml/parser.h>
# include <libxml/tree.h>
# include <libxml/xpath.h>
# include <libxml/relaxng.h>
int virXPathBoolean(const char *xpath,
xmlXPathContextPtr ctxt);
@ -176,4 +177,8 @@ int virXMLInjectNamespace(xmlNodePtr node,
const char *uri,
const char *key);
int
virXMLValidateAgainstSchema(const char *schemafile,
xmlDocPtr xml);
#endif /* __VIR_XML_H__ */