parser xml NEW notification parsing
diff --git a/src/parser_xml.c b/src/parser_xml.c
index 55aaf67..32c19a0 100644
--- a/src/parser_xml.c
+++ b/src/parser_xml.c
@@ -921,3 +921,153 @@
}
return ret;
}
+
+static LY_ERR
+lydxml_notif_envelope(struct lyxml_ctx *xmlctx, struct lyd_node **envp)
+{
+ LY_ERR ret = LY_SUCCESS;
+ const struct lyxml_ns *ns = NULL;
+ struct ly_attr *attr = NULL;
+ struct lyd_node *et;
+ const char *prefix;
+ size_t prefix_len;
+
+ *envp = NULL;
+
+ /* container envelope */
+ LY_CHECK_GOTO(ret = lydxml_envelope(xmlctx, "notification", "urn:ietf:params:xml:ns:netconf:notification:1.0",
+ envp), cleanup);
+
+ /* no envelope, fine */
+ if (!*envp) {
+ goto cleanup;
+ }
+
+ /* child "eventTime" */
+ if ((xmlctx->status != LYXML_ELEMENT) || ly_strncmp("eventTime", xmlctx->name, xmlctx->name_len)) {
+ LOGVAL(xmlctx->ctx, LY_VLOG_LINE, &xmlctx->line, LYVE_REFERENCE, "Missing the \"eventTime\" element.");
+ ret = LY_EVALID;
+ goto cleanup;
+ }
+
+ prefix = xmlctx->prefix;
+ prefix_len = xmlctx->prefix_len;
+ ns = lyxml_ns_get(xmlctx, prefix, prefix_len);
+ if (!ns) {
+ LOGVAL(xmlctx->ctx, LY_VLOG_LINE, &xmlctx->line, LYVE_REFERENCE, "Unknown XML prefix \"%.*s\".",
+ prefix_len, prefix);
+ ret = LY_EVALID;
+ goto cleanup;
+ } else if (strcmp(ns->uri, "urn:ietf:params:xml:ns:netconf:notification:1.0")) {
+ LOGVAL(xmlctx->ctx, LY_VLOG_LINE, &xmlctx->line, LYVE_REFERENCE, "Invalid namespace \"%s\" of \"eventTime\".",
+ ns->uri);
+ ret = LY_EVALID;
+ goto cleanup;
+ }
+
+ LY_CHECK_RET(lyxml_ctx_next(xmlctx));
+
+ /* create attributes */
+ if (xmlctx->status == LYXML_ATTRIBUTE) {
+ LY_CHECK_RET(lydxml_attrs(xmlctx, &attr));
+ }
+
+ /* validate value */
+ /* TODO */
+ /*if (!xmlctx->ws_only) {
+ LOGVAL(xmlctx->ctx, LY_VLOG_LINE, &xmlctx->line, LYVE_SYNTAX, "Unexpected value \"%.*s\" in the \"%s\" element.",
+ xmlctx->value_len, xmlctx->value, name);
+ ret = LY_EVALID;
+ goto cleanup;
+ }*/
+
+ /* create node */
+ ret = lyd_create_opaq(xmlctx->ctx, "eventTime", 9, xmlctx->value, xmlctx->value_len, NULL, LYD_XML, NULL,
+ prefix, prefix_len, ns->uri, &et);
+ LY_CHECK_GOTO(ret, cleanup);
+
+ /* assign atributes */
+ ((struct lyd_node_opaq *)et)->attr = attr;
+ attr = NULL;
+
+ /* insert */
+ lyd_insert_node(*envp, NULL, et);
+
+ /* finish parsing */
+ LY_CHECK_GOTO(ret = lyxml_ctx_next(xmlctx), cleanup);
+ if (xmlctx->status != LYXML_ELEM_CLOSE) {
+ assert(xmlctx->status == LYXML_ELEMENT);
+ LOGVAL(xmlctx->ctx, LY_VLOG_LINE, &xmlctx->line, LYVE_SYNTAX, "Unexpected sibling element \"%.*s\" of \"eventTime\".",
+ xmlctx->name_len, xmlctx->name);
+ ret = LY_EVALID;
+ goto cleanup;
+ }
+ LY_CHECK_GOTO(ret = lyxml_ctx_next(xmlctx), cleanup);
+
+cleanup:
+ if (ret) {
+ lyd_free_tree(*envp);
+ ly_free_attr(xmlctx->ctx, attr, 1);
+ }
+ return ret;
+}
+
+LY_ERR
+lyd_parse_xml_notif(const struct ly_ctx *ctx, const char *data, struct lyd_node **tree, struct lyd_node **ntf)
+{
+ LY_ERR ret = LY_SUCCESS;
+ struct lyd_xml_ctx lydctx = {0};
+ struct lyd_node *ntf_e = NULL;
+
+ /* init */
+ LY_CHECK_GOTO(ret = lyxml_ctx_new(ctx, data, &lydctx.xmlctx), cleanup);
+ lydctx.options = LYD_OPT_PARSE_ONLY | LYD_OPT_STRICT;
+ lydctx.int_opts = LYD_INTOPT_NOTIF;
+ *tree = NULL;
+ *ntf = NULL;
+
+ /* parse "notification" and "eventTime", if present */
+ LY_CHECK_GOTO(ret = lydxml_notif_envelope(lydctx.xmlctx, &ntf_e), cleanup);
+
+ /* parse the rest of data normally */
+ LY_CHECK_GOTO(ret = lydxml_data_r(&lydctx, NULL, tree), cleanup);
+
+ /* make sure we have parsed some notification */
+ if (!lydctx.op_ntf) {
+ LOGVAL(ctx, LY_VLOG_NONE, NULL, LYVE_DATA, "Missing the \"notification\" node.");
+ ret = LY_EVALID;
+ goto cleanup;
+ }
+
+ /* finish XML parsing */
+ if (ntf_e) {
+ if (lydctx.xmlctx->status != LYXML_ELEM_CLOSE) {
+ assert(lydctx.xmlctx->status == LYXML_ELEMENT);
+ LOGVAL(ctx, LY_VLOG_LINE, &lydctx.xmlctx->line, LYVE_SYNTAX, "Unexpected sibling element \"%.*s\" of \"notification\".",
+ lydctx.xmlctx->name_len, lydctx.xmlctx->name);
+ ret = LY_EVALID;
+ goto cleanup;
+ }
+ LY_CHECK_GOTO(ret = lyxml_ctx_next(lydctx.xmlctx), cleanup);
+ }
+
+ *ntf = lydctx.op_ntf;
+ assert(*tree);
+ if (ntf_e) {
+ /* connect to the notification */
+ lyd_insert_node(ntf_e, NULL, *tree);
+ *tree = ntf_e;
+ }
+
+cleanup:
+ /* we have used parse_only flag */
+ assert(!lydctx.unres_node_type.count && !lydctx.unres_meta_type.count && !lydctx.when_check.count);
+ lyxml_ctx_free(lydctx.xmlctx);
+ if (ret) {
+ lyd_free_all(*tree);
+ lyd_free_tree(ntf_e);
+ *tree = NULL;
+ *ntf = NULL;
+ }
+ return ret;
+}