XML Output: libxo - provide single API to output TXT, XML, JSON and HTML
Phil Shafer
phil at juniper.net
Thu Jul 31 09:08:06 UTC 2014
"Simon J. Gerraty" writes:
>We now have an API and library that can avoid the need to double the
>cost of adding new output to apps, ie you only write to libxo's api
>and it does plain TXT for you if needed.
I'm appending another example, using "wc".
I've added the "xo" equivalent of warn/warnx/err/errx/etc. Normally,
they'll make the expected noise on stderr, but with the XO_WARN_XML
flag, they generate XML content on the stdout (or whatever xo_handle_t
is in use). I don't have a JSON equivalent because, well, I don't
know what the json equivalent would look like.
There's also a xo_attr function that will add an attribute to
the next element emitted, so one can:
xo_attr("seconds", stop - start);
xo_emit("{:time}", fancy_time(stop - start));
to make:
<time seconds="600">10 minutes</time>
There's also the "printf(1)" equivalent command "xo" for use in
shell scripts:
% xo --wrap response/data 'The {:animal} is {:color} and {:mood}\n' bear brown angry
The bear is brown and angry
% xo -X -p --wrap response/data 'The {:animal} is {:color} and {:mood}\n' bear brown angry
<response>
<data>
<animal>bear</animal>
<color>brown</color>
<mood>angry</mood>
</data>
</response>
The code is in github:
https://github.com/Juniper/libxo
HTML docs are here:
http://juniper.github.io/libxo/libxo-manual.html
Text/source docs are here:
https://raw.githubusercontent.com/Juniper/libxo/master/doc/libxo.txt
I'm using the common master/develop branching scheme, so "master"
should be stable, while "develop" is where I'm working.
Simon said there's a github mirror for freebsd, so I make fork that
and add the patches for the various utilities I'm working thru.
Thanks,
Phil
-----------
diff -rbu /usr/src/usr.bin/wc/wc.c ./wc.c
--- /usr/src/usr.bin/wc/wc.c 2010-12-21 12:09:25.000000000 -0500
+++ ./wc.c 2014-07-31 04:20:15.000000000 -0400
@@ -61,6 +61,7 @@
#include <unistd.h>
#include <wchar.h>
#include <wctype.h>
+#include <libxo/libxo.h>
uintmax_t tlinect, twordct, tcharct, tlongline;
int doline, doword, dochar, domulti, dolongline;
@@ -105,33 +106,45 @@
if (doline + doword + dochar + domulti + dolongline == 0)
doline = doword = dochar = 1;
+ xo_open_container("wc");
+ xo_open_list("file");
errors = 0;
total = 0;
if (!*argv) {
+ xo_open_instance("file");
if (cnt((char *)NULL) != 0)
++errors;
else
- (void)printf("\n");
+ xo_emit("\n");
+ xo_close_instance("file");
}
else do {
+ xo_open_instance("file");
+ xo_emit(" {ek:filename/%s}\n", *argv);
if (cnt(*argv) != 0)
++errors;
else
- (void)printf(" %s\n", *argv);
+ xo_emit(" {d:filename/%s}\n", *argv);
+ xo_close_instance("file");
++total;
} while(*++argv);
+ xo_close_list("file");
if (total > 1) {
+ xo_open_container("total");
if (doline)
- (void)printf(" %7ju", tlinect);
+ xo_emit(" {:lines/%7ju/%ju}", tlinect);
if (doword)
- (void)printf(" %7ju", twordct);
+ xo_emit(" {:words/%7ju/%ju", twordct);
if (dochar || domulti)
- (void)printf(" %7ju", tcharct);
+ xo_emit(" {:characters/%7ju/%ju}", tcharct);
if (dolongline)
- (void)printf(" %7ju", tlongline);
- (void)printf(" total\n");
+ xo_emit(" {:long-lines/%7ju/%ju}", tlongline);
+ xo_emit(" total\n");
+ xo_close_container("total");
}
+ xo_close_container("wc");
+ xo_flush();
exit(errors == 0 ? 0 : 1);
}
@@ -154,7 +167,7 @@
fd = STDIN_FILENO;
} else {
if ((fd = open(file, O_RDONLY, 0)) < 0) {
- warn("%s: open", file);
+ xo_warn("%s: open", file);
return (1);
}
if (doword || (domulti && MB_CUR_MAX != 1))
@@ -167,7 +180,7 @@
if (doline) {
while ((len = read(fd, buf, MAXBSIZE))) {
if (len == -1) {
- warn("%s: read", file);
+ xo_warn("%s: read", file);
(void)close(fd);
return (1);
}
@@ -182,15 +195,15 @@
tmpll++;
}
tlinect += linect;
- (void)printf(" %7ju", linect);
+ xo_emit(" {:lines/%7ju/%ju}", linect);
if (dochar) {
tcharct += charct;
- (void)printf(" %7ju", charct);
+ xo_emit(" {:characters/%7ju/%ju}", charct);
}
if (dolongline) {
if (llct > tlongline)
tlongline = llct;
- (void)printf(" %7ju", tlongline);
+ xo_emit(" {:long-lines/%7ju/%ju}", tlongline);
}
(void)close(fd);
return (0);
@@ -201,12 +214,13 @@
*/
if (dochar || domulti) {
if (fstat(fd, &sb)) {
- warn("%s: fstat", file);
+ xo_warn("%s: fstat", file);
(void)close(fd);
return (1);
}
if (S_ISREG(sb.st_mode)) {
- (void)printf(" %7lld", (long long)sb.st_size);
+ xo_emit(" {:characters/%7lld/%lld}",
+ (long long)sb.st_size);
tcharct += sb.st_size;
(void)close(fd);
return (0);
@@ -220,7 +234,7 @@
memset(&mbs, 0, sizeof(mbs));
while ((len = read(fd, buf, MAXBSIZE)) != 0) {
if (len == -1) {
- warn("%s: read", file);
+ xo_warn("%s: read", file);
(void)close(fd);
return (1);
}
@@ -233,7 +247,7 @@
(size_t)-1) {
if (!warned) {
errno = EILSEQ;
- warn("%s", file);
+ xo_warn("%s", file);
warned = 1;
}
memset(&mbs, 0, sizeof(mbs));
@@ -264,23 +278,23 @@
}
if (domulti && MB_CUR_MAX > 1)
if (mbrtowc(NULL, NULL, 0, &mbs) == (size_t)-1 && !warned)
- warn("%s", file);
+ xo_warn("%s", file);
if (doline) {
tlinect += linect;
- (void)printf(" %7ju", linect);
+ xo_emit(" {:lines/%7ju/%ju}", linect);
}
if (doword) {
twordct += wordct;
- (void)printf(" %7ju", wordct);
+ xo_emit(" {:words/%7ju/%ju}", wordct);
}
if (dochar || domulti) {
tcharct += charct;
- (void)printf(" %7ju", charct);
+ xo_emit(" {:characters/%7ju/%ju}", charct);
}
if (dolongline) {
if (llct > tlongline)
tlongline = llct;
- (void)printf(" %7ju", llct);
+ xo_emit(" {:long-lines/%7ju/%ju}", llct);
}
(void)close(fd);
return (0);
@@ -289,6 +303,6 @@
static void
usage()
{
- (void)fprintf(stderr, "usage: wc [-Lclmw] [file ...]\n");
+ xo_error("usage: wc [-Lclmw] [file ...]\n");
exit(1);
}
More information about the freebsd-arch
mailing list