[libxml2] Add value-of tag support



commit 2cc93f77543b5721257f795f303bfb56a4b384c7
Author: Oliver Diehl <oliver diehl nxp com>
Date:   Tue Jan 11 14:43:44 2022 +0100

    Add value-of tag support

 schematron.c | 107 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 105 insertions(+), 2 deletions(-)
---
diff --git a/schematron.c b/schematron.c
index 2d2e03ec..331f683c 100644
--- a/schematron.c
+++ b/schematron.c
@@ -33,6 +33,7 @@
 #include <libxml/xpathInternals.h>
 #include <libxml/pattern.h>
 #include <libxml/schematron.h>
+#include <libxml/debugXML.h>
 
 #define SCHEMATRON_PARSE_OPTIONS XML_PARSE_NOENT
 
@@ -838,6 +839,57 @@ xmlSchematronAddNamespace(xmlSchematronParserCtxtPtr ctxt,
 
 }
 
+/**
+ * xmlSchematronParseTestReportMsg:
+ * @ctxt:  the schema parser context
+ * @con:  the assert or report node
+ *
+ * Format the message content of the assert or report test
+ */
+static void
+xmlSchematronParseTestReportMsg(xmlSchematronParserCtxtPtr ctxt, xmlNodePtr con)
+{
+    xmlNodePtr child;
+    xmlXPathCompExprPtr comp;
+
+    child = con->children;
+    while (child != NULL) {
+        if ((child->type == XML_TEXT_NODE) ||
+            (child->type == XML_CDATA_SECTION_NODE))
+            /* Do Nothing */
+            {}
+        else if (IS_SCHEMATRON(child, "name")) {
+            /* Do Nothing */
+        } else if (IS_SCHEMATRON(child, "value-of")) {
+            xmlChar *select;
+
+            select = xmlGetNoNsProp(child, BAD_CAST "select");
+
+            if (select == NULL) {
+                xmlSchematronPErr(ctxt, child,
+                                  XML_SCHEMAV_ATTRINVALID,
+                                  "value-of has no select attribute",
+                                  NULL, NULL);
+            } else {
+                /*
+                 * try first to compile the test expression
+                 */
+                comp = xmlXPathCtxtCompile(ctxt->xctxt, select);
+                if (comp == NULL) {
+                    xmlSchematronPErr(ctxt, child,
+                                      XML_SCHEMAV_ATTRINVALID,
+                                      "Failed to compile select expression %s",
+                                      select, NULL);
+                }
+                xmlXPathFreeCompExpr(comp);
+            }
+            xmlFree(select);
+        }
+        child = child->next;
+        continue;
+    }
+}
+
 /**
  * xmlSchematronParseRule:
  * @ctxt:  a schema validation context
@@ -901,7 +953,7 @@ xmlSchematronParseRule(xmlSchematronParserCtxtPtr ctxt,
                     NULL, NULL);
                 xmlFree(test);
             } else {
-                /* TODO will need dynamic processing instead */
+                xmlSchematronParseTestReportMsg(ctxt, cur);
                 report = xmlNodeGetContent(cur);
 
                 testptr = xmlSchematronAddTest(ctxt, XML_SCHEMATRON_ASSERT,
@@ -924,7 +976,7 @@ xmlSchematronParseRule(xmlSchematronParserCtxtPtr ctxt,
                     NULL, NULL);
                 xmlFree(test);
             } else {
-                /* TODO will need dynamic processing instead */
+                xmlSchematronParseTestReportMsg(ctxt, cur);
                 report = xmlNodeGetContent(cur);
 
                 testptr = xmlSchematronAddTest(ctxt, XML_SCHEMATRON_REPORT,
@@ -1294,6 +1346,7 @@ xmlSchematronFormatReport(xmlSchematronValidCtxtPtr ctxt,
                           xmlNodePtr test, xmlNodePtr cur) {
     xmlChar *ret = NULL;
     xmlNodePtr child, node;
+    xmlXPathCompExprPtr comp;
 
     if ((test == NULL) || (cur == NULL))
         return(ret);
@@ -1323,6 +1376,56 @@ xmlSchematronFormatReport(xmlSchematronValidCtxtPtr ctxt,
                 ret = xmlStrcat(ret, BAD_CAST ":");
                 ret = xmlStrcat(ret, node->name);
             }
+        } else if (IS_SCHEMATRON(child, "value-of")) {
+            xmlChar *select;
+            xmlXPathObjectPtr eval;
+
+            select = xmlGetNoNsProp(child, BAD_CAST "select");
+            comp = xmlXPathCtxtCompile(ctxt->xctxt, select);
+            eval = xmlXPathCompiledEval(comp, ctxt->xctxt);
+
+            switch (eval->type) {
+            case XPATH_NODESET: {
+                int indx;
+                xmlChar *spacer = BAD_CAST " ";
+
+                if (eval->nodesetval) {
+                    for (indx = 0; indx < eval->nodesetval->nodeNr; indx++) {
+                        if (indx > 0)
+                            ret = xmlStrcat(ret, spacer);
+                        ret = xmlStrcat(ret, eval->nodesetval->nodeTab[indx]->name);
+                    }
+                } else {
+                    xmlGenericError(xmlGenericErrorContext,
+                                    "Empty node set\n");
+                }
+                break;
+            }
+            case XPATH_BOOLEAN:
+                ret = xmlStrcat(ret, BAD_CAST xmlBoolToText(eval->boolval));
+                break;
+            case XPATH_NUMBER: {
+                xmlChar *buf;
+                int size;
+
+                size = snprintf(NULL, 0, "%0g", eval->floatval);
+                buf = (xmlChar*) malloc(size * sizeof(xmlChar));
+                /* xmlStrPrintf(buf, size, "%0g", eval->floatval); // doesn't work */
+                sprintf((char*) buf, "%0g", eval->floatval);
+                ret = xmlStrcat(ret, buf);
+                free(buf);
+                break;
+            }
+            case XPATH_STRING:
+                ret = xmlStrcat(ret, eval->stringval);
+                break;
+            default:
+                xmlGenericError(xmlGenericErrorContext,
+                                "Unsupported XPATH Type: %d\n", eval->type);
+            }
+            xmlXPathFreeObject(eval);
+            xmlXPathFreeCompExpr(comp);
+            xmlFree(select);
         } else {
             child = child->next;
             continue;


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]