virDomainObjParseXML(xmlDocPtr xml,
                     xmlXPathContextPtr ctxt,
                     virDomainXMLOptionPtr xmlopt,
                     unsigned int flags)
{
    long val;
    xmlNodePtr config;
    xmlNodePtr oldnode;
    virDomainObjPtr obj;
    size_t i;
    int n;
    int state;
    int reason = 0;
    void *parseOpaque = NULL;
    g_autofree char *tmp = NULL;
    g_autofree xmlNodePtr *nodes = NULL;

    if (!(obj = virDomainObjNew(xmlopt)))
        return NULL;

    if (!(config = virXPathNode("./domain", ctxt))) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("no domain config"));
        goto error;
    }

    oldnode = ctxt->node;
    ctxt->node = config;
    obj->def = virDomainDefParseXML(xml, ctxt, xmlopt, flags);
    ctxt->node = oldnode;
    if (!obj->def)
        goto error;

    if (!(tmp = virXMLPropString(ctxt->node, "state"))) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("missing domain state"));
        goto error;
    }
    if ((state = virDomainStateTypeFromString(tmp)) < 0) {
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                       _("invalid domain state '%s'"), tmp);
        goto error;
    }
    VIR_FREE(tmp);

    if ((tmp = virXMLPropString(ctxt->node, "reason"))) {
        if ((reason = virDomainStateReasonFromString(state, tmp)) < 0) {
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                           _("invalid domain state reason '%s'"), tmp);
            goto error;
        }
    }

    virDomainObjSetState(obj, state, reason);

    if (virXPathLong("string(./@pid)", ctxt, &val) < 0) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("invalid pid"));
        goto error;
    }
    obj->pid = (pid_t)val;

    if ((n = virXPathNodeSet("./taint", ctxt, &nodes)) < 0)
        goto error;
    for (i = 0; i < n; i++) {
        char *str = virXMLPropString(nodes[i], "flag");
        if (str) {
            int flag = virDomainTaintTypeFromString(str);
            if (flag < 0) {
                virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                               _("Unknown taint flag %s"), str);
                VIR_FREE(str);
                goto error;
            }
            VIR_FREE(str);
            virDomainObjTaint(obj, flag);
        }
    }

    if (xmlopt->privateData.parse &&
        xmlopt->privateData.parse(ctxt, obj, &xmlopt->config) < 0)
        goto error;

    if (xmlopt->privateData.getParseOpaque)
        parseOpaque = xmlopt->privateData.getParseOpaque(obj);

    /* callback to fill driver specific domain aspects */
    if (virDomainDefPostParse(obj->def, flags, xmlopt, parseOpaque) < 0)
        goto error;

    /* validate configuration */
    if (virDomainDefValidate(obj->def, flags, xmlopt) < 0)
        goto error;

    return obj;

 error:
    virObjectUnref(obj);
    return NULL;
}
virDomainObjParseXML(xmlDocPtr xml,
                     xmlXPathContextPtr ctxt,
                     virDomainXMLOptionPtr xmlopt,
                     unsigned int flags)
{
    long val;
    xmlNodePtr config;
    xmlNodePtr oldnode;
    virDomainObjPtr obj;
    size_t i;
    int n;
    int state;
    int reason = 0;
    void *parseOpaque = NULL;
    g_autofree char *tmp = NULL;
    g_autofree xmlNodePtr *nodes = NULL;

    if (!(obj = virDomainObjNew(xmlopt)))
        return NULL;

    if (!(config = virXPathNode("./domain", ctxt))) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("no domain config"));
        goto error;
    }

    oldnode = ctxt->node;
    ctxt->node = config;
    obj->def = virDomainDefParseXML(xml, ctxt, xmlopt, flags);
    ctxt->node = oldnode;
    if (!obj->def)
        goto error;

    if (!(tmp = virXMLPropString(ctxt->node, "state"))) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("missing domain state"));
        goto error;
    }
    if ((state = virDomainStateTypeFromString(tmp)) < 0) {
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                       _("invalid domain state '%s'"), tmp);
        goto error;
    }
    VIR_FREE(tmp);

    if ((tmp = virXMLPropString(ctxt->node, "reason"))) {
        if ((reason = virDomainStateReasonFromString(state, tmp)) < 0) {
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                           _("invalid domain state reason '%s'"), tmp);
            goto error;
        }
    }

    virDomainObjSetState(obj, state, reason);

    if (virXPathLong("string(./@pid)", ctxt, &val) < 0) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("invalid pid"));
        goto error;
    }
    obj->pid = (pid_t)val;

    if ((n = virXPathNodeSet("./taint", ctxt, &nodes)) < 0)
        goto error;
    for (i = 0; i < n; i++) {
        char *str = virXMLPropString(nodes[i], "flag");
        if (str) {
            int flag = virDomainTaintTypeFromString(str);
            if (flag < 0) {
                virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                               _("Unknown taint flag %s"), str);
                VIR_FREE(str);
                goto error;
            }
            VIR_FREE(str);
            virDomainObjTaint(obj, flag);
        }
    }

    if (xmlopt->privateData.parse &&
        xmlopt->privateData.parse(ctxt, obj, &xmlopt->config) < 0)
        goto error;

    if (xmlopt->privateData.getParseOpaque)
        parseOpaque = xmlopt->privateData.getParseOpaque(obj);

     
    if (virDomainDefPostParse(obj->def, flags, xmlopt, parseOpaque) < 0)
        goto error;

     
    if (virDomainDefValidate(obj->def, flags, xmlopt) < 0)
        goto error;

    return obj;

 error:
    virObjectUnref(obj);
    return NULL;
}