| 1 | This patch adds an "--xpath0" option to xmllint so that NUL characters
|
| 2 | can be used as separators.
|
| 3 |
|
| 4 | See <https://gitlab.gnome.org/GNOME/libxml2/-/issues/227>.
|
| 5 |
|
| 6 | diff --git a/doc/xmllint.xml b/doc/xmllint.xml
|
| 7 | |
| 8 | |
| 9 | @@ -70,6 +70,7 @@
|
| 10 | <arg choice="plain"><option>--debug</option></arg>
|
| 11 | <arg choice="plain"><option>--shell</option></arg>
|
| 12 | <arg choice="plain"><option>--xpath "<replaceable class="option">XPath_expression</replaceable>"</option></arg>
|
| 13 | + <arg choice="plain"><option>--xpath0 "<replaceable class="option">XPath_expression</replaceable>"</option></arg>
|
| 14 | <arg choice="plain"><option>--debugent</option></arg>
|
| 15 | <arg choice="plain"><option>--copy</option></arg>
|
| 16 | <arg choice="plain"><option>--recover</option></arg>
|
| 17 | @@ -537,6 +538,21 @@
|
| 18 | node set is serialized in full in the output. In case
|
| 19 | of an empty node set the "XPath set is empty" result
|
| 20 | will be shown and an error exit code will be returned.
|
| 21 | + Results are separated by the newline character.
|
| 22 | + </para>
|
| 23 | + </listitem>
|
| 24 | + </varlistentry>
|
| 25 | +
|
| 26 | + <varlistentry>
|
| 27 | + <term><option>--xpath0 "<replaceable class="option">XPath_expression</replaceable>"</option></term>
|
| 28 | + <listitem>
|
| 29 | + <para>
|
| 30 | + Run an XPath expression given as argument and print the
|
| 31 | + result. In case of a nodeset result, each node in the
|
| 32 | + node set is serialized in full in the output. In case
|
| 33 | + of an empty node set the "XPath set is empty" result
|
| 34 | + will be shown and an error exit code will be returned.
|
| 35 | + Results are separated by the null character.
|
| 36 | </para>
|
| 37 | </listitem>
|
| 38 | </varlistentry>
|
| 39 | diff --git a/xmllint.c b/xmllint.c
|
| 40 | |
| 41 | |
| 42 | @@ -194,6 +194,7 @@ static int sax1 = 0;
|
| 43 | #endif /* LIBXML_SAX1_ENABLED */
|
| 44 | #ifdef LIBXML_XPATH_ENABLED
|
| 45 | static const char *xpathquery = NULL;
|
| 46 | +static const char *xpathsep = "\n";
|
| 47 | #endif
|
| 48 | static int options = XML_PARSE_COMPACT | XML_PARSE_BIG_LINES;
|
| 49 | static int sax = 0;
|
| 50 | @@ -2095,7 +2096,7 @@ static void doXPathDump(xmlXPathObjectPtr cur) {
|
| 51 | for (i = 0;i < cur->nodesetval->nodeNr;i++) {
|
| 52 | node = cur->nodesetval->nodeTab[i];
|
| 53 | xmlNodeDumpOutput(buf, NULL, node, 0, 0, NULL);
|
| 54 | - xmlOutputBufferWrite(buf, 1, "\n");
|
| 55 | + xmlOutputBufferWrite(buf, 1, xpathsep);
|
| 56 | }
|
| 57 | xmlOutputBufferClose(buf);
|
| 58 | #else
|
| 59 | @@ -2104,27 +2105,27 @@ static void doXPathDump(xmlXPathObjectPtr cur) {
|
| 60 | break;
|
| 61 | }
|
| 62 | case XPATH_BOOLEAN:
|
| 63 | - if (cur->boolval) printf("true\n");
|
| 64 | - else printf("false\n");
|
| 65 | + if (cur->boolval) printf("true%s", xpathsep);
|
| 66 | + else printf("false%s", xpathsep);
|
| 67 | break;
|
| 68 | case XPATH_NUMBER:
|
| 69 | switch (xmlXPathIsInf(cur->floatval)) {
|
| 70 | case 1:
|
| 71 | - printf("Infinity\n");
|
| 72 | + printf("Infinity%s", xpathsep);
|
| 73 | break;
|
| 74 | case -1:
|
| 75 | - printf("-Infinity\n");
|
| 76 | + printf("-Infinity%s", xpathsep);
|
| 77 | break;
|
| 78 | default:
|
| 79 | if (xmlXPathIsNaN(cur->floatval)) {
|
| 80 | - printf("NaN\n");
|
| 81 | + printf("NaN%s", xpathsep);
|
| 82 | } else {
|
| 83 | - printf("%0g\n", cur->floatval);
|
| 84 | + printf("%0g%s", cur->floatval, xpathsep);
|
| 85 | }
|
| 86 | }
|
| 87 | break;
|
| 88 | case XPATH_STRING:
|
| 89 | - printf("%s\n", (const char *) cur->stringval);
|
| 90 | + printf("%s%s", (const char *) cur->stringval, xpathsep);
|
| 91 | break;
|
| 92 | case XPATH_UNDEFINED:
|
| 93 | fprintf(stderr, "XPath Object is uninitialized\n");
|
| 94 | @@ -3098,7 +3099,8 @@ static void usage(FILE *f, const char *name) {
|
| 95 | fprintf(f, "\t--sax: do not build a tree but work just at the SAX level\n");
|
| 96 | fprintf(f, "\t--oldxml10: use XML-1.0 parsing rules before the 5th edition\n");
|
| 97 | #ifdef LIBXML_XPATH_ENABLED
|
| 98 | - fprintf(f, "\t--xpath expr: evaluate the XPath expression, imply --noout\n");
|
| 99 | + fprintf(f, "\t--xpath expr: evaluate the XPath expression, results are separated by \\n, imply --noout\n");
|
| 100 | + fprintf(f, "\t--xpath0 expr: evaluate the XPath expression, results are separated by \\0, imply --noout\n");
|
| 101 | #endif
|
| 102 |
|
| 103 | fprintf(f, "\nLibxml project home page: http://xmlsoft.org/\n");
|
| 104 | @@ -3480,6 +3482,13 @@ main(int argc, char **argv) {
|
| 105 | i++;
|
| 106 | noout++;
|
| 107 | xpathquery = argv[i];
|
| 108 | + xpathsep = "\n";
|
| 109 | + } else if ((!strcmp(argv[i], "-xpath0")) ||
|
| 110 | + (!strcmp(argv[i], "--xpath0"))) {
|
| 111 | + i++;
|
| 112 | + noout++;
|
| 113 | + xpathquery = argv[i];
|
| 114 | + xpathsep = "\0";
|
| 115 | #endif
|
| 116 | } else if ((!strcmp(argv[i], "-oldxml10")) ||
|
| 117 | (!strcmp(argv[i], "--oldxml10"))) {
|
| 118 | @@ -3712,6 +3721,11 @@ main(int argc, char **argv) {
|
| 119 | i++;
|
| 120 | continue;
|
| 121 | }
|
| 122 | + if ((!strcmp(argv[i], "-xpath0")) ||
|
| 123 | + (!strcmp(argv[i], "--xpath0"))) {
|
| 124 | + i++;
|
| 125 | + continue;
|
| 126 | + }
|
| 127 | #endif
|
| 128 | if ((timing) && (repeat))
|
| 129 | startTimer();
|