The “xo” Utility¶
The xo
utility allows command line access to the functionality of
the libxo library. Using xo
, shell scripts can emit XML, JSON, and
HTML using the same commands that emit text output.
The style of output can be selected using a specific option: “-X” for XML, “-J” for JSON, “-H” for HTML, or “-T” for TEXT, which is the default. The “–style <style>” option can also be used. The standard set of “–libxo” options are available (see Command-line Arguments), as well as the LIBXO_OPTIONS environment variable.
The xo
utility accepts a format string suitable for xo_emit
and
a set of zero or more arguments used to supply data for that string:
xo "The {k:name} weighs {:weight/%d} pounds.\n" fish 6
TEXT:
The fish weighs 6 pounds.
XML:
<name>fish</name>
<weight>6</weight>
JSON:
"name": "fish",
"weight": 6
HTML:
<div class="line">
<div class="text">The </div>
<div class="data" data-tag="name">fish</div>
<div class="text"> weighs </div>
<div class="data" data-tag="weight">6</div>
<div class="text"> pounds.</div>
</div>
The --wrap $path
option can be used to wrap emitted content in a
specific hierarchy. The path is a set of hierarchical names separated
by the ‘/’ character:
xo --wrap top/a/b/c '{:tag}' value
XML:
<top>
<a>
<b>
<c>
<tag>value</tag>
</c>
</b>
</a>
</top>
JSON:
"top": {
"a": {
"b": {
"c": {
"tag": "value"
}
}
}
}
The --open $path
and --close $path
can be used to emit
hierarchical information without the matching close and open
tag. This allows a shell script to emit open tags, data, and
then close tags. The --depth
option may be used to set the
depth for indentation. The --leading-xpath
may be used to
prepend data to the XPath values used for HTML output style:
EXAMPLE:
#!/bin/sh
xo --open top/data
xo --depth 2 '{:tag}' value
xo --close top/data
XML:
<top>
<data>
<tag>value</tag>
</data>
</top>
JSON:
"top": {
"data": {
"tag": "value"
}
}
When making partial lines of output (where the format string does not
include a newline), use the --continuation
option to let secondary
invocations know they are adding data to an existing line.
When emitting a series of objects, use the --not-first
option to
ensure that any details from the previous object (e.g. commas in JSON)
are handled correctly.
Use the --top-wrap
option to ensure any top-level object details are
handled correctly, e.g. wrap the entire output in a top-level set of
braces for JSON output.
EXAMPLE:
#!/bin/sh
xo --top-wrap --open top/data
xo --depth 2 'First {:tag} ' value1
xo --depth 2 --continuation 'and then {:tag}\n' value2
xo --top-wrap --close top/data
TEXT:
First value1 and then value2
HTML:
<div class="line">
<div class="text">First </div>
<div class="data" data-tag="tag">value1</div>
<div class="text"> </div>
<div class="text">and then </div>
<div class="data" data-tag="tag">value2</div>
</div>
XML:
<top>
<data>
<tag>value1</tag>
<tag>value2</tag>
</data>
</top>
JSON:
{
"top": {
"data": {
"tag": "value1",
"tag": "value2"
}
}
}
Lists and Instances¶
A “list” is set of one or more instances that appear under the same parent. The instances contain details about a specific object. One can think of instances as objects or records. A call is needed to open and close the list, while a distinct call is needed to open and close each instance of the list.
Use the --open-list
and --open-instances
to open lists and
instances. Use the --close-list
and --close-instances
to close
them. Each of these options take a name
parameter, providing the
name of the list and instance.
In the following example, a list named “machine” is created with three instances:
opts="--json"
xo $opts --open-list machine
NF=
for name in red green blue; do
xo $opts --depth 1 $NF --open-instance machine
xo $opts --depth 2 "Machine {k:name} has {:memory}\n" $name 55
xo $opts --depth 1 --close-instance machine
NF=--not-first
done
xo $opts $NF --close-list machine
The normal libxo
functions use a state machine to help these
transitions, but since each xo
command is invoked independent of the
previous calls, the state must be passed in explicitly via these
command line options.
The --instance
option can be used to treat a single xo
invocation
as an instance with the given set of fields:
% xo --libxo:XP --instance foo 'The {:product} is {:status}\n' stereo "in route"
<foo>
<product>stereo</product>
<status>in route</status>
</foo>
Command Line Options¶
Usage: xo [options] format [fields]
--close <path> Close tags for the given path
--close-instance <name> Close an open instance name
--close-list <name> Close an open list name
--continuation OR -C Output belongs on same line as previous output
--depth <num> Set the depth for pretty printing
--help Display this help text
--html OR -H Generate HTML output
--instance OR -I <name> Wrap in an instance of the given name
--json OR -J Generate JSON output
--leading-xpath <path> Add a prefix to generated XPaths (HTML)
--not-first Indicate this object is not the first (JSON)
--open <path> Open tags for the given path
--open-instance <name> Open an instance given by name
--open-list <name> Open a list given by name
--option <opts> -or -O <opts> Give formatting options
--pretty OR -p Make 'pretty' output (add indent, newlines)
--style <style> Generate given style (xml, json, text, html)
--text OR -T Generate text output (the default style)
--top-wrap Generate a top-level object wrapper (JSON)
--version Display version information
--warn OR -W Display warnings in text on stderr
--warn-xml Display warnings in xml on stdout
--wrap <path> Wrap output in a set of containers
--xml OR -X Generate XML output
--xpath Add XPath data to HTML output)
Example¶
% xo 'The {:product} is {:status}\n' stereo "in route"
The stereo is in route
% xo -p -X 'The {:product} is {:status}\n' stereo "in route"
<product>stereo</product>
<status>in route</status>
% xo --libxo xml,pretty 'The {:product} is {:status}\n' stereo "in route"
<product>stereo</product>
<status>in route</status>