1*983afe33SPhil Shafer 2*983afe33SPhil ShaferFormatting with libxo 3*983afe33SPhil Shafer===================== 4*983afe33SPhil Shafer 5*983afe33SPhil ShaferMost unix commands emit text output aimed at humans. It is designed 6*983afe33SPhil Shaferto be parsed and understood by a user. Humans are gifted at 7*983afe33SPhil Shaferextracting details and pattern matching in such output. Often 8*983afe33SPhil Shaferprogrammers need to extract information from this human-oriented 9*983afe33SPhil Shaferoutput. Programmers use tools like grep, awk, and regular expressions 10*983afe33SPhil Shaferto ferret out the pieces of information they need. Such solutions are 11*983afe33SPhil Shaferfragile and require maintenance when output contents change or evolve, 12*983afe33SPhil Shaferalong with testing and validation. 13*983afe33SPhil Shafer 14*983afe33SPhil ShaferModern tool developers favor encoding schemes like XML and JSON, 15*983afe33SPhil Shaferwhich allow trivial parsing and extraction of data. Such formats are 16*983afe33SPhil Shafersimple, well understood, hierarchical, easily parsed, and often 17*983afe33SPhil Shaferintegrate easier with common tools and environments. Changes to 18*983afe33SPhil Shafercontent can be done in ways that do not break existing users of the 19*983afe33SPhil Shaferdata, which can reduce maintenance costs and increase feature velocity. 20*983afe33SPhil Shafer 21*983afe33SPhil ShaferIn addition, modern reality means that more output ends up in web 22*983afe33SPhil Shaferbrowsers than in terminals, making HTML output valuable. 23*983afe33SPhil Shafer 24*983afe33SPhil Shaferlibxo allows a single set of function calls in source code to generate 25*983afe33SPhil Shafertraditional text output, as well as XML and JSON formatted data. HTML 26*983afe33SPhil Shafercan also be generated; "<div>" elements surround the traditional text 27*983afe33SPhil Shaferoutput, with attributes that detail how to render the data. 28*983afe33SPhil Shafer 29*983afe33SPhil ShaferA single libxo function call in source code is all that's required:: 30*983afe33SPhil Shafer 31*983afe33SPhil Shafer xo_emit("Connecting to {:host}.{:domain}...\n", host, domain); 32*983afe33SPhil Shafer 33*983afe33SPhil Shafer TEXT: 34*983afe33SPhil Shafer Connecting to my-box.example.com... 35*983afe33SPhil Shafer XML: 36*983afe33SPhil Shafer <host>my-box</host> 37*983afe33SPhil Shafer <domain>example.com</domain> 38*983afe33SPhil Shafer JSON: 39*983afe33SPhil Shafer "host": "my-box", 40*983afe33SPhil Shafer "domain": "example.com" 41*983afe33SPhil Shafer HTML: 42*983afe33SPhil Shafer <div class="line"> 43*983afe33SPhil Shafer <div class="text">Connecting to </div> 44*983afe33SPhil Shafer <div class="data" data-tag="host" 45*983afe33SPhil Shafer data-xpath="/top/host">my-box</div> 46*983afe33SPhil Shafer <div class="text">.</div> 47*983afe33SPhil Shafer <div class="data" data-tag="domain" 48*983afe33SPhil Shafer data-xpath="/top/domain">example.com</div> 49*983afe33SPhil Shafer <div class="text">...</div> 50*983afe33SPhil Shafer </div> 51*983afe33SPhil Shafer 52*983afe33SPhil ShaferEncoding Styles 53*983afe33SPhil Shafer--------------- 54*983afe33SPhil Shafer 55*983afe33SPhil ShaferThere are four encoding styles supported by libxo: 56*983afe33SPhil Shafer 57*983afe33SPhil Shafer- TEXT output can be display on a terminal session, allowing 58*983afe33SPhil Shafer compatibility with traditional command line usage. 59*983afe33SPhil Shafer- XML output is suitable for tools like XPath and protocols like 60*983afe33SPhil Shafer NETCONF. 61*983afe33SPhil Shafer- JSON output can be used for RESTful APIs and integration with 62*983afe33SPhil Shafer languages like Javascript and Python. 63*983afe33SPhil Shafer- HTML can be matched with a small CSS file to permit rendering in any 64*983afe33SPhil Shafer HTML5 browser. 65*983afe33SPhil Shafer 66*983afe33SPhil ShaferIn general, XML and JSON are suitable for encoding data, while TEXT is 67*983afe33SPhil Shafersuited for terminal output and HTML is suited for display in a web 68*983afe33SPhil Shaferbrowser (see :ref:`xohtml`). 69*983afe33SPhil Shafer 70*983afe33SPhil ShaferText Output 71*983afe33SPhil Shafer~~~~~~~~~~~ 72*983afe33SPhil Shafer 73*983afe33SPhil ShaferMost traditional programs generate text output on standard output, 74*983afe33SPhil Shaferwith contents like:: 75*983afe33SPhil Shafer 76*983afe33SPhil Shafer 36 ./src 77*983afe33SPhil Shafer 40 ./bin 78*983afe33SPhil Shafer 90 . 79*983afe33SPhil Shafer 80*983afe33SPhil ShaferIn this example (taken from *du* source code), the code to generate this 81*983afe33SPhil Shaferdata might look like:: 82*983afe33SPhil Shafer 83*983afe33SPhil Shafer printf("%d\t%s\n", num_blocks, path); 84*983afe33SPhil Shafer 85*983afe33SPhil ShaferSimple, direct, obvious. But it's only making text output. Imagine 86*983afe33SPhil Shaferusing a single code path to make TEXT, XML, JSON or HTML, deciding at 87*983afe33SPhil Shaferrun time which to generate. 88*983afe33SPhil Shafer 89*983afe33SPhil Shaferlibxo expands on the idea of printf format strings to make a single 90*983afe33SPhil Shaferformat containing instructions for creating multiple output styles:: 91*983afe33SPhil Shafer 92*983afe33SPhil Shafer xo_emit("{:blocks/%d}\t{:path/%s}\n", num_blocks, path); 93*983afe33SPhil Shafer 94*983afe33SPhil ShaferThis line will generate the same text output as the earlier printf 95*983afe33SPhil Shafercall, but also has enough information to generate XML, JSON, and HTML. 96*983afe33SPhil Shafer 97*983afe33SPhil ShaferThe following sections introduce the other formats. 98*983afe33SPhil Shafer 99*983afe33SPhil ShaferXML Output 100*983afe33SPhil Shafer~~~~~~~~~~ 101*983afe33SPhil Shafer 102*983afe33SPhil ShaferXML output consists of a hierarchical set of elements, each encoded 103*983afe33SPhil Shaferwith a start tag and an end tag. The element should be named for data 104*983afe33SPhil Shafervalue that it is encoding:: 105*983afe33SPhil Shafer 106*983afe33SPhil Shafer <item> 107*983afe33SPhil Shafer <blocks>36</blocks> 108*983afe33SPhil Shafer <path>./src</path> 109*983afe33SPhil Shafer </item> 110*983afe33SPhil Shafer <item> 111*983afe33SPhil Shafer <blocks>40</blocks> 112*983afe33SPhil Shafer <path>./bin</path> 113*983afe33SPhil Shafer </item> 114*983afe33SPhil Shafer <item> 115*983afe33SPhil Shafer <blocks>90</blocks> 116*983afe33SPhil Shafer <path>.</path> 117*983afe33SPhil Shafer </item> 118*983afe33SPhil Shafer 119*983afe33SPhil Shafer`XML`_ is the W3C standard for encoding data. 120*983afe33SPhil Shafer 121*983afe33SPhil Shafer.. _XML: https://w3c.org/TR/xml 122*983afe33SPhil Shafer 123*983afe33SPhil ShaferJSON Output 124*983afe33SPhil Shafer~~~~~~~~~~~ 125*983afe33SPhil Shafer 126*983afe33SPhil ShaferJSON output consists of a hierarchical set of objects and lists, each 127*983afe33SPhil Shaferencoded with a quoted name, a colon, and a value. If the value is a 128*983afe33SPhil Shaferstring, it must be quoted, but numbers are not quoted. Objects are 129*983afe33SPhil Shaferencoded using braces; lists are encoded using square brackets. 130*983afe33SPhil ShaferData inside objects and lists is separated using commas:: 131*983afe33SPhil Shafer 132*983afe33SPhil Shafer items: [ 133*983afe33SPhil Shafer { "blocks": 36, "path" : "./src" }, 134*983afe33SPhil Shafer { "blocks": 40, "path" : "./bin" }, 135*983afe33SPhil Shafer { "blocks": 90, "path" : "./" } 136*983afe33SPhil Shafer ] 137*983afe33SPhil Shafer 138*983afe33SPhil ShaferHTML Output 139*983afe33SPhil Shafer~~~~~~~~~~~ 140*983afe33SPhil Shafer 141*983afe33SPhil ShaferHTML output is designed to allow the output to be rendered in a web 142*983afe33SPhil Shaferbrowser with minimal effort. Each piece of output data is rendered 143*983afe33SPhil Shaferinside a <div> element, with a class name related to the role of the 144*983afe33SPhil Shaferdata. By using a small set of class attribute values, a CSS 145*983afe33SPhil Shaferstylesheet can render the HTML into rich text that mirrors the 146*983afe33SPhil Shafertraditional text content. 147*983afe33SPhil Shafer 148*983afe33SPhil ShaferAdditional attributes can be enabled to provide more details about the 149*983afe33SPhil Shaferdata, including data type, description, and an XPath location:: 150*983afe33SPhil Shafer 151*983afe33SPhil Shafer <div class="line"> 152*983afe33SPhil Shafer <div class="data" data-tag="blocks">36</div> 153*983afe33SPhil Shafer <div class="padding"> </div> 154*983afe33SPhil Shafer <div class="data" data-tag="path">./src</div> 155*983afe33SPhil Shafer </div> 156*983afe33SPhil Shafer <div class="line"> 157*983afe33SPhil Shafer <div class="data" data-tag="blocks">40</div> 158*983afe33SPhil Shafer <div class="padding"> </div> 159*983afe33SPhil Shafer <div class="data" data-tag="path">./bin</div> 160*983afe33SPhil Shafer </div> 161*983afe33SPhil Shafer <div class="line"> 162*983afe33SPhil Shafer <div class="data" data-tag="blocks">90</div> 163*983afe33SPhil Shafer <div class="padding"> </div> 164*983afe33SPhil Shafer <div class="data" data-tag="path">./</div> 165*983afe33SPhil Shafer </div> 166