parser xml FEATURE try to guess sensible hints for opaque nodes

... instead of guessing them when printing.
Refs #1827
diff --git a/src/parser_xml.c b/src/parser_xml.c
index 69d1b45..1f395b8 100644
--- a/src/parser_xml.c
+++ b/src/parser_xml.c
@@ -411,6 +411,79 @@
 }
 
 /**
+ * @brief Get sensible data hints for an opaque node.
+ *
+ * @param[in] name Node name.
+ * @param[in] name_len Length of @p name.
+ * @param[in] value Node value.
+ * @param[in] value_len Length of @p value.
+ * @param[in] first Node first sibling.
+ * @param[in] ns Node module namespace.
+ * @param[out] hints Data hints to use.
+ * @param[out] anchor Anchor to insert after in case of a list.
+ */
+static void
+lydxml_get_hints_opaq(const char *name, size_t name_len, const char *value, size_t value_len, struct lyd_node *first,
+        const char *ns, uint32_t *hints, struct lyd_node **anchor)
+{
+    struct lyd_node_opaq *opaq;
+    char *ptr;
+    long num;
+
+    *hints = 0;
+    *anchor = NULL;
+
+    if (!value_len) {
+        /* no value */
+        *hints |= LYD_VALHINT_EMPTY;
+    } else if (!strncmp(value, "true", value_len) || !strncmp(value, "false", value_len)) {
+        /* boolean value */
+        *hints |= LYD_VALHINT_BOOLEAN;
+    } else {
+        num = strtol(value, &ptr, 10);
+        if ((unsigned)(ptr - value) == value_len) {
+            /* number value */
+            *hints |= LYD_VALHINT_DECNUM;
+            if ((num < INT32_MIN) || (num > UINT32_MAX)) {
+                /* large number */
+                *hints |= LYD_VALHINT_NUM64;
+            }
+        } else {
+            /* string value */
+            *hints |= LYD_VALHINT_STRING;
+        }
+    }
+
+    if (!first) {
+        return;
+    }
+
+    /* search backwards to find the last instance */
+    do {
+        first = first->prev;
+        if (first->schema) {
+            continue;
+        }
+
+        opaq = (struct lyd_node_opaq *)first;
+        assert(opaq->format == LY_VALUE_XML);
+        if (!ly_strncmp(opaq->name.name, name, name_len) && !strcmp(opaq->name.module_ns, ns)) {
+            if (opaq->value && opaq->value[0]) {
+                /* leaf-list nodes */
+                opaq->hints |= LYD_NODEHINT_LEAFLIST;
+                *hints |= LYD_NODEHINT_LEAFLIST;
+            } else {
+                /* list nodes */
+                opaq->hints |= LYD_NODEHINT_LIST;
+                *hints |= LYD_NODEHINT_LIST;
+            }
+            *anchor = first;
+            break;
+        }
+    } while (first->prev->next);
+}
+
+/**
  * @brief Get schema node for the current element.
  *
  * @param[in] lydctx XML data parser context.
@@ -537,8 +610,8 @@
     struct lyd_attr *attr = NULL;
     const struct lysc_node *snode;
     struct lysc_ext_instance *ext;
-    uint32_t prev_parse_opts, orig_parse_opts, prev_int_opts;
-    struct lyd_node *node = NULL, *anchor;
+    uint32_t prev_parse_opts, orig_parse_opts, prev_int_opts, hints;
+    struct lyd_node *node = NULL, *anchor, *insert_anchor = NULL;
     void *val_prefix_data = NULL;
     LY_VALUE_FORMAT format;
     ly_bool parse_subtree;
@@ -595,7 +668,7 @@
         if (xmlctx->ws_only) {
             /* ignore WS-only value */
             if (xmlctx->dynamic) {
-                free((char *) xmlctx->value);
+                free((char *)xmlctx->value);
             }
             xmlctx->dynamic = 0;
             xmlctx->value = "";
@@ -612,9 +685,13 @@
         ns = lyxml_ns_get(&xmlctx->ns, prefix, prefix_len);
         assert(ns);
 
+        /* get best-effort node hints */
+        lydxml_get_hints_opaq(name, name_len, xmlctx->value, xmlctx->value_len, parent ? lyd_child(parent) : *first_p,
+                ns->uri, &hints, &insert_anchor);
+
         /* create node */
         ret = lyd_create_opaq(ctx, name, name_len, prefix, prefix_len, ns->uri, strlen(ns->uri), xmlctx->value,
-                xmlctx->value_len, &xmlctx->dynamic, format, val_prefix_data, LYD_HINT_DATA, &node);
+                xmlctx->value_len, &xmlctx->dynamic, format, val_prefix_data, hints, &node);
         LY_CHECK_GOTO(ret, error);
 
         /* parser next */
@@ -781,7 +858,9 @@
     }
 
     /* insert, keep first pointer correct */
-    if (ext) {
+    if (insert_anchor) {
+        lyd_insert_after(insert_anchor, node);
+    } else if (ext) {
         LY_CHECK_GOTO(ret = lyd_insert_ext(parent, node), error);
     } else {
         lyd_insert_node(parent, first_p, node, lydctx->parse_opts & LYD_PARSE_ORDERED ? 1 : 0);
diff --git a/src/printer_json.c b/src/printer_json.c
index 4c53f0f..a301075 100644
--- a/src/printer_json.c
+++ b/src/printer_json.c
@@ -846,34 +846,6 @@
 json_print_opaq(struct jsonpr_ctx *pctx, const struct lyd_node_opaq *node)
 {
     ly_bool first = 1, last = 1;
-    char *ptr;
-    long num;
-
-    if (node->hints == LYD_HINT_DATA) {
-        /* basically, we do not know anything about the node so just do our best */
-        LY_CHECK_RET(json_print_member2(pctx, pctx->parent, node->format, &node->name, 0));
-        if (node->child) {
-            LY_CHECK_RET(json_print_inner(pctx, &node->node));
-            LEVEL_PRINTED;
-        } else {
-            if (node->value) {
-                num = strtol(node->value, &ptr, 10);
-                if (!ptr[0] && (ptr != node->value) &&
-                        (((num < 0) && (num >= INT32_MIN)) || ((num >= 0) && (num <= UINT32_MAX)))) {
-                    ly_print_(pctx->out, "%s", node->value);
-                } else {
-                    ly_print_(pctx->out, "\"%s\"", node->value);
-                }
-            } else {
-                ly_print_(pctx->out, "[null]");
-            }
-            LEVEL_PRINTED;
-
-            /* attributes */
-            json_print_attributes(pctx, (const struct lyd_node *)node, 0);
-        }
-        return LY_SUCCESS;
-    }
 
     if (node->hints & (LYD_NODEHINT_LIST | LYD_NODEHINT_LEAFLIST)) {
         if (node->prev->next && matching_node(node->prev, &node->node)) {
@@ -902,10 +874,10 @@
     } else {
         if (node->hints & LYD_VALHINT_EMPTY) {
             ly_print_(pctx->out, "[null]");
-        } else if (node->hints & (LYD_VALHINT_BOOLEAN | LYD_VALHINT_DECNUM)) {
+        } else if ((node->hints & (LYD_VALHINT_BOOLEAN | LYD_VALHINT_DECNUM)) && !(node->hints & LYD_VALHINT_NUM64)) {
             ly_print_(pctx->out, "%s", node->value);
         } else {
-            /* string */
+            /* string or a large number */
             ly_print_(pctx->out, "\"%s\"", node->value);
         }
         LEVEL_PRINTED;