Merge commit '7087c8de43b0d5d27c52da6ba2ba4957b7e336ff' into new_merge

This commit is contained in:
Phil Shafer 2023-01-30 00:04:21 -05:00
commit 34b867ca30
75 changed files with 2325 additions and 778 deletions

View File

@ -1,46 +1,32 @@
# Object files
*.o
# Libraries
*.lib
*.a
# Shared objects (inc. Windows DLLs)
*.dll
*.so
*.so.*
*.dylib
# Executables
*.exe
*.app
*~
*.orig
tag.sh
Makefile.in
aclocal.m4
ar-lib
autom4te.cache
build
bin
build*
compile
configure
config.guess
config.h.in
config.sub
depcomp
doc/Makefile.in
info*
install-sh
ltmain.sh
missing
m4
Makefile.in
configure
.DS_Store
xoconfig.h.in
xo_config.h.in
.gdbinit
.gdbinit.local
xtest
xtest.dSYM
tests/w
missing
patches*
doc/Makefile.in
encoder/Makefile.in
encoder/cbor/Makefile.in
encoder/test/Makefile.in
libxo/Makefile.in
tests/Makefile.in
tests/core/Makefile.in
tests/gettext/Makefile.in
tests/xo/Makefile.in
xo/Makefile.in
xohtml/Makefile.in
xolint/Makefile.in
xopo/Makefile.in

View File

@ -1,18 +0,0 @@
Makefile.in
aclocal.m4
ar-lib
autom4te.cache
bin*
build*
compile
configure
config.guess
config.sub
depcomp
doc/Makefile.in
info*
install-sh
ltmain.sh
m4
missing
patches*

View File

@ -10,7 +10,7 @@
ACLOCAL_AMFLAGS = -I m4
SUBDIRS = libxo xo xopo xolint xohtml tests doc encoder
SUBDIRS = bin libxo xo xopo xolint xohtml tests doc encoder
bin_SCRIPTS=libxo-config
dist_doc_DATA = Copyright

View File

@ -11,8 +11,8 @@
# a particular user has the dist or svn release.
#
AC_PREREQ(2.2)
AC_INIT([libxo], [1.4.0], [phil@juniper.net])
AC_PREREQ([2.69])
AC_INIT([libxo],[1.6.0],[phil@juniper.net])
AM_INIT_AUTOMAKE([-Wall -Werror foreign -Wno-portability])
# Support silent build rules. Requires at least automake-1.11.
@ -38,8 +38,6 @@ AC_PATH_PROG(MV, mv, /bin/mv)
AC_PATH_PROG(RM, rm, /bin/rm)
AC_PATH_PROG(SED, sed, /bin/sed)
AC_STDC_HEADERS
# Checks for typedefs, structures, and compiler characteristics.
AC_C_INLINE
AC_TYPE_SIZE_T
@ -335,9 +333,10 @@ AM_CONDITIONAL([HAVE_LIBM], [test "$HAVE_LIBM" != "no"])
AC_MSG_CHECKING([compiler for gcc])
HAVE_GCC=no
if test "${CC}" != ""; then
HAVE_GCC=`${CC} --version 2>&1 | grep GCC`
HAVE_GCC=`${CC} --version 2>&1 | grep -i GCC`
if test "${HAVE_GCC}" != ""; then
HAVE_GCC=yes
AC_DEFINE([HAVE_GCC], [1], [Using real gcc])
else
HAVE_GCC=no
fi
@ -450,6 +449,7 @@ AC_CONFIG_FILES([
xohtml/xohtml.sh
libxo/Makefile
libxo/add.man
bin/Makefile
encoder/Makefile
encoder/cbor/Makefile
encoder/csv/Makefile

View File

@ -8,7 +8,7 @@
# using the SOFTWARE, you agree to be bound by the terms of that
# LICENSE.
doc docs: xolint.rst html
doc docs: xolint-errors.rst html
#
# The contents of xolint.rst is generated based on xolint.pl, since we
@ -17,8 +17,8 @@ doc docs: xolint.rst html
# the developer needs to commit any changes.
#
xolint.rst: ${top_srcdir}/xolint/xolint.pl
perl ${top_srcdir}/xolint/xolint.pl -D > ${top_srcdir}/doc/xolint.rst
xolint-errors.rst: ${top_srcdir}/xolint/xolint.pl
perl ${top_srcdir}/xolint/xolint.pl -D > ${top_srcdir}/doc/xolint-errors.rst
SPHINX = python3 -msphinx

View File

@ -386,19 +386,18 @@ xo_destroy
Emitting Content (xo_emit)
--------------------------
The functions in this section are used to emit output.
The "fmt" argument is a string containing field descriptors as
specified in :ref:`format-strings`. The use of a handle is optional and
`NULL` can be passed to access the internal "default" handle. See
The functions in this section are used to emit output. They use a
`format` string containing field descriptors as specified in
:ref:`format-strings`. The use of a handle is optional and `NULL` can
be passed to access the internal "default" handle. See
:ref:`handles`.
The remaining arguments to `xo_emit` and `xo_emit_h` are a set of
arguments corresponding to the fields in the format string. Care must
be taken to ensure the argument types match the fields in the format
string, since an inappropriate cast can ruin your day. The vap
argument to `xo_emit_hv` points to a variable argument list that can
be used to retrieve arguments via `va_arg`.
string, since an inappropriate or missing argument can ruin your day.
The `vap` argument to `xo_emit_hv` points to a variable argument list
that can be used to retrieve arguments via `va_arg`.
.. c:function:: xo_ssize_t xo_emit (const char *fmt, ...)
@ -428,19 +427,40 @@ be used to retrieve arguments via `va_arg`.
Single Field Emitting Functions (xo_emit_field)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The functions in this section can also make output, but only make a
single field at a time. These functions are intended to avoid the
scenario where one would otherwise need to compose a format
descriptors using `snprintf`. The individual parts of the format
descriptor are passed in distinctly.
The functions in this section emit formatted output similar to
`xo_emit` but where `xo_emit` uses a single string argument containing
the description for multiple fields, `xo_emit_field` emits a single
field using multiple ar- guments to contain the field description.
`xo_emit_field_h` adds an ex- plicit handle to use instead of the
default handle, while `xo_emit_field_hv` accepts a va_list for
additional flexibility.
.. c:function:: xo_ssize_t xo_emit_field (const char *rolmod, const char *contents, const char *fmt, const char *efmt, ...)
The arguments `rolmod`, `content`, `fmt`, and `efmt` are detailed in
:ref:`field-formatting`. Using distinct arguments allows callers to
pass the field description in pieces, rather than having to use
something like `snprintf` to build the format string required by
`xo_emit`. The arguments are each NUL-terminated strings. The `rolmod`
argument contains the `role` and `modifier` portions of the field
description, the `content` argument contains the `content` portion, and
the `fmt` and `efmt` contain the `field-format` and `encoding-format` por-
tions, respectively.
As with `xo_emit`, the `fmt` and `efmt` values are both optional,
since the `field-format` string defaults to "%s", and the
`encoding-format`'s default value is derived from the `field-format`
per :ref:`field-formatting`. However, care must be taken to avoid
using a value directly as the format, since characters like '{', '%',
and '}' will be interpreted as formatting directives, and may cause
xo_emit_field to dereference arbitrary values off the stack, leading
to bugs, core files, and gnashing of teeth.
.. c:function:: xo_ssize_t xo_emit_field (const char *rolmod, const char *content, const char *fmt, const char *efmt, ...)
:param rolmod: A comma-separated list of field roles and field modifiers
:type rolmod: const char *
:param contents: The "contents" portion of the field description string
:type contents: const char *
:param fmt: Content format string
:param content: The "content" portion of the field description string
:type content: const char *
:param fmt: Contents format string
:type fmt: const char *
:param efmt: Encoding format string, followed by additional arguments
:type efmt: const char *
@ -450,8 +470,11 @@ descriptor are passed in distinctly.
::
EXAMPLE::
xo_emit_field("T", title, NULL, NULL, NULL);
xo_emit_field("T", "Host name is ", NULL, NULL);
xo_emit_field("V", "host-name", NULL, NULL, host-name);
xo_emit_field(",leaf-list,quotes", "sku", "%s-%u", "%s-000-%u",
"gum", 1412);
.. c:function:: xo_ssize_t xo_emit_field_h (xo_handle_t *xop, const char *rolmod, const char *contents, const char *fmt, const char *efmt, ...)

View File

@ -205,4 +205,7 @@ a difference, change the names to make that difference more obvious.
What does this message mean?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. include:: xolint.rst
.. toctree::
:maxdepth: 2
xolint-errors.rst

View File

@ -1,5 +1,6 @@
.. index:: Field Formatting
.. _field-formatting:
Field Formatting
----------------

View File

@ -180,6 +180,11 @@ Labels are text that appears before a value::
xo_emit("{Lwc:Cost}{:cost/%u}\n", cost);
If a label needs to include a slash, it must be escaped using two
backslashes, one for the C compiler and one for libxo::
xo_emit("{Lc:Low\\/warn level}{:level/%s}\n", level);
.. index:: Field Roles; Note
.. _note-role:

View File

@ -0,0 +1,444 @@
'A percent sign appearing in text is a literal'
+++++++++++++++++++++++++++++++++++++++++++++++
The message "A percent sign appearing in text is a literal" can be caused by code like:
::
xo_emit("cost: %d", cost);
This code should be replaced with code like:
::
xo_emit("{L:cost}: {:cost/%d}", cost);
This can be a bit surprising and could be a field that was not
properly converted to a libxo-style format string.
'Unknown long name for role/modifier'
+++++++++++++++++++++++++++++++++++++
The message "Unknown long name for role/modifier" can be caused by code like:
::
xo_emit("{,humanization:value}", value);
This code should be replaced with code like:
::
xo_emit("{,humanize:value}", value);
The hn-* modifiers (hn-decimal, hn-space, hn-1000)
are only valid for fields with the {h:} modifier.
'Last character before field definition is a field type'
++++++++++++++++++++++++++++++++++++++++++++++++++++++++
The message "Last character before field definition is a field type" can be caused by code like:
A common typo:
::
xo_emit("{T:Min} T{:Max}");
This code should be replaced with code like:
::
xo_emit("{T:Min} {T:Max}");
Twiddling the "{" and the field role is a common typo.
'Encoding format uses different number of arguments'
++++++++++++++++++++++++++++++++++++++++++++++++++++
The message "Encoding format uses different number of arguments" can be caused by code like:
::
xo_emit("{:name/%6.6s %%04d/%s}", name, number);
This code should be replaced with code like:
::
xo_emit("{:name/%6.6s %04d/%s-%d}", name, number);
Both format should consume the same number of arguments off the stack
'Only one field role can be used'
+++++++++++++++++++++++++++++++++
The message "Only one field role can be used" can be caused by code like:
::
xo_emit("{LT:Max}");
This code should be replaced with code like:
::
xo_emit("{T:Max}");
'Potential missing slash after C, D, N, L, or T with format'
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
The message "Potential missing slash after C, D, N, L, or T with format" can be caused by code like:
::
xo_emit("{T:%6.6s}\n", "Max");
This code should be replaced with code like:
::
xo_emit("{T:/%6.6s}\n", "Max");
The "%6.6s" will be a literal, not a field format. While
it's possibly valid, it's likely a missing "/".
'An encoding format cannot be given (roles: DNLT)'
++++++++++++++++++++++++++++++++++++++++++++++++++
The message "An encoding format cannot be given (roles: DNLT)" can be caused by code like:
::
xo_emit("{T:Max//%s}", "Max");
Fields with the C, D, N, L, and T roles are not emitted in
the 'encoding' style (JSON, XML), so an encoding format
would make no sense.
'Format cannot be given when content is present (roles: CDLN)'
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
The message "Format cannot be given when content is present (roles: CDLN)" can be caused by code like:
::
xo_emit("{N:Max/%6.6s}", "Max");
Fields with the C, D, L, or N roles can't have both
static literal content ("{L:Label}") and a
format ("{L:/%s}").
This error will also occur when the content has a backslash
in it, like "{N:Type of I/O}"; backslashes should be escaped,
like "{N:Type of I\\/O}". Note the double backslash, one for
handling 'C' strings, and one for libxo.
'Field has color without fg- or bg- (role: C)'
++++++++++++++++++++++++++++++++++++++++++++++
The message "Field has color without fg- or bg- (role: C)" can be caused by code like:
::
xo_emit("{C:green}{:foo}{C:}", x);
This code should be replaced with code like:
::
xo_emit("{C:fg-green}{:foo}{C:}", x);
Colors must be prefixed by either "fg-" or "bg-".
'Field has invalid color or effect (role: C)'
+++++++++++++++++++++++++++++++++++++++++++++
The message "Field has invalid color or effect (role: C)" can be caused by code like:
::
xo_emit("{C:fg-purple,bold}{:foo}{C:gween}", x);
This code should be replaced with code like:
::
xo_emit("{C:fg-red,bold}{:foo}{C:fg-green}", x);
The list of colors and effects are limited. The
set of colors includes default, black, red, green,
yellow, blue, magenta, cyan, and white, which must
be prefixed by either "fg-" or "bg-". Effects are
limited to bold, no-bold, underline, no-underline,
inverse, no-inverse, normal, and reset. Values must
be separated by commas.
'Field has humanize modifier but no format string'
++++++++++++++++++++++++++++++++++++++++++++++++++
The message "Field has humanize modifier but no format string" can be caused by code like:
::
xo_emit("{h:value}", value);
This code should be replaced with code like:
::
xo_emit("{h:value/%d}", value);
Humanization is only value for numbers, which are not
likely to use the default format ("%s").
'Field has hn-* modifier but not 'h' modifier'
++++++++++++++++++++++++++++++++++++++++++++++
The message "Field has hn-* modifier but not 'h' modifier" can be caused by code like:
::
xo_emit("{,hn-1000:value}", value);
This code should be replaced with code like:
::
xo_emit("{h,hn-1000:value}", value);
The hn-* modifiers (hn-decimal, hn-space, hn-1000)
are only valid for fields with the {h:} modifier.
'Value field must have a name (as content)")'
+++++++++++++++++++++++++++++++++++++++++++++
The message "Value field must have a name (as content)")" can be caused by code like:
::
xo_emit("{:/%s}", "value");
This code should be replaced with code like:
::
xo_emit("{:tag-name/%s}", "value");
The field name is used for XML and JSON encodings. These
tags names are static and must appear directly in the
field descriptor.
'Use hyphens, not underscores, for value field name'
++++++++++++++++++++++++++++++++++++++++++++++++++++
The message "Use hyphens, not underscores, for value field name" can be caused by code like:
::
xo_emit("{:no_under_scores}", "bad");
This code should be replaced with code like:
::
xo_emit("{:no-under-scores}", "bad");
Use of hyphens is traditional in XML, and the XOF_UNDERSCORES
flag can be used to generate underscores in JSON, if desired.
But the raw field name should use hyphens.
'Value field name cannot start with digit'
++++++++++++++++++++++++++++++++++++++++++
The message "Value field name cannot start with digit" can be caused by code like:
::
xo_emit("{:10-gig/}");
This code should be replaced with code like:
::
xo_emit("{:ten-gig/}");
XML element names cannot start with a digit.
'Value field name should be lower case'
+++++++++++++++++++++++++++++++++++++++
The message "Value field name should be lower case" can be caused by code like:
::
xo_emit("{:WHY-ARE-YOU-SHOUTING}", "NO REASON");
This code should be replaced with code like:
::
xo_emit("{:why-are-you-shouting}", "no reason");
Lower case is more civilized. Even TLAs should be lower case
to avoid scenarios where the differences between "XPath" and
"Xpath" drive your users crazy. Lower case rules the seas.
'Value field name should be longer than two characters'
+++++++++++++++++++++++++++++++++++++++++++++++++++++++
The message "Value field name should be longer than two characters" can be caused by code like:
::
xo_emit("{:x}", "mumble");
This code should be replaced with code like:
::
xo_emit("{:something-meaningful}", "mumble");
Field names should be descriptive, and it's hard to
be descriptive in less than two characters. Consider
your users and try to make something more useful.
Note that this error often occurs when the field type
is placed after the colon ("{:T/%20s}"), instead of before
it ("{T:/20s}").
'Value field name contains invalid character'
+++++++++++++++++++++++++++++++++++++++++++++
The message "Value field name contains invalid character" can be caused by code like:
::
xo_emit("{:cost-in-$$/%u}", 15);
This code should be replaced with code like:
::
xo_emit("{:cost-in-dollars/%u}", 15);
An invalid character is often a sign of a typo, like "{:]}"
instead of "{]:}". Field names are restricted to lower-case
characters, digits, and hyphens.
'decoration field contains invalid character'
+++++++++++++++++++++++++++++++++++++++++++++
The message "decoration field contains invalid character" can be caused by code like:
::
xo_emit("{D:not good}");
This code should be replaced with code like:
::
xo_emit("{D:((}{:good}{D:))}", "yes");
This is minor, but fields should use proper roles. Decoration
fields are meant to hold punctuation and other characters used
to decorate the content, typically to make it more readable
to human readers.
'Anchor content should be decimal width'
++++++++++++++++++++++++++++++++++++++++
The message "Anchor content should be decimal width" can be caused by code like:
::
xo_emit("{[:mumble}");
This code should be replaced with code like:
::
xo_emit("{[:32}");
Anchors need an integer value to specify the width of
the set of anchored fields. The value can be positive
(for left padding/right justification) or negative (for
right padding/left justification) and can appear in
either the start or stop anchor field descriptor.
'Anchor format should be "%d"'
++++++++++++++++++++++++++++++
The message "Anchor format should be "%d"" can be caused by code like:
::
xo_emit("{[:/%s}");
This code should be replaced with code like:
::
xo_emit("{[:/%d}");
Anchors only grok integer values, and if the value is not static,
if must be in an 'int' argument, represented by the "%d" format.
Anything else is an error.
'Anchor cannot have both format and encoding format")'
++++++++++++++++++++++++++++++++++++++++++++++++++++++
The message "Anchor cannot have both format and encoding format")" can be caused by code like:
::
xo_emit("{[:32/%d}");
This code should be replaced with code like:
::
xo_emit("{[:32}");
Anchors can have a static value or argument for the width,
but cannot have both.
'Max width only valid for strings'
++++++++++++++++++++++++++++++++++
The message "Max width only valid for strings" can be caused by code like:
::
xo_emit("{:tag/%2.4.6d}", 55);
This code should be replaced with code like:
::
xo_emit("{:tag/%2.6d}", 55);
libxo allows a true 'max width' in addition to the traditional
printf-style 'max number of bytes to use for input'. But this
is supported only for string values, since it makes no sense
for non-strings. This error may occur from a typo,
like "{:tag/%6..6d}" where only one period should be used.

View File

@ -1,444 +1,40 @@
'A percent sign appearing in text is a literal'
+++++++++++++++++++++++++++++++++++++++++++++++
The message "A percent sign appearing in text is a literal" can be caused by code like:
::
xo_emit("cost: %d", cost);
This code should be replaced with code like:
::
xo_emit("{L:cost}: {:cost/%d}", cost);
This can be a bit surprising and could be a field that was not
properly converted to a libxo-style format string.
'Unknown long name for role/modifier'
+++++++++++++++++++++++++++++++++++++
The message "Unknown long name for role/modifier" can be caused by code like:
::
xo_emit("{,humanization:value}", value);
This code should be replaced with code like:
::
xo_emit("{,humanize:value}", value);
The hn-* modifiers (hn-decimal, hn-space, hn-1000)
are only valid for fields with the {h:} modifier.
'Last character before field definition is a field type'
++++++++++++++++++++++++++++++++++++++++++++++++++++++++
The message "Last character before field definition is a field type" can be caused by code like:
A common typo:
::
xo_emit("{T:Min} T{:Max}");
This code should be replaced with code like:
::
xo_emit("{T:Min} {T:Max}");
Twiddling the "{" and the field role is a common typo.
'Encoding format uses different number of arguments'
++++++++++++++++++++++++++++++++++++++++++++++++++++
The message "Encoding format uses different number of arguments" can be caused by code like:
::
xo_emit("{:name/%6.6s %%04d/%s}", name, number);
This code should be replaced with code like:
::
xo_emit("{:name/%6.6s %04d/%s-%d}", name, number);
Both format should consume the same number of arguments off the stack
'Only one field role can be used'
+++++++++++++++++++++++++++++++++
The message "Only one field role can be used" can be caused by code like:
::
xo_emit("{LT:Max}");
This code should be replaced with code like:
::
xo_emit("{T:Max}");
'Potential missing slash after C, D, N, L, or T with format'
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
The message "Potential missing slash after C, D, N, L, or T with format" can be caused by code like:
::
xo_emit("{T:%6.6s}\n", "Max");
This code should be replaced with code like:
::
xo_emit("{T:/%6.6s}\n", "Max");
The "%6.6s" will be a literal, not a field format. While
it's possibly valid, it's likely a missing "/".
'An encoding format cannot be given (roles: DNLT)'
++++++++++++++++++++++++++++++++++++++++++++++++++
The message "An encoding format cannot be given (roles: DNLT)" can be caused by code like:
::
xo_emit("{T:Max//%s}", "Max");
Fields with the C, D, N, L, and T roles are not emitted in
the 'encoding' style (JSON, XML), so an encoding format
would make no sense.
'Format cannot be given when content is present (roles: CDLN)'
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
The message "Format cannot be given when content is present (roles: CDLN)" can be caused by code like:
::
xo_emit("{N:Max/%6.6s}", "Max");
Fields with the C, D, L, or N roles can't have both
static literal content ("{L:Label}") and a
format ("{L:/%s}").
This error will also occur when the content has a backslash
in it, like "{N:Type of I/O}"; backslashes should be escaped,
like "{N:Type of I\\/O}". Note the double backslash, one for
handling 'C' strings, and one for libxo.
'Field has color without fg- or bg- (role: C)'
++++++++++++++++++++++++++++++++++++++++++++++
The message "Field has color without fg- or bg- (role: C)" can be caused by code like:
::
xo_emit("{C:green}{:foo}{C:}", x);
This code should be replaced with code like:
::
xo_emit("{C:fg-green}{:foo}{C:}", x);
Colors must be prefixed by either "fg-" or "bg-".
'Field has invalid color or effect (role: C)'
+++++++++++++++++++++++++++++++++++++++++++++
The message "Field has invalid color or effect (role: C)" can be caused by code like:
::
xo_emit("{C:fg-purple,bold}{:foo}{C:gween}", x);
This code should be replaced with code like:
::
xo_emit("{C:fg-red,bold}{:foo}{C:fg-green}", x);
The list of colors and effects are limited. The
set of colors includes default, black, red, green,
yellow, blue, magenta, cyan, and white, which must
be prefixed by either "fg-" or "bg-". Effects are
limited to bold, no-bold, underline, no-underline,
inverse, no-inverse, normal, and reset. Values must
be separated by commas.
'Field has humanize modifier but no format string'
++++++++++++++++++++++++++++++++++++++++++++++++++
The message "Field has humanize modifier but no format string" can be caused by code like:
::
xo_emit("{h:value}", value);
This code should be replaced with code like:
::
xo_emit("{h:value/%d}", value);
Humanization is only value for numbers, which are not
likely to use the default format ("%s").
'Field has hn-* modifier but not 'h' modifier'
++++++++++++++++++++++++++++++++++++++++++++++
The message "Field has hn-* modifier but not 'h' modifier" can be caused by code like:
::
xo_emit("{,hn-1000:value}", value);
This code should be replaced with code like:
::
xo_emit("{h,hn-1000:value}", value);
The hn-* modifiers (hn-decimal, hn-space, hn-1000)
are only valid for fields with the {h:} modifier.
'Value field must have a name (as content)")'
+++++++++++++++++++++++++++++++++++++++++++++
The message "Value field must have a name (as content)")" can be caused by code like:
::
xo_emit("{:/%s}", "value");
This code should be replaced with code like:
::
xo_emit("{:tag-name/%s}", "value");
The field name is used for XML and JSON encodings. These
tags names are static and must appear directly in the
field descriptor.
'Use hyphens, not underscores, for value field name'
++++++++++++++++++++++++++++++++++++++++++++++++++++
The message "Use hyphens, not underscores, for value field name" can be caused by code like:
::
xo_emit("{:no_under_scores}", "bad");
This code should be replaced with code like:
::
xo_emit("{:no-under-scores}", "bad");
Use of hyphens is traditional in XML, and the XOF_UNDERSCORES
flag can be used to generate underscores in JSON, if desired.
But the raw field name should use hyphens.
'Value field name cannot start with digit'
++++++++++++++++++++++++++++++++++++++++++
The message "Value field name cannot start with digit" can be caused by code like:
::
xo_emit("{:10-gig/}");
This code should be replaced with code like:
::
xo_emit("{:ten-gig/}");
XML element names cannot start with a digit.
'Value field name should be lower case'
+++++++++++++++++++++++++++++++++++++++
The message "Value field name should be lower case" can be caused by code like:
::
xo_emit("{:WHY-ARE-YOU-SHOUTING}", "NO REASON");
This code should be replaced with code like:
::
xo_emit("{:why-are-you-shouting}", "no reason");
Lower case is more civilized. Even TLAs should be lower case
to avoid scenarios where the differences between "XPath" and
"Xpath" drive your users crazy. Lower case rules the seas.
'Value field name should be longer than two characters'
+++++++++++++++++++++++++++++++++++++++++++++++++++++++
The message "Value field name should be longer than two characters" can be caused by code like:
::
xo_emit("{:x}", "mumble");
This code should be replaced with code like:
::
xo_emit("{:something-meaningful}", "mumble");
Field names should be descriptive, and it's hard to
be descriptive in less than two characters. Consider
your users and try to make something more useful.
Note that this error often occurs when the field type
is placed after the colon ("{:T/%20s}"), instead of before
it ("{T:/20s}").
'Value field name contains invalid character'
+++++++++++++++++++++++++++++++++++++++++++++
The message "Value field name contains invalid character" can be caused by code like:
::
xo_emit("{:cost-in-$$/%u}", 15);
This code should be replaced with code like:
::
xo_emit("{:cost-in-dollars/%u}", 15);
An invalid character is often a sign of a typo, like "{:]}"
instead of "{]:}". Field names are restricted to lower-case
characters, digits, and hyphens.
'decoration field contains invalid character'
+++++++++++++++++++++++++++++++++++++++++++++
The message "decoration field contains invalid character" can be caused by code like:
::
xo_emit("{D:not good}");
This code should be replaced with code like:
::
xo_emit("{D:((}{:good}{D:))}", "yes");
This is minor, but fields should use proper roles. Decoration
fields are meant to hold punctuation and other characters used
to decorate the content, typically to make it more readable
to human readers.
'Anchor content should be decimal width'
++++++++++++++++++++++++++++++++++++++++
The message "Anchor content should be decimal width" can be caused by code like:
::
xo_emit("{[:mumble}");
This code should be replaced with code like:
::
xo_emit("{[:32}");
Anchors need an integer value to specify the width of
the set of anchored fields. The value can be positive
(for left padding/right justification) or negative (for
right padding/left justification) and can appear in
either the start or stop anchor field descriptor.
'Anchor format should be "%d"'
++++++++++++++++++++++++++++++
The message "Anchor format should be "%d"" can be caused by code like:
::
xo_emit("{[:/%s}");
This code should be replaced with code like:
::
xo_emit("{[:/%d}");
Anchors only grok integer values, and if the value is not static,
if must be in an 'int' argument, represented by the "%d" format.
Anything else is an error.
'Anchor cannot have both format and encoding format")'
++++++++++++++++++++++++++++++++++++++++++++++++++++++
The message "Anchor cannot have both format and encoding format")" can be caused by code like:
::
xo_emit("{[:32/%d}");
This code should be replaced with code like:
::
xo_emit("{[:32}");
Anchors can have a static value or argument for the width,
but cannot have both.
'Max width only valid for strings'
++++++++++++++++++++++++++++++++++
The message "Max width only valid for strings" can be caused by code like:
::
xo_emit("{:tag/%2.4.6d}", 55);
This code should be replaced with code like:
::
xo_emit("{:tag/%2.6d}", 55);
libxo allows a true 'max width' in addition to the traditional
printf-style 'max number of bytes to use for input'. But this
is supported only for string values, since it makes no sense
for non-strings. This error may occur from a typo,
like "{:tag/%6..6d}" where only one period should be used.
======
xolint
======
`xolint` is a tool for reporting common mistakes in format strings
in source code that invokes `xo_emit`. It allows these errors
to be diagnosed at build time, rather than waiting until runtime.
`xolint` takes the one or more C files as arguments, and reports
and errors, warning, or informational messages as needed:
============ ===================================================
Option Meaning
============ ===================================================
-c Invoke 'cpp' against the input file
-C <flags> Flags that are passed to 'cpp
-d Enable debug output
-D Generate documentation for all xolint messages
-I Generate info table code
-p Print the offending lines after the message
-V Print vocabulary of all field names
-X Extract samples from xolint, suitable for testing
============ ===================================================
The output message will contain the source filename and line number, the
class of the message, the message, and, if -p is given, the
line that contains the error::
% xolint.pl -t xolint.c
xolint.c: 16: error: anchor format should be "%d"
16 xo_emit("{[:/%s}");
The "-I" option will generate a table of `xo_info_t`_ structures,
suitable for inclusion in source code.
.. _xo_info_t: :ref:`field-information`
The "-V" option does not report errors, but prints a complete list of
all field names, sorted alphabetically. The output can help spot
inconsistencies and spelling errors.

View File

@ -74,6 +74,7 @@ man5_files = \
xo_format.5
man7_files = \
libxo-csv.7 \
xo_options.7
man_MANS = ${man3_files} ${man5_files} ${man7_files}

0
contrib/libxo/libxo/gen-wide.sh Executable file → Normal file
View File

View File

@ -0,0 +1,274 @@
.\" #
.\" # Copyright (c) 2021, Juniper Networks, Inc.
.\" # All rights reserved.
.\" # This SOFTWARE is licensed under the LICENSE provided in the
.\" # ../Copyright file. By downloading, installing, copying, or
.\" # using the SOFTWARE, you agree to be bound by the terms of that
.\" # LICENSE.
.\" # Phil Shafer, May 2021
.\"
.Dd May 13, 2021
.Dt LIBXO-CSV 7
.Os
.Sh NAME
.Nm --libxo encoder=csv[+options]
.Nd a CVS encoder for libxo\-based commands
.Sh DESCRIPTION
The
.Nm libxo
library supports a "pluggable" encoder mechanism, and ships with an
encoder for CSV (comma separated values) files. The encoder allows
paths and fields to be selected out of the output contents:
.Bd -literal -offset indent
% df --libxo @csv
name,total-blocks,used-blocks,available-blocks,used-percent,mounted-on
zroot/ROOT/default,3825984331,29376725,3796607605,1,/
devfs,1,1,0,100,/dev
zroot/usr/home,3808301289,11693684,3796607605,0,/usr/home
zroot/var/audit,3796607806,201,3796607605,0,/var/audit
...
% df --libxo @csv+leafs=name.used-percent
name,used-percent
zroot/ROOT/default,1
devfs,100
zroot/usr/home,0
zroot/var/audit,0
...
% df --libxo @csv+leafs=available-blocks+no-header /
3796607605
.Ed
contains software to generate four "built-in"
formats: text, XML, JSON, and HTML.
These formats are common and useful, but there are other common and
useful formats that users will want, and including them all in the
libxo software would be difficult and cumbersome.
.Pp
To allow support for additional encodings, libxo includes a
"pluggable" extension mechanism for dynamically loading new encoders.
.Nm libxo -based
applications can automatically use any installed encoder.
.Pp
Use the "encoder=XXX" option to access encoders. The following
example uses the "cbor" encoder, saving the output into a file:
.Bd -literal -offset indent
df --libxo encoder=cbor > df-output.cbor
.Ed
.Pp
Encoders can support specific options that can be accessed by
following the encoder name with a colon (':') or a plus sign ('+') and
one of more options, separated by the same character:
.Bd -literal -offset indent
df --libxo encoder=csv+path=filesystem+leaf=name+no-header
df --libxo encoder=csv:path=filesystem:leaf=name:no-header
.Ed
.Pp
These examples instructs libxo to load the "csv" encoder and pass the
following options:
.Bd -literal -offset indent
path=filesystem
leaf=name
no-header
.Ed
.Pp
Each of these option is interpreted by the encoder, and all such
options names and semantics are specific to the particular encoder.
Refer to the intended encoder for documentation on its options.
.Pp
The string "@" can be used in place of the string "encoder=".
.Bd -literal -offset indent
df --libxo @csv:no-header
.Ed
.Sh The CSV (Comma Separated Values) Encoder
.Nm libxo
ships with a custom encoder for "CSV" files, a common format for
comma separated values. The output of the CSV encoder can be loaded
directly into spreadsheets or similar applications.
.Pp
A standard for CSV files is provided in RFC 4180, but since the
format predates that standard by decades, there are many minor
differences in CSV file consumers and their expectations. The CSV
encoder has a number of options to tailor output to those
expectations.
.Pp
Consider the following XML:
.Bd -literal -offset indent
% list-items --libxo xml,pretty
<top>
<data test="value">
<item test2="value2">
<sku test3="value3" key="key">GRO-000-415</sku>
<name key="key">gum</name>
<sold>1412</sold>
<in-stock>54</in-stock>
<on-order>10</on-order>
</item>
<item>
<sku test3="value3" key="key">HRD-000-212</sku>
<name key="key">rope</name>
<sold>85</sold>
<in-stock>4</in-stock>
<on-order>2</on-order>
</item>
<item>
<sku test3="value3" key="key">HRD-000-517</sku>
<name key="key">ladder</name>
<sold>0</sold>
<in-stock>2</in-stock>
<on-order>1</on-order>
</item>
</data>
</top>
.Ed
.Pp
This output is a list of `instances` (named "item"), each containing a
set of `leafs` ("sku", "name", etc).
.Pp
The CSV encoder will emit the leaf values in this output as `fields`
inside a CSV `record`, which is a line containing a set of
comma-separated values:
.Bd -literal -offset indent
% list-items --libxo encoder=csv
sku,name,sold,in-stock,on-order
GRO-000-415,gum,1412,54,10
HRD-000-212,rope,85,4,2
HRD-000-517,ladder,0,2,1
.Ed
.Pp
Be aware that since the CSV encoder looks for data instances, when
used with
.Nm xo ,
the `--instance` option will be needed:
.Bd -literal -offset indent
% xo --libxo encoder=csv --instance foo 'The {:product} is {:status}\n' stereo "in route"
product,status
stereo,in route
.Ed
.Sh The "path" Option
By default, the CSV encoder will attempt to emit any list instance
generated by the application.
In some cases, this may be unacceptable, and a specific list may be
desired.
.Pp
Use the "path" option to limit the processing of output to a specific
hierarchy. The path should be one or more names of containers or
lists.
.Pp
For example, if the "list-items" application generates other lists,
the user can give "path=top/data/item" as a path:
.Bd -literal -offset indent
% list-items --libxo encoder=csv:path=top/data/item
sku,name,sold,in-stock,on-order
GRO-000-415,gum,1412,54,10
HRD-000-212,rope,85,4,2
HRD-000-517,ladder,0,2,1
.Ed
.Pp
Paths are "relative", meaning they need not be a complete set
of names to the list. This means that "path=item" may be sufficient
for the above example.
.Sh The "leafs" Option
The CSV encoding requires that all lines of output have the same
number of fields with the same order. In contrast, XML and JSON allow
any order (though libxo forces key leafs to appear before other
leafs).
.Pp
To maintain a consistent set of fields inside the CSV file, the same
set of leafs must be selected from each list item. By default, the
CSV encoder records the set of leafs that appear in the first list
instance it processes, and extract only those leafs from future
instances. If the first instance is missing a leaf that is desired by
the consumer, the "leaf" option can be used to ensure that an empty
value is recorded for instances that lack a particular leaf.
.Pp
The "leafs" option can also be used to exclude leafs, limiting the
output to only those leafs provided.
.Pp
In addition, the order of the output fields follows the order in which
the leafs are listed. "leafs=one.two" and "leafs=two.one" give
distinct output.
.Pp
So the "leafs" option can be used to expand, limit, and order the set
of leafs.
.Pp
The value of the leafs option should be one or more leaf names,
separated by a period ("."):
.Bd -literal -offset indent
% list-items --libxo encoder=csv:leafs=sku.on-order
sku,on-order
GRO-000-415,10
HRD-000-212,2
HRD-000-517,1
% list-items -libxo encoder=csv:leafs=on-order.sku
on-order,sku
10,GRO-000-415
2,HRD-000-212
1,HRD-000-517
.Ed
.Pp
Note that since libxo uses terminology from YANG (:RFC:`7950`), the
data modeling language for NETCONF (:RFC:`6241`), which uses "leafs"
as the plural form of "leaf". libxo follows that convention.
.Sh The "no-header" Option
CSV files typical begin with a line that defines the fields included
in that file, in an attempt to make the contents self-defining:
.Bd -literal -offset indent
sku,name,sold,in-stock,on-order
GRO-000-415,gum,1412,54,10
HRD-000-212,rope,85,4,2
HRD-000-517,ladder,0,2,1
.Ed
.Pp
There is no reliable mechanism for determining whether this header
line is included, so the consumer must make an assumption.
.Pp
The csv encoder defaults to producing the header line, but the
"no-header" option can be included to avoid the header line.
.Sh The "no-quotes" Option
RFC 4180 specifies that fields containing spaces should be quoted, but
many CSV consumers do not handle quotes. The "no-quotes" option
instruct the CSV encoder to avoid the use of quotes.
.Sh The "dos" Option
RFC 4180 defines the end-of-line marker as a carriage return
followed by a newline. This "CRLF" convention dates from the distant
past, but its use was anchored in the 1980s by the `DOS` operating
system.
.Pp
The CSV encoder defaults to using the standard Unix end-of-line
marker, a simple newline. Use the "dos" option to use the `CRLF`
convention.
.Sh Option Handling
The handling of command-line options is complex, since there are three
hierarchies in use, but the rules are:
.Bl -bullet
.It
commas separate
.Nm libxo
options
.Bd -literal -ofset indent
\-\-libxo json,pretty,warn
.Ed
.It
pluses separate encoder options
.Bd -literal -ofset indent
\-\-libxo @csv+dos+no-header,warn
.Ed
.It
periods separate tag names
.Bd -literal -ofset indent
\-\-libxo @csv+leafs=name.used.free+dos,warn
.El
.Sh SEE ALSO
.Xr libxo 3 ,
.Xr xo_options 7
.Sh HISTORY
The
.Nm libxo
library first appeared in
.Fx 11.0 .
The CSV encoder first appeared in
.Fx 13.0 .
.Sh AUTHORS
.Nm libxo
was written by
.An Phil Shafer Aq Mt phil@freebsd.org .

View File

@ -86,6 +86,95 @@ suited for terminal output and HTML is suited for display in a web
browser (see
.Xr xohtml 1 ).
.Pp
.Nm libxo
uses command line options to trigger rendering behavior.
The following options are recognised:
.Pp
.Bl -tag -width "--libxo"
.It
\-\^\-libxo <options>
.It
\-\^\-libxo=<options>
.It
\-\^\-libxo:<brief-options>
.El
.Pp
Options is a comma-separated list of tokens that correspond to output
styles, flags, or features:
.Pp
.Bl -tag -width "12345678"
.It Sy "Token Action"
.It Dv dtrt
Enable "Do The Right Thing" mode
.It Dv html
Emit HTML output
.It Dv indent=xx
Set the indentation level
.It Dv info
Add info attributes (HTML)
.It Dv json
Emit JSON output
.It Dv keys
Emit the key attribute for keys (XML)
.It Dv log-gettext
Log (via stderr) each
.Xr gettext 3
string lookup
.It Dv log-syslog
Log (via stderr) each syslog message (via
.Xr xo_syslog 3 )
.It Dv no-humanize
Ignore the {h:} modifier (TEXT, HTML)
.It Dv no-locale
Do not initialize the locale setting
.It Dv no-retain
Prevent retaining formatting information
.It Dv no-top
Do not emit a top set of braces (JSON)
.It Dv not-first
Pretend the 1st output item was not 1st (JSON)
.It Dv pretty
Emit pretty-printed output
.It Dv retain
Force retaining formatting information
.It Dv text
Emit TEXT output
.It Dv underscores
Replace XML-friendly "-"s with JSON friendly "_"s e
.It Dv units
Add the 'units' (XML) or 'data-units (HTML) attribute
.It Dv warn
Emit warnings when libxo detects bad calls
.It Dv warn-xml
Emit warnings in XML
.It Dv xml
Emit XML output
.It Dv xpath
Add XPath expressions (HTML)
.El
.Pp
The
.Dq brief-options
are single letter commands, designed for those with
too little patience to use real tokens.
No comma separator is used.
.Bl -column "i<num>"
.It Sy "Token Action"
.It "H " "Enable HTML output (XO_STYLE_HTML)"
.It "I " "Enable info output (XOF_INFO)"
.It "i<num> " "Indent by <number>"
.It "J " "Enable JSON output (XO_STYLE_JSON)"
.It "P " "Enable pretty-printed output (XOF_PRETTY)"
.It "T " "Enable text output (XO_STYLE_TEXT)"
.It "W " "Enable warnings (XOF_WARN)"
.It "X " "Enable XML output (XO_STYLE_XML)"
.It "x " "Enable XPath data (XOF_XPATH)"
.El
.Pp
Refer to
.Xr xo_options 7
for additional option information.
.Pp
The
.Nm
library allows an application to generate text, XML, JSON,
@ -291,6 +380,7 @@ Instructs
to use an alternative set of low-level output functions.
.El
.Sh SEE ALSO
.Xr libxo-csv 7,
.Xr xo 1 ,
.Xr xolint 1 ,
.Xr xo_attr 3 ,
@ -303,6 +393,7 @@ to use an alternative set of low-level output functions.
.Xr xo_no_setlocale 3 ,
.Xr xo_open_container 3 ,
.Xr xo_open_list 3 ,
.Xr xo_options 7,
.Xr xo_parse_args 3 ,
.Xr xo_set_allocator 3 ,
.Xr xo_set_flags 3 ,

View File

@ -6979,8 +6979,21 @@ xo_do_open_container (xo_handle_t *xop, xo_xof_flags_t flags, const char *name)
pre_nl = XOF_ISSET(xop, XOF_PRETTY) ? ",\n" : ", ";
xop->xo_stack[xop->xo_depth].xs_flags |= XSF_NOT_FIRST;
/* If we need underscores, make a local copy and doctor it */
const char *new_name = name;
if (XOF_ISSET(xop, XOF_UNDERSCORES)) {
size_t len = strlen(name);
const char *old_name = name;
char *buf, *cp, *ep;
buf = alloca(len + 1);
for (cp = buf, ep = buf + len + 1; cp < ep; cp++, old_name++)
*cp = (*old_name == '-') ? '_' : *old_name;
new_name = buf;
}
rc = xo_printf(xop, "%s%*s\"%s\": {%s",
pre_nl, xo_indent(xop), "", name, ppn);
pre_nl, xo_indent(xop), "", new_name, ppn);
break;
case XO_STYLE_SDPARAMS:
@ -7142,8 +7155,21 @@ xo_do_open_list (xo_handle_t *xop, xo_xof_flags_t flags, const char *name)
pre_nl = XOF_ISSET(xop, XOF_PRETTY) ? ",\n" : ", ";
xop->xo_stack[xop->xo_depth].xs_flags |= XSF_NOT_FIRST;
/* If we need underscores, make a local copy and doctor it */
const char *new_name = name;
if (XOF_ISSET(xop, XOF_UNDERSCORES)) {
size_t len = strlen(name);
const char *old_name = name;
char *buf, *cp, *ep;
buf = alloca(len + 1);
for (cp = buf, ep = buf + len + 1; cp < ep; cp++, old_name++)
*cp = (*old_name == '-') ? '_' : *old_name;
new_name = buf;
}
rc = xo_printf(xop, "%s%*s\"%s\": [%s",
pre_nl, xo_indent(xop), "", name, ppn);
pre_nl, xo_indent(xop), "", new_name, ppn);
break;
case XO_STYLE_ENCODER:

View File

@ -33,7 +33,7 @@ function.
Example:
xo_handle_t *xop = xo_create(XO_STYLE_JSON, XOF_WARN);
....
xo_emit_h(xop, "testing\n");
xo_emit_h(xop, "testing\\n");
.Ed
.Pp
By default,

View File

@ -48,7 +48,7 @@ In this example, a set of four values is emitted using the following
source code:
.Bd -literal -offset indent
xo_emit(" {:lines/%7ju} {:words/%7ju} "
"{:characters/%7ju} {d:filename/%s}\n",
"{:characters/%7ju} {d:filename/%s}\\n",
linect, wordct, charct, file);
.Ed
Output can then be generated in various style, using
@ -100,6 +100,8 @@ then the number of display columns consumed by the output will be returned.
.Sh SEE ALSO
.Xr xo_open_container 3 ,
.Xr xo_open_list 3 ,
.Xr xo_emit_f 3 ,
.Xo xo_emit_field 3 ,
.Xr xo_format 5 ,
.Xr libxo 3
.Sh HISTORY

View File

@ -84,14 +84,14 @@ clear this information; they are not generally needed.
.Bd -literal -offset indent
for (i = 0; i < 1000; i++) {
xo_open_instance("item");
xo_emit_f(XOEF_RETAIN, "{:name} {:count/%d}\n",
xo_emit_f(XOEF_RETAIN, "{:name} {:count/%d}\\n",
name[i], count[i]);
}
.Ed
.Pp
In this example, the caller desires to clear the retained information.
.Bd -literal -offset indent
const char *fmt = "{:name} {:count/%d}\n";
const char *fmt = "{:name} {:count/%d}\\n";
for (i = 0; i < 1000; i++) {
xo_open_instance("item");
xo_emit_f(XOEF_RETAIN, fmt, name[i], count[i]);

View File

@ -0,0 +1,113 @@
.\" #
.\" # Copyright (c) 2021, Juniper Networks, Inc.
.\" # All rights reserved.
.\" # This SOFTWARE is licensed under the LICENSE provided in the
.\" # ../Copyright file. By downloading, installing, copying, or
.\" # using the SOFTWARE, you agree to be bound by the terms of that
.\" # LICENSE.
.\" # Phil Shafer, July 2014
.\"
.Dd December 4, 2014
.Dt LIBXO 3
.Os
.Sh NAME
.Nm xo_emit_field
.Nd emit formatted output based on format string and arguments
.Sh LIBRARY
.Lb libxo
.Sh SYNOPSIS
.In libxo/xo.h
.Ft xo_ssize_t
.Fn xo_emit_field "const char *rolmod" "const char *content" "const char *fmt" "const char *efmt" "..."
.Ft xo_ssize_t
.Fn xo_emit_field_h "xo_handle_t *xop" "const char *rolmod" "const char *content" "const char *fmt" const char *efmt" "..."
.Ft xo_ssize_t
.Fn xo_emit_field_hv "xo_handle_t *xop" "const char *rolmod" "const char *content" "const char *fmt" "const char *efmt" "va_list vap"
.Sh DESCRIPTION
The
.Fn xo_emit_field
function emits formatted output similar to
.Xr xo_emit 3
but where
.Fn xo_emit
uses a single string argument containing the description
for multiple fields,
.Fn xo_emit_field
emits a single field using multiple arguments to contain the
field description.
.Fn xo_emit_field_h
adds an explicit handle to use instead of the default
handle, while
.Fn xo_emit_field_hv
accepts a
.Fa va_list
for additional flexibility.
.Pp
The arguments
.Fa rolmod ,
.Fa content ,
.Fa fmt ,
and
.Fa efmt
are detailed in
.Xr xo_format 5 .
Using distinct arguments allows callers to pass the field description
in pieces, rather than having to use something like
.Xr snprintf 3
to build the format string required by
.Fn xo_emit .
The arguments are each NUL-terminated strings. The
.Fa rolmod
argument contains the "role" and "modifier" portions of
the field description, the
.Fa content
argument contains the "content" portion, and the
.Fa fmt
and
.Fa efmt
contain the "field-format" and "encoding-format" portions, respectively.
.Pp
As with xo_emit, the
.Fa fmt
and
.Fa efmt
values are both optional, since the field-format string
defaults to "%s", and the encoding-format's default value is
derived from the field-format
per
.Xr xo_format 5 .
However, care must be taken to avoid using a value directly as the
format, since characters like '{', '%', and '}' will be interpreted
as formatting directives, and may cause
.Nm
to dereference arbitrary values off the stack, leading to bugs,
core files, and gnashing of teeth.
.Sh EXAMPLES
In this example, a set of four values is emitted using the following
source code:
.Bd -literal -offset indent
xo_emit_field("T", title, NULL, NULL, NULL);
xo_emit_field("Vt", "max-chaos", NULL, NULL, " very ");
xo_emit_field("V", "min-chaos", "%02d", "%d", 42);
xo_emit_field_h(NULL, ",leaf-list,quotes", "sku", "%s-%u", "%s-000-%u",
"gum", 1412);
.Ed
.Sh RETURN CODE
.Nm
returns a negative value on error. If the
.Nm XOF_COLUMNS
flag has been turned on for the specific handle using
.Xr xo_set_flags 3 ,
then the number of display columns consumed by the output will be returned.
.Sh SEE ALSO
.Xr xo_format 5 ,
.Xr libxo 3
.Sh HISTORY
The
.Nm libxo
library first appeared in
.Fx 11.0 .
.Sh AUTHORS
.Nm libxo
was written by
.An Phil Shafer Aq Mt phil@freebsd.org .

View File

@ -206,6 +206,33 @@ xo_encoder_find (const char *name)
return NULL;
}
/*
* Return the encoder function for a specific shared library. This is
* really just a means of keeping the annoying gcc verbiage out of the
* main code. And that's only need because gcc breaks dlfunc's
* promise that I can cast it's return value to a function: "The
* precise return type of dlfunc() is unspecified; applications must
* cast it to an appropriate function pointer type."
*/
static xo_encoder_init_func_t
xo_encoder_func (void *dlp)
{
xo_encoder_init_func_t func;
#if defined(HAVE_GCC) && __GNUC__ > 8
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wcast-function-type"
#endif /* HAVE_GCC */
func = (xo_encoder_init_func_t) dlfunc(dlp, XO_ENCODER_INIT_NAME);
#if defined(HAVE_GCC) && __GNUC__ > 8
#pragma GCC diagnostic pop /* Restore previous setting */
#endif /* HAVE_GCC */
return func;
}
static xo_encoder_node_t *
xo_encoder_discover (const char *name)
{
@ -234,7 +261,7 @@ xo_encoder_discover (const char *name)
*/
xo_encoder_init_func_t func;
func = (xo_encoder_init_func_t) dlfunc(dlp, XO_ENCODER_INIT_NAME);
func = xo_encoder_func(dlp);
if (func) {
xo_encoder_init_args_t xei;

View File

@ -242,6 +242,13 @@ Labels are text that appears before a value.
.Bd -literal -offset indent
xo_emit("{Lwc:Cost}{:cost/%u}\\n", cost);
.Ed
.Pp
If a label needs to include a slash, it must be escaped using two
backslashes, one for the C compiler and one for
.Nm libxo .
.Bd -literal -offset indent
xo_emit("{Lc:Low\\\\/warn level}{:level/%s}\\n", level);
.Ed
.Ss "The Note Role ({N:})"
Notes are text that appears after a value.
.Bd -literal -offset indent

View File

@ -141,7 +141,7 @@ flag is set.
.Bd -literal -offset indent -compact
EXAMPLE:
xo_open_container("system");
xo_emit("The host name is {:host-name}\n", hn);
xo_emit("The host name is {:host-name}\\n", hn);
xo_close_container("system");
XML:
<system><host-name>foo</host-name></system>

View File

@ -77,7 +77,7 @@ close each instance of the list:
for (ip = list; ip->i_title; ip++) {
xo_open_instance("item");
xo_emit("{L:Item} '{:name/%s}':\n", ip->i_title);
xo_emit("{L:Item} '{:name/%s}':\\n", ip->i_title);
xo_close_instance("item");
}
@ -91,7 +91,7 @@ generation of XML and JSON data.
xo_open_list("user");
for (i = 0; i < num_users; i++) {
xo_open_instance("user");
xo_emit("{k:name}:{:uid/%u}:{:gid/%u}:{:home}\n",
xo_emit("{k:name}:{:uid/%u}:{:gid/%u}:{:home}\\n",
pw[i].pw_name, pw[i].pw_uid,
pw[i].pw_gid, pw[i].pw_dir);
xo_close_instance("user");
@ -138,7 +138,7 @@ To emit a leaf list, call the
function using the ""l"" modifier:
.Bd -literal -offset indent -compact
for (ip = list; ip->i_title; ip++) {
xo_emit("{Lwc:Item}{l:item}\n", ip->i_title);
xo_emit("{Lwc:Item}{l:item}\\n", ip->i_title);
}
.Ed
.Pp

View File

@ -7,7 +7,7 @@
.\" # LICENSE.
.\" # Phil Shafer, July 2014
.\"
.Dd December 4, 2014
.Dd November 17, 2020
.Dt LIBXO 3
.Os
.Sh NAME
@ -24,7 +24,9 @@
.Sh DESCRIPTION
The
.Fn xo_parse_args
function is used to process command-line arguments.
function is used to process command-line arguments, which are
described in
.Xr xo_options 7 .
.Nm libxo
specific
options are processed and removed
@ -42,91 +44,6 @@ Following the call to
.Fn xo_parse_args ,
the application can process the remaining arguments in a normal manner.
.Pp
.Nm libxo
uses command line options to trigger rendering behavior.
The following options are recognised:
.Pp
.Bl -tag -width "--libxo"
.It
\-\^\-libxo <options>
.It
\-\^\-libxo=<options>
.It
\-\^\-libxo:<brief-options>
.El
.Pp
Options is a comma-separated list of tokens that correspond to output
styles, flags, or features:
.Pp
.Bl -tag -width "12345678"
.It Sy "Token Action"
.It Dv dtrt
Enable "Do The Right Thing" mode
.It Dv html
Emit HTML output
.It Dv indent=xx
Set the indentation level
.It Dv info
Add info attributes (HTML)
.It Dv json
Emit JSON output
.It Dv keys
Emit the key attribute for keys (XML)
.It Dv log-gettext
Log (via stderr) each
.Xr gettext 3
string lookup
.It Dv log-syslog
Log (via stderr) each syslog message (via
.Xr xo_syslog 3 )
.If Dv no-humanize
Ignore the {h:} modifier (TEXT, HTML)
.It Dv no-locale
Do not initialize the locale setting
.It Dv no-retain
Prevent retaining formatting information
.It Dv no-top
Do not emit a top set of braces (JSON)
.It Dv not-first
Pretend the 1st output item was not 1st (JSON)
.It Dv pretty
Emit pretty-printed output
.It Dv retain
Force retaining formatting information
.It Dv text
Emit TEXT output
.If Dv underscores
Replace XML-friendly "-"s with JSON friendly "_"s e
.It Dv units
Add the 'units' (XML) or 'data-units (HTML) attribute
.It Dv warn
Emit warnings when libxo detects bad calls
.It Dv warn-xml
Emit warnings in XML
.It Dv xml
Emit XML output
.It Dv xpath
Add XPath expressions (HTML)
.El
.Pp
The
.Dq brief-options
are single letter commands, designed for those with
too little patience to use real tokens.
No comma separator is used.
.Bl -column "i<num>"
.It Sy "Token Action"
.It "H " "Enable HTML output (XO_STYLE_HTML)"
.It "I " "Enable info output (XOF_INFO)"
.It "i<num> " "Indent by <number>"
.It "J " "Enable JSON output (XO_STYLE_JSON)"
.It "P " "Enable pretty-printed output (XOF_PRETTY)"
.It "T " "Enable text output (XO_STYLE_TEXT)"
.It "W " "Enable warnings (XOF_WARN)"
.It "X " "Enable XML output (XO_STYLE_XML)"
.It "x " "Enable XPath data (XOF_XPATH)"
.El
.Pp
The
.Fn xo_set_program
function sets name of the program as reported by
@ -149,6 +66,7 @@ must be maintained by the caller.
.Pp
.Sh SEE ALSO
.Xr xo_emit 3 ,
.Xr xo_options 7,
.Xr libxo 3
.Sh HISTORY
The

View File

@ -51,24 +51,32 @@ endif
EXTRA_DIST = \
${TEST_CASES} \
${addprefix saved/, ${TEST_CASES:.c=.T.err}} \
${addprefix saved/, ${TEST_CASES:.c=.T.out}} \
${addprefix saved/, ${TEST_CASES:.c=.XP.err}} \
${addprefix saved/, ${TEST_CASES:.c=.XP.out}} \
${addprefix saved/, ${TEST_CASES:.c=.JP.err}} \
${addprefix saved/, ${TEST_CASES:.c=.JP.out}} \
${addprefix saved/, ${TEST_CASES:.c=.HP.err}} \
${addprefix saved/, ${TEST_CASES:.c=.HP.out}} \
${addprefix saved/, ${TEST_CASES:.c=.X.err}} \
${addprefix saved/, ${TEST_CASES:.c=.X.out}} \
${addprefix saved/, ${TEST_CASES:.c=.J.err}} \
${addprefix saved/, ${TEST_CASES:.c=.J.out}} \
${addprefix saved/, ${TEST_CASES:.c=.E.err}} \
${addprefix saved/, ${TEST_CASES:.c=.E.out}} \
${addprefix saved/, ${TEST_CASES:.c=.H.err}} \
${addprefix saved/, ${TEST_CASES:.c=.H.out}} \
${addprefix saved/, ${TEST_CASES:.c=.HIPx.err}} \
${addprefix saved/, ${TEST_CASES:.c=.HIPx.out}} \
${addprefix saved/, ${TEST_CASES:.c=.E.err}} \
${addprefix saved/, ${TEST_CASES:.c=.E.out}}
${addprefix saved/, ${TEST_CASES:.c=.HP.err}} \
${addprefix saved/, ${TEST_CASES:.c=.HP.out}} \
${addprefix saved/, ${TEST_CASES:.c=.J.err}} \
${addprefix saved/, ${TEST_CASES:.c=.J.out}} \
${addprefix saved/, ${TEST_CASES:.c=.JP.err}} \
${addprefix saved/, ${TEST_CASES:.c=.JP.out}} \
${addprefix saved/, ${TEST_CASES:.c=.JPu.err}} \
${addprefix saved/, ${TEST_CASES:.c=.JPu.out}} \
${addprefix saved/, ${TEST_CASES:.c=.T.err}} \
${addprefix saved/, ${TEST_CASES:.c=.T.out}} \
${addprefix saved/, ${TEST_CASES:.c=.X.err}} \
${addprefix saved/, ${TEST_CASES:.c=.X.out}} \
${addprefix saved/, ${TEST_CASES:.c=.XP.err}} \
${addprefix saved/, ${TEST_CASES:.c=.XP.out}} \
${addprefix saved/, test_01.Ecsv1.out} \
${addprefix saved/, test_01.Ecsv1.err} \
${addprefix saved/, test_01.Ecsv2.out} \
${addprefix saved/, test_01.Ecsv2.err} \
${addprefix saved/, test_01.Ecsv3.out} \
${addprefix saved/, test_01.Ecsv3.err}
S2O = | ${SED} '1,/@@/d'
@ -91,7 +99,7 @@ echo "... $$test ... $$fmt ..."; \
xoopts==warn,$$csv ; \
${TEST_JIG}; true;
TEST_FORMATS = T XP JP HP X J H HIPx
TEST_FORMATS = T XP JP JPu HP X J H HIPx
test tests: ${bin_PROGRAMS}
@${MKDIR} -p out
@ -113,7 +121,7 @@ test tests: ${bin_PROGRAMS}
-@ (${TEST_TRACE} test=test_01.c; base=test_01; \
( fmt=Ecsv1; csv=encoder=csv ; \
${TEST_JIG2} ); \
( fmt=Ecsv2; csv=encoder=csv:path=top/data/item:no-header ; \
( fmt=Ecsv2; csv=encoder=csv:path=top-level/data/item:no-header ; \
${TEST_JIG2} ); \
( fmt=Ecsv3; csv=@csv:path=item:leafs=sku.sold:no-quotes ; \
${TEST_JIG2} ); \

View File

@ -1,5 +1,5 @@
op create: [test] [] [0]
op open_container: [top] [] [0x810]
op open_container: [top-level] [] [0x810]
op string: [type] [ethernet] [0]
op content: [type] [bridge] [0]
op content: [type] [18u] [0]
@ -21,6 +21,10 @@ op string: [label] [value] [0x200000]
op string: [max-chaos] [very] [0x1000]
op content: [min-chaos] [42] [0]
op string: [some-chaos] [[42]] [0]
op attr: [test-attr] [attr-value] [0]
op open_leaf_list: [sku] [] [0]
op string: [sku] [gum-000-1412] [0x2010]
op close_leaf_list: [sku] [] [0]
op string: [host] [my-box] [0]
op string: [domain] [example.com] [0]
op attr: [test] [value] [0]
@ -197,6 +201,6 @@ op content: [mode_octal] [640] [0x8]
op content: [links] [1] [0x1000]
op string: [user] [user] [0x1000]
op string: [group] [group] [0x1000]
op close_container: [top] [] [0]
op close_container: [top-level] [] [0]
op finish: [] [] [0]
op flush: [] [] [0]

File diff suppressed because one or more lines are too long

View File

@ -1,64 +1,67 @@
<div class="line">
<div class="text">static </div>
<div class="data" data-tag="type" data-xpath="/top/type">ethernet</div>
<div class="data" data-tag="type" data-xpath="/top-level/type">ethernet</div>
<div class="text"> </div>
<div class="data" data-tag="type" data-xpath="/top/type">bridge</div>
<div class="data" data-tag="type" data-xpath="/top-level/type">bridge</div>
<div class="text"> </div>
<div class="data" data-tag="type" data-xpath="/top/type"> 18u</div>
<div class="data" data-tag="type" data-xpath="/top-level/type"> 18u</div>
<div class="text"> </div>
<div class="data" data-tag="type" data-xpath="/top/type"> 24</div>
<div class="data" data-tag="type" data-xpath="/top-level/type"> 24</div>
<div class="text">anchor </div>
<div class="padding"> </div>
<div class="data" data-tag="address" data-xpath="/top/address">0x0</div>
<div class="data" data-tag="address" data-xpath="/top-level/address">0x0</div>
<div class="text">..</div>
<div class="data" data-tag="port" data-xpath="/top/port">1</div>
<div class="data" data-tag="port" data-xpath="/top-level/port">1</div>
</div>
<div class="line">
<div class="text">anchor </div>
<div class="padding"> </div>
<div class="data" data-tag="address" data-xpath="/top/address">0x0</div>
<div class="data" data-tag="address" data-xpath="/top-level/address">0x0</div>
<div class="text">..</div>
<div class="data" data-tag="port" data-xpath="/top/port">1</div>
<div class="data" data-tag="port" data-xpath="/top-level/port">1</div>
</div>
<div class="line">
<div class="text">anchor </div>
<div class="padding"> </div>
<div class="data" data-tag="address" data-xpath="/top/address">0x0</div>
<div class="data" data-tag="address" data-xpath="/top-level/address">0x0</div>
<div class="text">..</div>
<div class="data" data-tag="port" data-xpath="/top/port">1</div>
<div class="data" data-tag="port" data-xpath="/top-level/port">1</div>
</div>
<div class="line">
<div class="text">df </div>
<div class="data" data-tag="used-percent" data-xpath="/top/used-percent"> 12</div>
<div class="data" data-tag="used-percent" data-xpath="/top-level/used-percent"> 12</div>
<div class="units">%</div>
</div>
<div class="line">
<div class="text">testing argument modifier </div>
<div class="data" data-tag="host" data-xpath="/top/host">my-box</div>
<div class="data" data-tag="host" data-xpath="/top-level/host">my-box</div>
<div class="text">.</div>
<div class="data" data-tag="domain" data-xpath="/top/domain">example.com</div>
<div class="data" data-tag="domain" data-xpath="/top-level/domain">example.com</div>
<div class="text">...</div>
</div>
<div class="line">
<div class="text">testing argument modifier with encoding to </div>
<div class="text">.</div>
<div class="data" data-tag="domain" data-xpath="/top/domain">example.com</div>
<div class="data" data-tag="domain" data-xpath="/top-level/domain">example.com</div>
<div class="text">...</div>
</div>
<div class="line">
<div class="label">Label text</div>
<div class="text"> </div>
<div class="data" data-tag="label" data-xpath="/top/label">value</div>
<div class="data" data-tag="label" data-xpath="/top-level/label">value</div>
</div>
<div class="line">
<div class="data" data-tag="max-chaos" data-xpath="/top/max-chaos"> very </div>
<div class="data" data-tag="min-chaos" data-xpath="/top/min-chaos">42</div>
<div class="data" data-tag="some-chaos" data-xpath="/top/some-chaos">42
<div class="title">My Title
</div>
<div class="data" data-tag="max-chaos" data-xpath="/top-level/max-chaos"> very </div>
<div class="data" data-tag="min-chaos" data-xpath="/top-level/min-chaos">42</div>
<div class="data" data-tag="some-chaos" data-xpath="/top-level/some-chaos">42
</div>
<div class="data" data-tag="sku" data-xpath="/top-level/sku" data-type="string" data-help="Stock Keeping Unit">gum-1412</div>
<div class="text">Connecting to </div>
<div class="data" data-tag="host" data-xpath="/top/host">my-box</div>
<div class="data" data-tag="host" data-xpath="/top-level/host">my-box</div>
<div class="text">.</div>
<div class="data" data-tag="domain" data-xpath="/top/domain">example.com</div>
<div class="data" data-tag="domain" data-xpath="/top-level/domain">example.com</div>
<div class="text">...</div>
</div>
<div class="line">
@ -69,39 +72,39 @@
<div class="title"> SKU</div>
</div>
<div class="line">
<div class="data" data-tag="name" data-xpath="/top/data/item/name" data-type="string" data-help="Name of the item" data-key="key">gum </div>
<div class="data" data-tag="sold" data-xpath="/top/data/item[sku = 'GRO-000-415'][name = 'gum']/sold" data-type="number" data-help="Number of items sold"> 1412</div>
<div class="data" data-tag="in-stock" data-xpath="/top/data/item[sku = 'GRO-000-415'][name = 'gum']/in-stock" data-type="number" data-help="Number of items in stock"> 54</div>
<div class="data" data-tag="on-order" data-xpath="/top/data/item[sku = 'GRO-000-415'][name = 'gum']/on-order" data-type="number" data-help="Number of items on order"> 10</div>
<div class="data" data-tag="sku" data-xpath="/top/data/item/sku" data-type="string" data-help="Stock Keeping Unit" data-key="key"> GRO-000-415</div>
<div class="data" data-tag="name" data-xpath="/top-level/data/item/name" data-type="string" data-help="Name of the item" data-key="key">gum </div>
<div class="data" data-tag="sold" data-xpath="/top-level/data/item[sku = 'GRO-000-415'][name = 'gum']/sold" data-type="number" data-help="Number of items sold"> 1412</div>
<div class="data" data-tag="in-stock" data-xpath="/top-level/data/item[sku = 'GRO-000-415'][name = 'gum']/in-stock" data-type="number" data-help="Number of items in stock"> 54</div>
<div class="data" data-tag="on-order" data-xpath="/top-level/data/item[sku = 'GRO-000-415'][name = 'gum']/on-order" data-type="number" data-help="Number of items on order"> 10</div>
<div class="data" data-tag="sku" data-xpath="/top-level/data/item/sku" data-type="string" data-help="Stock Keeping Unit" data-key="key"> GRO-000-415</div>
</div>
<div class="line">
<div class="data" data-tag="name" data-xpath="/top/data/item/name" data-type="string" data-help="Name of the item" data-key="key">rope </div>
<div class="data" data-tag="sold" data-xpath="/top/data/item[sku = 'HRD-000-212'][name = 'rope']/sold" data-type="number" data-help="Number of items sold"> 85</div>
<div class="data" data-tag="in-stock" data-xpath="/top/data/item[sku = 'HRD-000-212'][name = 'rope']/in-stock" data-type="number" data-help="Number of items in stock"> 4</div>
<div class="data" data-tag="on-order" data-xpath="/top/data/item[sku = 'HRD-000-212'][name = 'rope']/on-order" data-type="number" data-help="Number of items on order"> 2</div>
<div class="data" data-tag="sku" data-xpath="/top/data/item/sku" data-type="string" data-help="Stock Keeping Unit" data-key="key"> HRD-000-212</div>
<div class="data" data-tag="name" data-xpath="/top-level/data/item/name" data-type="string" data-help="Name of the item" data-key="key">rope </div>
<div class="data" data-tag="sold" data-xpath="/top-level/data/item[sku = 'HRD-000-212'][name = 'rope']/sold" data-type="number" data-help="Number of items sold"> 85</div>
<div class="data" data-tag="in-stock" data-xpath="/top-level/data/item[sku = 'HRD-000-212'][name = 'rope']/in-stock" data-type="number" data-help="Number of items in stock"> 4</div>
<div class="data" data-tag="on-order" data-xpath="/top-level/data/item[sku = 'HRD-000-212'][name = 'rope']/on-order" data-type="number" data-help="Number of items on order"> 2</div>
<div class="data" data-tag="sku" data-xpath="/top-level/data/item/sku" data-type="string" data-help="Stock Keeping Unit" data-key="key"> HRD-000-212</div>
</div>
<div class="line">
<div class="data" data-tag="name" data-xpath="/top/data/item/name" data-type="string" data-help="Name of the item" data-key="key">ladder </div>
<div class="data" data-tag="sold" data-xpath="/top/data/item[sku = 'HRD-000-517'][name = 'ladder']/sold" data-type="number" data-help="Number of items sold"> 0</div>
<div class="data" data-tag="in-stock" data-xpath="/top/data/item[sku = 'HRD-000-517'][name = 'ladder']/in-stock" data-type="number" data-help="Number of items in stock"> 2</div>
<div class="data" data-tag="on-order" data-xpath="/top/data/item[sku = 'HRD-000-517'][name = 'ladder']/on-order" data-type="number" data-help="Number of items on order"> 1</div>
<div class="data" data-tag="sku" data-xpath="/top/data/item/sku" data-type="string" data-help="Stock Keeping Unit" data-key="key"> HRD-000-517</div>
<div class="data" data-tag="name" data-xpath="/top-level/data/item/name" data-type="string" data-help="Name of the item" data-key="key">ladder </div>
<div class="data" data-tag="sold" data-xpath="/top-level/data/item[sku = 'HRD-000-517'][name = 'ladder']/sold" data-type="number" data-help="Number of items sold"> 0</div>
<div class="data" data-tag="in-stock" data-xpath="/top-level/data/item[sku = 'HRD-000-517'][name = 'ladder']/in-stock" data-type="number" data-help="Number of items in stock"> 2</div>
<div class="data" data-tag="on-order" data-xpath="/top-level/data/item[sku = 'HRD-000-517'][name = 'ladder']/on-order" data-type="number" data-help="Number of items on order"> 1</div>
<div class="data" data-tag="sku" data-xpath="/top-level/data/item/sku" data-type="string" data-help="Stock Keeping Unit" data-key="key"> HRD-000-517</div>
</div>
<div class="line">
<div class="data" data-tag="name" data-xpath="/top/data/item/name" data-type="string" data-help="Name of the item" data-key="key">bolt </div>
<div class="data" data-tag="sold" data-xpath="/top/data/item[sku = 'HRD-000-632'][name = 'bolt']/sold" data-type="number" data-help="Number of items sold"> 4123</div>
<div class="data" data-tag="in-stock" data-xpath="/top/data/item[sku = 'HRD-000-632'][name = 'bolt']/in-stock" data-type="number" data-help="Number of items in stock"> 144</div>
<div class="data" data-tag="on-order" data-xpath="/top/data/item[sku = 'HRD-000-632'][name = 'bolt']/on-order" data-type="number" data-help="Number of items on order"> 42</div>
<div class="data" data-tag="sku" data-xpath="/top/data/item/sku" data-type="string" data-help="Stock Keeping Unit" data-key="key"> HRD-000-632</div>
<div class="data" data-tag="name" data-xpath="/top-level/data/item/name" data-type="string" data-help="Name of the item" data-key="key">bolt </div>
<div class="data" data-tag="sold" data-xpath="/top-level/data/item[sku = 'HRD-000-632'][name = 'bolt']/sold" data-type="number" data-help="Number of items sold"> 4123</div>
<div class="data" data-tag="in-stock" data-xpath="/top-level/data/item[sku = 'HRD-000-632'][name = 'bolt']/in-stock" data-type="number" data-help="Number of items in stock"> 144</div>
<div class="data" data-tag="on-order" data-xpath="/top-level/data/item[sku = 'HRD-000-632'][name = 'bolt']/on-order" data-type="number" data-help="Number of items on order"> 42</div>
<div class="data" data-tag="sku" data-xpath="/top-level/data/item/sku" data-type="string" data-help="Stock Keeping Unit" data-key="key"> HRD-000-632</div>
</div>
<div class="line">
<div class="data" data-tag="name" data-xpath="/top/data/item/name" data-type="string" data-help="Name of the item" data-key="key">water </div>
<div class="data" data-tag="sold" data-xpath="/top/data/item[sku = 'GRO-000-2331'][name = 'water']/sold" data-type="number" data-help="Number of items sold"> 17</div>
<div class="data" data-tag="in-stock" data-xpath="/top/data/item[sku = 'GRO-000-2331'][name = 'water']/in-stock" data-type="number" data-help="Number of items in stock"> 14</div>
<div class="data" data-tag="on-order" data-xpath="/top/data/item[sku = 'GRO-000-2331'][name = 'water']/on-order" data-type="number" data-help="Number of items on order"> 2</div>
<div class="data" data-tag="sku" data-xpath="/top/data/item/sku" data-type="string" data-help="Stock Keeping Unit" data-key="key"> GRO-000-2331</div>
<div class="data" data-tag="name" data-xpath="/top-level/data/item/name" data-type="string" data-help="Name of the item" data-key="key">water </div>
<div class="data" data-tag="sold" data-xpath="/top-level/data/item[sku = 'GRO-000-2331'][name = 'water']/sold" data-type="number" data-help="Number of items sold"> 17</div>
<div class="data" data-tag="in-stock" data-xpath="/top-level/data/item[sku = 'GRO-000-2331'][name = 'water']/in-stock" data-type="number" data-help="Number of items in stock"> 14</div>
<div class="data" data-tag="on-order" data-xpath="/top-level/data/item[sku = 'GRO-000-2331'][name = 'water']/on-order" data-type="number" data-help="Number of items on order"> 2</div>
<div class="data" data-tag="sku" data-xpath="/top-level/data/item/sku" data-type="string" data-help="Stock Keeping Unit" data-key="key"> GRO-000-2331</div>
</div>
<div class="line">
</div>
@ -110,224 +113,224 @@
<div class="line">
<div class="label">Item</div>
<div class="text"> '</div>
<div class="data" data-tag="name" data-xpath="/top/data2/item/name" data-type="string" data-help="Name of the item" data-key="key">gum</div>
<div class="data" data-tag="name" data-xpath="/top-level/data2/item/name" data-type="string" data-help="Name of the item" data-key="key">gum</div>
<div class="text">':</div>
</div>
<div class="line">
<div class="padding"> </div>
<div class="label">Total sold</div>
<div class="text">: </div>
<div class="data" data-tag="sold" data-xpath="/top/data2/item[sku = 'GRO-000-415'][name = 'gum']/sold" data-type="number" data-help="Number of items sold">1412.0</div>
<div class="data" data-tag="sold" data-xpath="/top-level/data2/item[sku = 'GRO-000-415'][name = 'gum']/sold" data-type="number" data-help="Number of items sold">1412.0</div>
</div>
<div class="line">
<div class="padding"> </div>
<div class="label">In stock</div>
<div class="decoration">:</div>
<div class="padding"> </div>
<div class="data" data-tag="in-stock" data-xpath="/top/data2/item[sku = 'GRO-000-415'][name = 'gum']/in-stock" data-type="number" data-help="Number of items in stock">54</div>
<div class="data" data-tag="in-stock" data-xpath="/top-level/data2/item[sku = 'GRO-000-415'][name = 'gum']/in-stock" data-type="number" data-help="Number of items in stock">54</div>
</div>
<div class="line">
<div class="padding"> </div>
<div class="label">On order</div>
<div class="decoration">:</div>
<div class="padding"> </div>
<div class="data" data-tag="on-order" data-xpath="/top/data2/item[sku = 'GRO-000-415'][name = 'gum']/on-order" data-type="number" data-help="Number of items on order">10</div>
<div class="data" data-tag="on-order" data-xpath="/top-level/data2/item[sku = 'GRO-000-415'][name = 'gum']/on-order" data-type="number" data-help="Number of items on order">10</div>
</div>
<div class="line">
<div class="padding"> </div>
<div class="label">SKU</div>
<div class="text">: </div>
<div class="data" data-tag="sku" data-xpath="/top/data2/item/sku" data-type="string" data-help="Stock Keeping Unit" data-key="key">GRO-000-415</div>
<div class="data" data-tag="sku" data-xpath="/top-level/data2/item/sku" data-type="string" data-help="Stock Keeping Unit" data-key="key">GRO-000-415</div>
</div>
<div class="line">
<div class="label">Item</div>
<div class="text"> '</div>
<div class="data" data-tag="name" data-xpath="/top/data2/item/name" data-type="string" data-help="Name of the item" data-key="key">rope</div>
<div class="data" data-tag="name" data-xpath="/top-level/data2/item/name" data-type="string" data-help="Name of the item" data-key="key">rope</div>
<div class="text">':</div>
</div>
<div class="line">
<div class="padding"> </div>
<div class="label">Total sold</div>
<div class="text">: </div>
<div class="data" data-tag="sold" data-xpath="/top/data2/item[sku = 'HRD-000-212'][name = 'rope']/sold" data-type="number" data-help="Number of items sold">85.0</div>
<div class="data" data-tag="sold" data-xpath="/top-level/data2/item[sku = 'HRD-000-212'][name = 'rope']/sold" data-type="number" data-help="Number of items sold">85.0</div>
</div>
<div class="line">
<div class="padding"> </div>
<div class="label">In stock</div>
<div class="decoration">:</div>
<div class="padding"> </div>
<div class="data" data-tag="in-stock" data-xpath="/top/data2/item[sku = 'HRD-000-212'][name = 'rope']/in-stock" data-type="number" data-help="Number of items in stock">4</div>
<div class="data" data-tag="in-stock" data-xpath="/top-level/data2/item[sku = 'HRD-000-212'][name = 'rope']/in-stock" data-type="number" data-help="Number of items in stock">4</div>
</div>
<div class="line">
<div class="padding"> </div>
<div class="label">On order</div>
<div class="decoration">:</div>
<div class="padding"> </div>
<div class="data" data-tag="on-order" data-xpath="/top/data2/item[sku = 'HRD-000-212'][name = 'rope']/on-order" data-type="number" data-help="Number of items on order">2</div>
<div class="data" data-tag="on-order" data-xpath="/top-level/data2/item[sku = 'HRD-000-212'][name = 'rope']/on-order" data-type="number" data-help="Number of items on order">2</div>
</div>
<div class="line">
<div class="padding"> </div>
<div class="label">SKU</div>
<div class="text">: </div>
<div class="data" data-tag="sku" data-xpath="/top/data2/item/sku" data-type="string" data-help="Stock Keeping Unit" data-key="key">HRD-000-212</div>
<div class="data" data-tag="sku" data-xpath="/top-level/data2/item/sku" data-type="string" data-help="Stock Keeping Unit" data-key="key">HRD-000-212</div>
</div>
<div class="line">
<div class="label">Item</div>
<div class="text"> '</div>
<div class="data" data-tag="name" data-xpath="/top/data2/item/name" data-type="string" data-help="Name of the item" data-key="key">ladder</div>
<div class="data" data-tag="name" data-xpath="/top-level/data2/item/name" data-type="string" data-help="Name of the item" data-key="key">ladder</div>
<div class="text">':</div>
</div>
<div class="line">
<div class="padding"> </div>
<div class="label">Total sold</div>
<div class="text">: </div>
<div class="data" data-tag="sold" data-xpath="/top/data2/item[sku = 'HRD-000-517'][name = 'ladder']/sold" data-type="number" data-help="Number of items sold">0</div>
<div class="data" data-tag="sold" data-xpath="/top-level/data2/item[sku = 'HRD-000-517'][name = 'ladder']/sold" data-type="number" data-help="Number of items sold">0</div>
</div>
<div class="line">
<div class="padding"> </div>
<div class="label">In stock</div>
<div class="decoration">:</div>
<div class="padding"> </div>
<div class="data" data-tag="in-stock" data-xpath="/top/data2/item[sku = 'HRD-000-517'][name = 'ladder']/in-stock" data-type="number" data-help="Number of items in stock">2</div>
<div class="data" data-tag="in-stock" data-xpath="/top-level/data2/item[sku = 'HRD-000-517'][name = 'ladder']/in-stock" data-type="number" data-help="Number of items in stock">2</div>
</div>
<div class="line">
<div class="padding"> </div>
<div class="label">On order</div>
<div class="decoration">:</div>
<div class="padding"> </div>
<div class="data" data-tag="on-order" data-xpath="/top/data2/item[sku = 'HRD-000-517'][name = 'ladder']/on-order" data-type="number" data-help="Number of items on order">1</div>
<div class="data" data-tag="on-order" data-xpath="/top-level/data2/item[sku = 'HRD-000-517'][name = 'ladder']/on-order" data-type="number" data-help="Number of items on order">1</div>
</div>
<div class="line">
<div class="padding"> </div>
<div class="label">SKU</div>
<div class="text">: </div>
<div class="data" data-tag="sku" data-xpath="/top/data2/item/sku" data-type="string" data-help="Stock Keeping Unit" data-key="key">HRD-000-517</div>
<div class="data" data-tag="sku" data-xpath="/top-level/data2/item/sku" data-type="string" data-help="Stock Keeping Unit" data-key="key">HRD-000-517</div>
</div>
<div class="line">
<div class="label">Item</div>
<div class="text"> '</div>
<div class="data" data-tag="name" data-xpath="/top/data2/item/name" data-type="string" data-help="Name of the item" data-key="key">bolt</div>
<div class="data" data-tag="name" data-xpath="/top-level/data2/item/name" data-type="string" data-help="Name of the item" data-key="key">bolt</div>
<div class="text">':</div>
</div>
<div class="line">
<div class="padding"> </div>
<div class="label">Total sold</div>
<div class="text">: </div>
<div class="data" data-tag="sold" data-xpath="/top/data2/item[sku = 'HRD-000-632'][name = 'bolt']/sold" data-type="number" data-help="Number of items sold">4123.0</div>
<div class="data" data-tag="sold" data-xpath="/top-level/data2/item[sku = 'HRD-000-632'][name = 'bolt']/sold" data-type="number" data-help="Number of items sold">4123.0</div>
</div>
<div class="line">
<div class="padding"> </div>
<div class="label">In stock</div>
<div class="decoration">:</div>
<div class="padding"> </div>
<div class="data" data-tag="in-stock" data-xpath="/top/data2/item[sku = 'HRD-000-632'][name = 'bolt']/in-stock" data-type="number" data-help="Number of items in stock">144</div>
<div class="data" data-tag="in-stock" data-xpath="/top-level/data2/item[sku = 'HRD-000-632'][name = 'bolt']/in-stock" data-type="number" data-help="Number of items in stock">144</div>
</div>
<div class="line">
<div class="padding"> </div>
<div class="label">On order</div>
<div class="decoration">:</div>
<div class="padding"> </div>
<div class="data" data-tag="on-order" data-xpath="/top/data2/item[sku = 'HRD-000-632'][name = 'bolt']/on-order" data-type="number" data-help="Number of items on order">42</div>
<div class="data" data-tag="on-order" data-xpath="/top-level/data2/item[sku = 'HRD-000-632'][name = 'bolt']/on-order" data-type="number" data-help="Number of items on order">42</div>
</div>
<div class="line">
<div class="padding"> </div>
<div class="label">SKU</div>
<div class="text">: </div>
<div class="data" data-tag="sku" data-xpath="/top/data2/item/sku" data-type="string" data-help="Stock Keeping Unit" data-key="key">HRD-000-632</div>
<div class="data" data-tag="sku" data-xpath="/top-level/data2/item/sku" data-type="string" data-help="Stock Keeping Unit" data-key="key">HRD-000-632</div>
</div>
<div class="line">
<div class="label">Item</div>
<div class="text"> '</div>
<div class="data" data-tag="name" data-xpath="/top/data2/item/name" data-type="string" data-help="Name of the item" data-key="key">water</div>
<div class="data" data-tag="name" data-xpath="/top-level/data2/item/name" data-type="string" data-help="Name of the item" data-key="key">water</div>
<div class="text">':</div>
</div>
<div class="line">
<div class="padding"> </div>
<div class="label">Total sold</div>
<div class="text">: </div>
<div class="data" data-tag="sold" data-xpath="/top/data2/item[sku = 'GRO-000-2331'][name = 'water']/sold" data-type="number" data-help="Number of items sold">17.0</div>
<div class="data" data-tag="sold" data-xpath="/top-level/data2/item[sku = 'GRO-000-2331'][name = 'water']/sold" data-type="number" data-help="Number of items sold">17.0</div>
</div>
<div class="line">
<div class="padding"> </div>
<div class="label">In stock</div>
<div class="decoration">:</div>
<div class="padding"> </div>
<div class="data" data-tag="in-stock" data-xpath="/top/data2/item[sku = 'GRO-000-2331'][name = 'water']/in-stock" data-type="number" data-help="Number of items in stock">14</div>
<div class="data" data-tag="in-stock" data-xpath="/top-level/data2/item[sku = 'GRO-000-2331'][name = 'water']/in-stock" data-type="number" data-help="Number of items in stock">14</div>
</div>
<div class="line">
<div class="padding"> </div>
<div class="label">On order</div>
<div class="decoration">:</div>
<div class="padding"> </div>
<div class="data" data-tag="on-order" data-xpath="/top/data2/item[sku = 'GRO-000-2331'][name = 'water']/on-order" data-type="number" data-help="Number of items on order">2</div>
<div class="data" data-tag="on-order" data-xpath="/top-level/data2/item[sku = 'GRO-000-2331'][name = 'water']/on-order" data-type="number" data-help="Number of items on order">2</div>
</div>
<div class="line">
<div class="padding"> </div>
<div class="label">SKU</div>
<div class="text">: </div>
<div class="data" data-tag="sku" data-xpath="/top/data2/item/sku" data-type="string" data-help="Stock Keeping Unit" data-key="key">GRO-000-2331</div>
<div class="data" data-tag="sku" data-xpath="/top-level/data2/item/sku" data-type="string" data-help="Stock Keeping Unit" data-key="key">GRO-000-2331</div>
</div>
<div class="line">
<div class="label">Item</div>
<div class="text"> '</div>
<div class="data" data-tag="name" data-xpath="/top/data3/item/name" data-type="string" data-help="Name of the item" data-key="key">fish</div>
<div class="data" data-tag="name" data-xpath="/top-level/data3/item/name" data-type="string" data-help="Name of the item" data-key="key">fish</div>
<div class="text">':</div>
</div>
<div class="line">
<div class="padding"> </div>
<div class="label">Total sold</div>
<div class="text">: </div>
<div class="data" data-tag="sold" data-xpath="/top/data3/item[sku = 'GRO-000-533'][name = 'fish']/sold" data-type="number" data-help="Number of items sold">1321.0</div>
<div class="data" data-tag="sold" data-xpath="/top-level/data3/item[sku = 'GRO-000-533'][name = 'fish']/sold" data-type="number" data-help="Number of items sold">1321.0</div>
</div>
<div class="line">
<div class="padding"> </div>
<div class="label">In stock</div>
<div class="decoration">:</div>
<div class="padding"> </div>
<div class="data" data-tag="in-stock" data-xpath="/top/data3/item[sku = 'GRO-000-533'][name = 'fish']/in-stock" data-type="number" data-help="Number of items in stock">45</div>
<div class="data" data-tag="in-stock" data-xpath="/top-level/data3/item[sku = 'GRO-000-533'][name = 'fish']/in-stock" data-type="number" data-help="Number of items in stock">45</div>
</div>
<div class="line">
<div class="padding"> </div>
<div class="label">On order</div>
<div class="decoration">:</div>
<div class="padding"> </div>
<div class="data" data-tag="on-order" data-xpath="/top/data3/item[sku = 'GRO-000-533'][name = 'fish']/on-order" data-type="number" data-help="Number of items on order">1</div>
<div class="data" data-tag="on-order" data-xpath="/top-level/data3/item[sku = 'GRO-000-533'][name = 'fish']/on-order" data-type="number" data-help="Number of items on order">1</div>
</div>
<div class="line">
<div class="padding"> </div>
<div class="label">SKU</div>
<div class="text">: </div>
<div class="data" data-tag="sku" data-xpath="/top/data3/item/sku" data-type="string" data-help="Stock Keeping Unit" data-key="key">GRO-000-533</div>
<div class="data" data-tag="sku" data-xpath="/top-level/data3/item/sku" data-type="string" data-help="Stock Keeping Unit" data-key="key">GRO-000-533</div>
</div>
<div class="line">
<div class="label">Item</div>
<div class="decoration">:</div>
<div class="padding"> </div>
<div class="data" data-tag="item" data-xpath="/top/data4/item">gum</div>
<div class="data" data-tag="item" data-xpath="/top-level/data4/item">gum</div>
</div>
<div class="line">
<div class="label">Item</div>
<div class="decoration">:</div>
<div class="padding"> </div>
<div class="data" data-tag="item" data-xpath="/top/data4/item">rope</div>
<div class="data" data-tag="item" data-xpath="/top-level/data4/item">rope</div>
</div>
<div class="line">
<div class="label">Item</div>
<div class="decoration">:</div>
<div class="padding"> </div>
<div class="data" data-tag="item" data-xpath="/top/data4/item">ladder</div>
<div class="data" data-tag="item" data-xpath="/top-level/data4/item">ladder</div>
</div>
<div class="line">
<div class="label">Item</div>
<div class="decoration">:</div>
<div class="padding"> </div>
<div class="data" data-tag="item" data-xpath="/top/data4/item">bolt</div>
<div class="data" data-tag="item" data-xpath="/top-level/data4/item">bolt</div>
</div>
<div class="line">
<div class="label">Item</div>
<div class="decoration">:</div>
<div class="padding"> </div>
<div class="data" data-tag="item" data-xpath="/top/data4/item">water</div>
<div class="data" data-tag="item" data-xpath="/top-level/data4/item">water</div>
</div>
<div class="line">
<div class="title">Item </div>
@ -337,45 +340,45 @@
<div class="title"> SKU</div>
</div>
<div class="line">
<div class="data" data-tag="name" data-xpath="/top/data/item/name" data-type="string" data-help="Name of the item" data-key="key">gum </div>
<div class="data" data-tag="sold" data-xpath="/top/data/item[sku = 'GRO-000-415'][name = 'gum']/sold" data-type="number" data-help="Number of items sold"> 1412</div>
<div class="data" data-tag="on-order" data-xpath="/top/data/item[sku = 'GRO-000-415'][name = 'gum']/on-order" data-type="number" data-help="Number of items on order"> 10</div>
<div class="data" data-tag="in-stock" data-xpath="/top/data/item[sku = 'GRO-000-415'][name = 'gum']/in-stock" data-type="number" data-help="Number of items in stock"> 54</div>
<div class="data" data-tag="sku" data-xpath="/top/data/item/sku" data-type="string" data-help="Stock Keeping Unit" data-key="key"> GRO-000-415</div>
<div class="data" data-tag="name" data-xpath="/top-level/data/item/name" data-type="string" data-help="Name of the item" data-key="key">gum </div>
<div class="data" data-tag="sold" data-xpath="/top-level/data/item[sku = 'GRO-000-415'][name = 'gum']/sold" data-type="number" data-help="Number of items sold"> 1412</div>
<div class="data" data-tag="on-order" data-xpath="/top-level/data/item[sku = 'GRO-000-415'][name = 'gum']/on-order" data-type="number" data-help="Number of items on order"> 10</div>
<div class="data" data-tag="in-stock" data-xpath="/top-level/data/item[sku = 'GRO-000-415'][name = 'gum']/in-stock" data-type="number" data-help="Number of items in stock"> 54</div>
<div class="data" data-tag="sku" data-xpath="/top-level/data/item/sku" data-type="string" data-help="Stock Keeping Unit" data-key="key"> GRO-000-415</div>
</div>
<div class="line">
<div class="data" data-tag="name" data-xpath="/top/data/item/name" data-type="string" data-help="Name of the item" data-key="key">rope </div>
<div class="data" data-tag="sold" data-xpath="/top/data/item[sku = 'HRD-000-212'][name = 'rope']/sold" data-type="number" data-help="Number of items sold"> 85</div>
<div class="data" data-tag="name" data-xpath="/top-level/data/item/name" data-type="string" data-help="Name of the item" data-key="key">rope </div>
<div class="data" data-tag="sold" data-xpath="/top-level/data/item[sku = 'HRD-000-212'][name = 'rope']/sold" data-type="number" data-help="Number of items sold"> 85</div>
<div class="text">Extra: </div>
<div class="data" data-tag="extra" data-xpath="/top/data/item[sku = 'HRD-000-212'][name = 'rope']/extra">special</div>
<div class="data" data-tag="on-order" data-xpath="/top/data/item[sku = 'HRD-000-212'][name = 'rope']/on-order" data-type="number" data-help="Number of items on order"> 2</div>
<div class="data" data-tag="in-stock" data-xpath="/top/data/item[sku = 'HRD-000-212'][name = 'rope']/in-stock" data-type="number" data-help="Number of items in stock"> 4</div>
<div class="data" data-tag="sku" data-xpath="/top/data/item/sku" data-type="string" data-help="Stock Keeping Unit" data-key="key"> HRD-000-212</div>
<div class="data" data-tag="extra" data-xpath="/top-level/data/item[sku = 'HRD-000-212'][name = 'rope']/extra">special</div>
<div class="data" data-tag="on-order" data-xpath="/top-level/data/item[sku = 'HRD-000-212'][name = 'rope']/on-order" data-type="number" data-help="Number of items on order"> 2</div>
<div class="data" data-tag="in-stock" data-xpath="/top-level/data/item[sku = 'HRD-000-212'][name = 'rope']/in-stock" data-type="number" data-help="Number of items in stock"> 4</div>
<div class="data" data-tag="sku" data-xpath="/top-level/data/item/sku" data-type="string" data-help="Stock Keeping Unit" data-key="key"> HRD-000-212</div>
</div>
<div class="line">
<div class="data" data-tag="name" data-xpath="/top/data/item/name" data-type="string" data-help="Name of the item" data-key="key">ladder </div>
<div class="data" data-tag="sold" data-xpath="/top/data/item[sku = 'HRD-000-517'][name = 'ladder']/sold" data-type="number" data-help="Number of items sold"> 0</div>
<div class="data" data-tag="name" data-xpath="/top-level/data/item/name" data-type="string" data-help="Name of the item" data-key="key">ladder </div>
<div class="data" data-tag="sold" data-xpath="/top-level/data/item[sku = 'HRD-000-517'][name = 'ladder']/sold" data-type="number" data-help="Number of items sold"> 0</div>
<div class="text">Extra: </div>
<div class="data" data-tag="extra" data-xpath="/top/data/item[sku = 'HRD-000-517'][name = 'ladder']/extra">special</div>
<div class="data" data-tag="on-order" data-xpath="/top/data/item[sku = 'HRD-000-517'][name = 'ladder']/on-order" data-type="number" data-help="Number of items on order"> 1</div>
<div class="data" data-tag="in-stock" data-xpath="/top/data/item[sku = 'HRD-000-517'][name = 'ladder']/in-stock" data-type="number" data-help="Number of items in stock"> 2</div>
<div class="data" data-tag="sku" data-xpath="/top/data/item/sku" data-type="string" data-help="Stock Keeping Unit" data-key="key"> HRD-000-517</div>
<div class="data" data-tag="extra" data-xpath="/top-level/data/item[sku = 'HRD-000-517'][name = 'ladder']/extra">special</div>
<div class="data" data-tag="on-order" data-xpath="/top-level/data/item[sku = 'HRD-000-517'][name = 'ladder']/on-order" data-type="number" data-help="Number of items on order"> 1</div>
<div class="data" data-tag="in-stock" data-xpath="/top-level/data/item[sku = 'HRD-000-517'][name = 'ladder']/in-stock" data-type="number" data-help="Number of items in stock"> 2</div>
<div class="data" data-tag="sku" data-xpath="/top-level/data/item/sku" data-type="string" data-help="Stock Keeping Unit" data-key="key"> HRD-000-517</div>
</div>
<div class="line">
<div class="data" data-tag="name" data-xpath="/top/data/item/name" data-type="string" data-help="Name of the item" data-key="key">bolt </div>
<div class="data" data-tag="sold" data-xpath="/top/data/item[sku = 'HRD-000-632'][name = 'bolt']/sold" data-type="number" data-help="Number of items sold"> 4123</div>
<div class="data" data-tag="on-order" data-xpath="/top/data/item[sku = 'HRD-000-632'][name = 'bolt']/on-order" data-type="number" data-help="Number of items on order"> 42</div>
<div class="data" data-tag="in-stock" data-xpath="/top/data/item[sku = 'HRD-000-632'][name = 'bolt']/in-stock" data-type="number" data-help="Number of items in stock"> 144</div>
<div class="data" data-tag="sku" data-xpath="/top/data/item/sku" data-type="string" data-help="Stock Keeping Unit" data-key="key"> HRD-000-632</div>
<div class="data" data-tag="name" data-xpath="/top-level/data/item/name" data-type="string" data-help="Name of the item" data-key="key">bolt </div>
<div class="data" data-tag="sold" data-xpath="/top-level/data/item[sku = 'HRD-000-632'][name = 'bolt']/sold" data-type="number" data-help="Number of items sold"> 4123</div>
<div class="data" data-tag="on-order" data-xpath="/top-level/data/item[sku = 'HRD-000-632'][name = 'bolt']/on-order" data-type="number" data-help="Number of items on order"> 42</div>
<div class="data" data-tag="in-stock" data-xpath="/top-level/data/item[sku = 'HRD-000-632'][name = 'bolt']/in-stock" data-type="number" data-help="Number of items in stock"> 144</div>
<div class="data" data-tag="sku" data-xpath="/top-level/data/item/sku" data-type="string" data-help="Stock Keeping Unit" data-key="key"> HRD-000-632</div>
</div>
<div class="line">
<div class="data" data-tag="name" data-xpath="/top/data/item/name" data-type="string" data-help="Name of the item" data-key="key">water </div>
<div class="data" data-tag="sold" data-xpath="/top/data/item[sku = 'GRO-000-2331'][name = 'water']/sold" data-type="number" data-help="Number of items sold"> 17</div>
<div class="data" data-tag="name" data-xpath="/top-level/data/item/name" data-type="string" data-help="Name of the item" data-key="key">water </div>
<div class="data" data-tag="sold" data-xpath="/top-level/data/item[sku = 'GRO-000-2331'][name = 'water']/sold" data-type="number" data-help="Number of items sold"> 17</div>
<div class="text">Extra: </div>
<div class="data" data-tag="extra" data-xpath="/top/data/item[sku = 'GRO-000-2331'][name = 'water']/extra">special</div>
<div class="data" data-tag="on-order" data-xpath="/top/data/item[sku = 'GRO-000-2331'][name = 'water']/on-order" data-type="number" data-help="Number of items on order"> 2</div>
<div class="data" data-tag="in-stock" data-xpath="/top/data/item[sku = 'GRO-000-2331'][name = 'water']/in-stock" data-type="number" data-help="Number of items in stock"> 14</div>
<div class="data" data-tag="sku" data-xpath="/top/data/item/sku" data-type="string" data-help="Stock Keeping Unit" data-key="key"> GRO-000-2331</div>
<div class="data" data-tag="extra" data-xpath="/top-level/data/item[sku = 'GRO-000-2331'][name = 'water']/extra">special</div>
<div class="data" data-tag="on-order" data-xpath="/top-level/data/item[sku = 'GRO-000-2331'][name = 'water']/on-order" data-type="number" data-help="Number of items on order"> 2</div>
<div class="data" data-tag="in-stock" data-xpath="/top-level/data/item[sku = 'GRO-000-2331'][name = 'water']/in-stock" data-type="number" data-help="Number of items in stock"> 14</div>
<div class="data" data-tag="sku" data-xpath="/top-level/data/item/sku" data-type="string" data-help="Stock Keeping Unit" data-key="key"> GRO-000-2331</div>
</div>
<div class="line">
</div>
@ -398,7 +401,7 @@
<div class="label">Cost</div>
<div class="decoration">:</div>
<div class="padding"> </div>
<div class="data" data-tag="cost" data-xpath="/top/cost">425</div>
<div class="data" data-tag="cost" data-xpath="/top-level/cost">425</div>
</div>
<div class="line">
<div class="text">X</div>
@ -407,28 +410,28 @@
<div class="label">Cost</div>
<div class="decoration">:</div>
<div class="padding"> </div>
<div class="data" data-tag="cost" data-xpath="/top/cost">455</div>
<div class="data" data-tag="cost" data-xpath="/top-level/cost">455</div>
</div>
<div class="line">
<div class="text"> </div>
<div class="data" data-tag="links" data-xpath="/top/links">links</div>
<div class="data" data-tag="links" data-xpath="/top-level/links">links</div>
<div class="text"> </div>
<div class="data" data-tag="user" data-xpath="/top/user">user</div>
<div class="data" data-tag="user" data-xpath="/top-level/user">user</div>
<div class="text"> </div>
<div class="data" data-tag="group" data-xpath="/top/group">group</div>
<div class="data" data-tag="group" data-xpath="/top-level/group">group</div>
<div class="text"> </div>
</div>
<div class="line">
<div class="data" data-tag="links" data-xpath="/top/links">3 </div>
<div class="data" data-tag="post" data-xpath="/top/post">this </div>
<div class="data" data-tag="links" data-xpath="/top-level/links">3 </div>
<div class="data" data-tag="post" data-xpath="/top-level/post">this </div>
</div>
<div class="line">
<div class="data" data-tag="mode" data-xpath="/top/mode">/some/file</div>
<div class="data" data-tag="mode" data-xpath="/top-level/mode">/some/file</div>
<div class="text"> </div>
<div class="data" data-tag="links" data-xpath="/top/links"> 1</div>
<div class="data" data-tag="links" data-xpath="/top-level/links"> 1</div>
<div class="text"> </div>
<div class="data" data-tag="user" data-xpath="/top/user">user </div>
<div class="data" data-tag="user" data-xpath="/top-level/user">user </div>
<div class="text"> </div>
<div class="data" data-tag="group" data-xpath="/top/group">group </div>
<div class="data" data-tag="group" data-xpath="/top-level/group">group </div>
<div class="text"> </div>
</div>

View File

@ -51,10 +51,13 @@
<div class="data" data-tag="label">value</div>
</div>
<div class="line">
<div class="title">My Title
</div>
<div class="data" data-tag="max-chaos"> very </div>
<div class="data" data-tag="min-chaos">42</div>
<div class="data" data-tag="some-chaos">42
</div>
<div class="data" data-tag="sku">gum-1412</div>
<div class="text">Connecting to </div>
<div class="data" data-tag="host">my-box</div>
<div class="text">.</div>

View File

@ -1 +1 @@
{"top": {"type":"ethernet","type":"bridge","type":"18u","type":24,"address":"0x0","port":1,"address":"0x0","port":1,"address":"0x0","port":1,"used-percent":12,"kve_start":"0xdeadbeef","kve_end":"0xcabb1e","host":"my-box","domain":"example.com","host":"my-box","domain":"example.com","label":"value","max-chaos":"very","min-chaos":42,"some-chaos":"[42]","host":"my-box","domain":"example.com", "data": {"item": [{"sku":"GRO-000-415","name":"gum","sold":1412,"in-stock":54,"on-order":10}, {"sku":"HRD-000-212","name":"rope","sold":85,"in-stock":4,"on-order":2}, {"sku":"HRD-000-517","name":"ladder","sold":0,"in-stock":2,"on-order":1}, {"sku":"HRD-000-632","name":"bolt","sold":4123,"in-stock":144,"on-order":42}, {"sku":"GRO-000-2331","name":"water","sold":17,"in-stock":14,"on-order":2}]}, "data2": {"item": [{"sku":"GRO-000-415","name":"gum","sold":1412.0,"in-stock":54,"on-order":10}, {"sku":"HRD-000-212","name":"rope","sold":85.0,"in-stock":4,"on-order":2}, {"sku":"HRD-000-517","name":"ladder","sold":0,"in-stock":2,"on-order":1}, {"sku":"HRD-000-632","name":"bolt","sold":4123.0,"in-stock":144,"on-order":42}, {"sku":"GRO-000-2331","name":"water","sold":17.0,"in-stock":14,"on-order":2}]}, "data3": {"item": [{"sku":"GRO-000-533","name":"fish","sold":1321.0,"in-stock":45,"on-order":1}]}, "data4": {"item": ["gum","rope","ladder","bolt","water"]}, "data": {"item": [{"sku":"GRO-000-415","name":"gum","sold":1412,"on-order":10,"in-stock":54}, {"sku":"HRD-000-212","name":"rope","sold":85,"extra":"special","on-order":2,"in-stock":4}, {"sku":"HRD-000-517","name":"ladder","sold":0,"extra":"special","on-order":1,"in-stock":2}, {"sku":"HRD-000-632","name":"bolt","sold":4123,"on-order":42,"in-stock":144}, {"sku":"GRO-000-2331","name":"water","sold":17,"extra":"special","on-order":2,"in-stock":14}]},"cost":425,"cost":455,"mode":"mode","mode_octal":"octal","links":"links","user":"user","group":"group","pre":"that","links":3,"post":"this","mode":"/some/file","mode_octal":640,"links":1,"user":"user","group":"group"}}
{"top-level": {"type":"ethernet","type":"bridge","type":"18u","type":24,"address":"0x0","port":1,"address":"0x0","port":1,"address":"0x0","port":1,"used-percent":12,"kve_start":"0xdeadbeef","kve_end":"0xcabb1e","host":"my-box","domain":"example.com","host":"my-box","domain":"example.com","label":"value","max-chaos":"very","min-chaos":42,"some-chaos":"[42]", "sku": ["gum-000-1412"],"host":"my-box","domain":"example.com", "data": {"item": [{"sku":"GRO-000-415","name":"gum","sold":1412,"in-stock":54,"on-order":10}, {"sku":"HRD-000-212","name":"rope","sold":85,"in-stock":4,"on-order":2}, {"sku":"HRD-000-517","name":"ladder","sold":0,"in-stock":2,"on-order":1}, {"sku":"HRD-000-632","name":"bolt","sold":4123,"in-stock":144,"on-order":42}, {"sku":"GRO-000-2331","name":"water","sold":17,"in-stock":14,"on-order":2}]}, "data2": {"item": [{"sku":"GRO-000-415","name":"gum","sold":1412.0,"in-stock":54,"on-order":10}, {"sku":"HRD-000-212","name":"rope","sold":85.0,"in-stock":4,"on-order":2}, {"sku":"HRD-000-517","name":"ladder","sold":0,"in-stock":2,"on-order":1}, {"sku":"HRD-000-632","name":"bolt","sold":4123.0,"in-stock":144,"on-order":42}, {"sku":"GRO-000-2331","name":"water","sold":17.0,"in-stock":14,"on-order":2}]}, "data3": {"item": [{"sku":"GRO-000-533","name":"fish","sold":1321.0,"in-stock":45,"on-order":1}]}, "data4": {"item": ["gum","rope","ladder","bolt","water"]}, "data": {"item": [{"sku":"GRO-000-415","name":"gum","sold":1412,"on-order":10,"in-stock":54}, {"sku":"HRD-000-212","name":"rope","sold":85,"extra":"special","on-order":2,"in-stock":4}, {"sku":"HRD-000-517","name":"ladder","sold":0,"extra":"special","on-order":1,"in-stock":2}, {"sku":"HRD-000-632","name":"bolt","sold":4123,"on-order":42,"in-stock":144}, {"sku":"GRO-000-2331","name":"water","sold":17,"extra":"special","on-order":2,"in-stock":14}]},"cost":425,"cost":455,"mode":"mode","mode_octal":"octal","links":"links","user":"user","group":"group","pre":"that","links":3,"post":"this","mode":"/some/file","mode_octal":640,"links":1,"user":"user","group":"group"}}

View File

@ -1,5 +1,5 @@
{
"top": {
"top-level": {
"type": "ethernet",
"type": "bridge",
"type": "18u",
@ -21,6 +21,9 @@
"max-chaos": "very",
"min-chaos": 42,
"some-chaos": "[42]",
"sku": [
"gum-000-1412"
],
"host": "my-box",
"domain": "example.com",
"data": {

View File

@ -0,0 +1,185 @@
{
"top_level": {
"type": "ethernet",
"type": "bridge",
"type": "18u",
"type": 24,
"address": "0x0",
"port": 1,
"address": "0x0",
"port": 1,
"address": "0x0",
"port": 1,
"used_percent": 12,
"kve_start": "0xdeadbeef",
"kve_end": "0xcabb1e",
"host": "my-box",
"domain": "example.com",
"host": "my-box",
"domain": "example.com",
"label": "value",
"max_chaos": "very",
"min_chaos": 42,
"some_chaos": "[42]",
"sku": [
"gum-000-1412"
],
"host": "my-box",
"domain": "example.com",
"data": {
"item": [
{
"sku": "GRO-000-415",
"name": "gum",
"sold": 1412,
"in_stock": 54,
"on_order": 10
},
{
"sku": "HRD-000-212",
"name": "rope",
"sold": 85,
"in_stock": 4,
"on_order": 2
},
{
"sku": "HRD-000-517",
"name": "ladder",
"sold": 0,
"in_stock": 2,
"on_order": 1
},
{
"sku": "HRD-000-632",
"name": "bolt",
"sold": 4123,
"in_stock": 144,
"on_order": 42
},
{
"sku": "GRO-000-2331",
"name": "water",
"sold": 17,
"in_stock": 14,
"on_order": 2
}
]
},
"data2": {
"item": [
{
"sku": "GRO-000-415",
"name": "gum",
"sold": 1412.0,
"in_stock": 54,
"on_order": 10
},
{
"sku": "HRD-000-212",
"name": "rope",
"sold": 85.0,
"in_stock": 4,
"on_order": 2
},
{
"sku": "HRD-000-517",
"name": "ladder",
"sold": 0,
"in_stock": 2,
"on_order": 1
},
{
"sku": "HRD-000-632",
"name": "bolt",
"sold": 4123.0,
"in_stock": 144,
"on_order": 42
},
{
"sku": "GRO-000-2331",
"name": "water",
"sold": 17.0,
"in_stock": 14,
"on_order": 2
}
]
},
"data3": {
"item": [
{
"sku": "GRO-000-533",
"name": "fish",
"sold": 1321.0,
"in_stock": 45,
"on_order": 1
}
]
},
"data4": {
"item": [
"gum",
"rope",
"ladder",
"bolt",
"water"
]
},
"data": {
"item": [
{
"sku": "GRO-000-415",
"name": "gum",
"sold": 1412,
"on_order": 10,
"in_stock": 54
},
{
"sku": "HRD-000-212",
"name": "rope",
"sold": 85,
"extra": "special",
"on_order": 2,
"in_stock": 4
},
{
"sku": "HRD-000-517",
"name": "ladder",
"sold": 0,
"extra": "special",
"on_order": 1,
"in_stock": 2
},
{
"sku": "HRD-000-632",
"name": "bolt",
"sold": 4123,
"on_order": 42,
"in_stock": 144
},
{
"sku": "GRO-000-2331",
"name": "water",
"sold": 17,
"extra": "special",
"on_order": 2,
"in_stock": 14
}
]
},
"cost": 425,
"cost": 455,
"mode": "mode",
"mode_octal": "octal",
"links": "links",
"user": "user",
"group": "group",
"pre": "that",
"links": 3,
"post": "this",
"mode": "/some/file",
"mode_octal": 640,
"links": 1,
"user": "user",
"group": "group"
}
}

View File

@ -5,8 +5,9 @@ df 12%
testing argument modifier my-box.example.com...
testing argument modifier with encoding to .example.com...
Label text value
My Title
very 4242
Connecting to my-box.example.com...
gum-1412Connecting to my-box.example.com...
Item Total Sold In Stock On Order SKU
gum 1412 54 10 GRO-000-415
rope 85 4 2 HRD-000-212

View File

@ -1 +1 @@
<top><type>ethernet</type><type>bridge</type><type>18u</type><type>24</type><address>0x0</address><port>1</port><address>0x0</address><port>1</port><address>0x0</address><port>1</port><used-percent>12</used-percent><kve_start>0xdeadbeef</kve_start><kve_end>0xcabb1e</kve_end><host>my-box</host><domain>example.com</domain><host>my-box</host><domain>example.com</domain><label>value</label><max-chaos>very</max-chaos><min-chaos>42</min-chaos><some-chaos>[42]</some-chaos><host>my-box</host><domain>example.com</domain><data test="value"><item test2="value2"><sku test3="value3" key="key">GRO-000-415</sku><name key="key">gum</name><sold>1412</sold><in-stock>54</in-stock><on-order>10</on-order></item><item><sku test3="value3" key="key">HRD-000-212</sku><name key="key">rope</name><sold>85</sold><in-stock>4</in-stock><on-order>2</on-order></item><item><sku test3="value3" key="key">HRD-000-517</sku><name key="key">ladder</name><sold>0</sold><in-stock>2</in-stock><on-order>1</on-order></item><item><sku test3="value3" key="key">HRD-000-632</sku><name key="key">bolt</name><sold>4123</sold><in-stock>144</in-stock><on-order>42</on-order></item><item><sku test3="value3" key="key">GRO-000-2331</sku><name key="key">water</name><sold>17</sold><in-stock>14</in-stock><on-order>2</on-order></item></data><data2><item><sku key="key">GRO-000-415</sku><name key="key">gum</name><sold>1412.0</sold><in-stock>54</in-stock><on-order>10</on-order></item><item><sku key="key">HRD-000-212</sku><name key="key">rope</name><sold>85.0</sold><in-stock>4</in-stock><on-order>2</on-order></item><item><sku key="key">HRD-000-517</sku><name key="key">ladder</name><sold>0</sold><in-stock>2</in-stock><on-order>1</on-order></item><item><sku key="key">HRD-000-632</sku><name key="key">bolt</name><sold>4123.0</sold><in-stock>144</in-stock><on-order>42</on-order></item><item><sku key="key">GRO-000-2331</sku><name key="key">water</name><sold>17.0</sold><in-stock>14</in-stock><on-order>2</on-order></item></data2><data3><item><sku key="key">GRO-000-533</sku><name key="key">fish</name><sold>1321.0</sold><in-stock>45</in-stock><on-order>1</on-order></item></data3><data4><item test4="value4">gum</item><item test4="value4">rope</item><item test4="value4">ladder</item><item test4="value4">bolt</item><item test4="value4">water</item></data4><data test="value"><item test2="value2"><sku test3="value3" key="key">GRO-000-415</sku><name key="key">gum</name><sold>1412</sold><on-order>10</on-order><in-stock>54</in-stock></item><item><sku test3="value3" key="key">HRD-000-212</sku><name key="key">rope</name><sold>85</sold><extra>special</extra><on-order>2</on-order><in-stock>4</in-stock></item><item><sku test3="value3" key="key">HRD-000-517</sku><name key="key">ladder</name><sold>0</sold><extra>special</extra><on-order>1</on-order><in-stock>2</in-stock></item><item><sku test3="value3" key="key">HRD-000-632</sku><name key="key">bolt</name><sold>4123</sold><on-order>42</on-order><in-stock>144</in-stock></item><item><sku test3="value3" key="key">GRO-000-2331</sku><name key="key">water</name><sold>17</sold><extra>special</extra><on-order>2</on-order><in-stock>14</in-stock></item></data><cost>425</cost><cost>455</cost><mode>mode</mode><mode_octal>octal</mode_octal><links>links</links><user>user</user><group>group</group><pre>that</pre><links>3</links><post>this</post><mode>/some/file</mode><mode_octal>640</mode_octal><links>1</links><user>user</user><group>group</group></top>
<top-level><type>ethernet</type><type>bridge</type><type>18u</type><type>24</type><address>0x0</address><port>1</port><address>0x0</address><port>1</port><address>0x0</address><port>1</port><used-percent>12</used-percent><kve_start>0xdeadbeef</kve_start><kve_end>0xcabb1e</kve_end><host>my-box</host><domain>example.com</domain><host>my-box</host><domain>example.com</domain><label>value</label><max-chaos>very</max-chaos><min-chaos>42</min-chaos><some-chaos>[42]</some-chaos><sku test-attr="attr-value">gum-000-1412</sku><host>my-box</host><domain>example.com</domain><data test="value"><item test2="value2"><sku test3="value3" key="key">GRO-000-415</sku><name key="key">gum</name><sold>1412</sold><in-stock>54</in-stock><on-order>10</on-order></item><item><sku test3="value3" key="key">HRD-000-212</sku><name key="key">rope</name><sold>85</sold><in-stock>4</in-stock><on-order>2</on-order></item><item><sku test3="value3" key="key">HRD-000-517</sku><name key="key">ladder</name><sold>0</sold><in-stock>2</in-stock><on-order>1</on-order></item><item><sku test3="value3" key="key">HRD-000-632</sku><name key="key">bolt</name><sold>4123</sold><in-stock>144</in-stock><on-order>42</on-order></item><item><sku test3="value3" key="key">GRO-000-2331</sku><name key="key">water</name><sold>17</sold><in-stock>14</in-stock><on-order>2</on-order></item></data><data2><item><sku key="key">GRO-000-415</sku><name key="key">gum</name><sold>1412.0</sold><in-stock>54</in-stock><on-order>10</on-order></item><item><sku key="key">HRD-000-212</sku><name key="key">rope</name><sold>85.0</sold><in-stock>4</in-stock><on-order>2</on-order></item><item><sku key="key">HRD-000-517</sku><name key="key">ladder</name><sold>0</sold><in-stock>2</in-stock><on-order>1</on-order></item><item><sku key="key">HRD-000-632</sku><name key="key">bolt</name><sold>4123.0</sold><in-stock>144</in-stock><on-order>42</on-order></item><item><sku key="key">GRO-000-2331</sku><name key="key">water</name><sold>17.0</sold><in-stock>14</in-stock><on-order>2</on-order></item></data2><data3><item><sku key="key">GRO-000-533</sku><name key="key">fish</name><sold>1321.0</sold><in-stock>45</in-stock><on-order>1</on-order></item></data3><data4><item test4="value4">gum</item><item test4="value4">rope</item><item test4="value4">ladder</item><item test4="value4">bolt</item><item test4="value4">water</item></data4><data test="value"><item test2="value2"><sku test3="value3" key="key">GRO-000-415</sku><name key="key">gum</name><sold>1412</sold><on-order>10</on-order><in-stock>54</in-stock></item><item><sku test3="value3" key="key">HRD-000-212</sku><name key="key">rope</name><sold>85</sold><extra>special</extra><on-order>2</on-order><in-stock>4</in-stock></item><item><sku test3="value3" key="key">HRD-000-517</sku><name key="key">ladder</name><sold>0</sold><extra>special</extra><on-order>1</on-order><in-stock>2</in-stock></item><item><sku test3="value3" key="key">HRD-000-632</sku><name key="key">bolt</name><sold>4123</sold><on-order>42</on-order><in-stock>144</in-stock></item><item><sku test3="value3" key="key">GRO-000-2331</sku><name key="key">water</name><sold>17</sold><extra>special</extra><on-order>2</on-order><in-stock>14</in-stock></item></data><cost>425</cost><cost>455</cost><mode>mode</mode><mode_octal>octal</mode_octal><links>links</links><user>user</user><group>group</group><pre>that</pre><links>3</links><post>this</post><mode>/some/file</mode><mode_octal>640</mode_octal><links>1</links><user>user</user><group>group</group></top-level>

View File

@ -1,4 +1,4 @@
<top>
<top-level>
<type>ethernet</type>
<type>bridge</type>
<type>18u</type>
@ -20,6 +20,7 @@
<max-chaos>very</max-chaos>
<min-chaos>42</min-chaos>
<some-chaos>[42]</some-chaos>
<sku test-attr="attr-value">gum-000-1412</sku>
<host>my-box</host>
<domain>example.com</domain>
<data test="value">
@ -167,4 +168,4 @@
<links>1</links>
<user>user</user>
<group>group</group>
</top>
</top-level>

View File

@ -23,6 +23,7 @@ op content: [bytes] [2] [0x2004]
op content: [bytes] [3] [0x2004]
op content: [bytes] [4] [0x2004]
op close_leaf_list: [bytes] [] [0]
op content: [granularity-lw] [155] [0]
op content: [mbuf-current] [10] [0]
op content: [mbuf-cache] [20] [0]
op content: [mbuf-total] [30] [0]

File diff suppressed because one or more lines are too long

View File

@ -78,6 +78,13 @@
<div class="padding"> </div>
<div class="note">bytes</div>
</div>
<div class="line">
<div class="label">Low/warn granularity</div>
<div class="decoration">:</div>
<div class="padding"> </div>
<div class="data" data-tag="granularity-lw" data-units="mAh" data-xpath="/top/data[name = 'em0 '][name = 'em0']/granularity-lw">155</div>
<div class="padding"> </div>
</div>
<div class="line">
<div class="data" data-tag="mbuf-current" data-xpath="/top/data[name = 'em0 '][name = 'em0']/mbuf-current">10</div>
<div class="text">/</div>

View File

@ -78,6 +78,13 @@
<div class="padding"> </div>
<div class="note">bytes</div>
</div>
<div class="line">
<div class="label">Low/warn granularity</div>
<div class="decoration">:</div>
<div class="padding"> </div>
<div class="data" data-tag="granularity-lw" data-units="mAh">155</div>
<div class="padding"> </div>
</div>
<div class="line">
<div class="data" data-tag="mbuf-current">10</div>
<div class="text">/</div>

View File

@ -1 +1 @@
{"top": {"data": {"name":"em0","flags":"0x8843","name":"em0","flags":"0x8843","what":"braces","length":"abcdef","fd":-1,"error":"Bad file descriptor","test":"good","fd":-1,"error":"Bad fi","test":"good","lines":20,"words":30,"characters":40, "bytes": [0,1,2,3,4],"mbuf-current":10,"mbuf-cache":20,"mbuf-total":30,"distance":50,"location":"Boston","memory":64,"total":640,"memory":64,"total":640,"ten":10,"eleven":11,"unknown":1010,"unknown":1010,"min":15,"cur":20,"max":125,"min":15,"cur":20,"max":125,"min":15,"cur":20,"max":125,"min":15,"cur":20,"max":125,"val1":21,"val2":58368,"val3":100663296,"val4":44470272,"val5":1342172800, "flag": ["one","two","three"],"works":null,"empty-tag":true,"t1":"1000","t2":"test5000","t3":"ten-longx","t4":"xtest", "__error": {"message":"this is an error"}, "__error": {"message":"two more errors"}, "__warning": {"message":"this is an warning"}, "__warning": {"message":"two more warnings"},"count":10,"test":4, "error": {"message":"Shut 'er down, Clancey! She's a-pumpin' mud! <>!,\"!<>\n"}, "error": {"message":"err message (1)"}, "error": {"message":"err message (2)\n"}, "error": {"message":"err message (1)\n"}, "error": {"message":"err message (2)\n"}}}}
{"top": {"data": {"name":"em0","flags":"0x8843","name":"em0","flags":"0x8843","what":"braces","length":"abcdef","fd":-1,"error":"Bad file descriptor","test":"good","fd":-1,"error":"Bad fi","test":"good","lines":20,"words":30,"characters":40, "bytes": [0,1,2,3,4],"granularity-lw":155,"mbuf-current":10,"mbuf-cache":20,"mbuf-total":30,"distance":50,"location":"Boston","memory":64,"total":640,"memory":64,"total":640,"ten":10,"eleven":11,"unknown":1010,"unknown":1010,"min":15,"cur":20,"max":125,"min":15,"cur":20,"max":125,"min":15,"cur":20,"max":125,"min":15,"cur":20,"max":125,"val1":21,"val2":58368,"val3":100663296,"val4":44470272,"val5":1342172800, "flag": ["one","two","three"],"works":null,"empty-tag":true,"t1":"1000","t2":"test5000","t3":"ten-longx","t4":"xtest", "__error": {"message":"this is an error"}, "__error": {"message":"two more errors"}, "__warning": {"message":"this is an warning"}, "__warning": {"message":"two more warnings"},"count":10,"test":4, "error": {"message":"Shut 'er down, Clancey! She's a-pumpin' mud! <>!,\"!<>\n"}, "error": {"message":"err message (1)"}, "error": {"message":"err message (2)\n"}, "error": {"message":"err message (1)\n"}, "error": {"message":"err message (2)\n"}}}}

View File

@ -23,6 +23,7 @@
3,
4
],
"granularity-lw": 155,
"mbuf-current": 10,
"mbuf-cache": 20,
"mbuf-total": 30,

View File

@ -0,0 +1 @@
test_02: key field emitted after normal value field: 'name'

View File

@ -0,0 +1,99 @@
{
"top": {
"data": {
"name": "em0",
"flags": "0x8843",
"name": "em0",
"flags": "0x8843",
"what": "braces",
"length": "abcdef",
"fd": -1,
"error": "Bad file descriptor",
"test": "good",
"fd": -1,
"error": "Bad fi",
"test": "good",
"lines": 20,
"words": 30,
"characters": 40,
"bytes": [
0,
1,
2,
3,
4
],
"granularity_lw": 155,
"mbuf_current": 10,
"mbuf_cache": 20,
"mbuf_total": 30,
"distance": 50,
"location": "Boston",
"memory": 64,
"total": 640,
"memory": 64,
"total": 640,
"ten": 10,
"eleven": 11,
"unknown": 1010,
"unknown": 1010,
"min": 15,
"cur": 20,
"max": 125,
"min": 15,
"cur": 20,
"max": 125,
"min": 15,
"cur": 20,
"max": 125,
"min": 15,
"cur": 20,
"max": 125,
"val1": 21,
"val2": 58368,
"val3": 100663296,
"val4": 44470272,
"val5": 1342172800,
"flag": [
"one",
"two",
"three"
],
"works": null,
"empty_tag": true,
"t1": "1000",
"t2": "test5000",
"t3": "ten-longx",
"t4": "xtest",
"__error": {
"message": "this is an error"
},
"__error": {
"message": "two more errors"
},
"__warning": {
"message": "this is an warning"
},
"__warning": {
"message": "two more warnings"
},
"count": 10,
"test": 4,
"error": {
"message": "Shut 'er down, Clancey! She's a-pumpin' mud! <>!,\"!<>\n"
},
"error": {
"message": "err message (1)"
},
"error": {
"message": "err message (2)\n"
},
"error": {
"message": "err message (1)\n"
},
"error": {
"message": "err message (2)\n"
}
}
}
}

View File

@ -12,6 +12,7 @@ improper use of profanity; ten yard penalty; first down
2 bytes
3 bytes
4 bytes
Low/warn granularity: 155 mAh
10/20/30 mbufs <&> in use (current/cache/total)
50 miles from Boston
64k left out of 640kb

View File

@ -2,7 +2,7 @@
</message><message>abcdef: Bad file descriptor
</message><message>improper use of profanity; ten yard penalty; first down
</message><length>abcdef</length><fd>-1</fd><error>Bad file descriptor</error><test>good</test><fd>-1</fd><error>Bad fi</error><test>good</test><message>improper use of profanity; ten yard penalty; first down
</message><lines>20</lines><words>30</words><characters>40</characters><bytes>0</bytes><bytes>1</bytes><bytes>2</bytes><bytes>3</bytes><bytes>4</bytes><mbuf-current>10</mbuf-current><mbuf-cache>20</mbuf-cache><mbuf-total>30</mbuf-total><distance units="miles">50</distance><location>Boston</location><memory units="k">64</memory><total units="kb">640</total><memory units="k">64</memory><total units="kilobytes">640</total><ten>10</ten><eleven>11</eleven><unknown>1010</unknown><unknown>1010</unknown><min>15</min><cur>20</cur><max>125</max><min>15</min><cur>20</cur><max>125</max><min>15</min><cur>20</cur><max>125</max><min>15</min><cur>20</cur><max>125</max><val1>21</val1><val2>58368</val2><val3>100663296</val3><val4>44470272</val4><val5>1342172800</val5><flag>one</flag><flag>two</flag><flag>three</flag><works>null</works><empty-tag></empty-tag><t1>1000</t1><t2>test5000</t2><t3>ten-longx</t3><t4>xtest</t4><__error><message>this is an error</message></__error><__error><message>two more errors</message></__error><__warning><message>this is an warning</message></__warning><__warning><message>two more warnings</message></__warning><count>10</count><test>4</test><message>improper use of profanity; ten yard penalty; first down
</message><lines>20</lines><words>30</words><characters>40</characters><bytes>0</bytes><bytes>1</bytes><bytes>2</bytes><bytes>3</bytes><bytes>4</bytes><granularity-lw units="mAh">155</granularity-lw><mbuf-current>10</mbuf-current><mbuf-cache>20</mbuf-cache><mbuf-total>30</mbuf-total><distance units="miles">50</distance><location>Boston</location><memory units="k">64</memory><total units="kb">640</total><memory units="k">64</memory><total units="kilobytes">640</total><ten>10</ten><eleven>11</eleven><unknown>1010</unknown><unknown>1010</unknown><min>15</min><cur>20</cur><max>125</max><min>15</min><cur>20</cur><max>125</max><min>15</min><cur>20</cur><max>125</max><min>15</min><cur>20</cur><max>125</max><val1>21</val1><val2>58368</val2><val3>100663296</val3><val4>44470272</val4><val5>1342172800</val5><flag>one</flag><flag>two</flag><flag>three</flag><works>null</works><empty-tag></empty-tag><t1>1000</t1><t2>test5000</t2><t3>ten-longx</t3><t4>xtest</t4><__error><message>this is an error</message></__error><__error><message>two more errors</message></__error><__warning><message>this is an warning</message></__warning><__warning><message>two more warnings</message></__warning><count>10</count><test>4</test><message>improper use of profanity; ten yard penalty; first down
</message><error><message>Shut 'er down, Clancey! She's a-pumpin' mud! &lt;&gt;!,"!&lt;&gt;
</message></error><error><message>err message (1)</message></error><error><message>err message (2)
</message></error><error><message>err message (1)

View File

@ -28,6 +28,7 @@
<bytes>2</bytes>
<bytes>3</bytes>
<bytes>4</bytes>
<granularity-lw units="mAh">155</granularity-lw>
<mbuf-current>10</mbuf-current>
<mbuf-cache>20</mbuf-cache>
<mbuf-total>30</mbuf-total>

View File

@ -0,0 +1,33 @@
{
"employees": {
"employee": [
],
"extra": "",
"memory": [
{
"type": "name",
"in_use": 12345,
"memory_use": 54321,
"high_use": "-",
"requests": 32145
}
],
"employee": [
{
"first_name": "Terry",
"last_name": "Jones",
"department": 660
},
{
"first_name": "Leslie",
"last_name": "Patterson",
"department": 341
},
{
"first_name": "Ashley",
"last_name": "Smith",
"department": 1440
}
]
}
}

View File

@ -0,0 +1,21 @@
{
"employees": {
"employee": [
{
"first_name": "Terry",
"last_name": "Jones",
"department": 660
},
{
"first_name": "Leslie",
"last_name": "Patterson",
"department": 341
},
{
"first_name": "Ashley",
"last_name": "Smith",
"department": 1440
}
]
}
}

View File

@ -0,0 +1,91 @@
{
"indian_languages": {
"gurmukhi": "ਲਹੌਰ ਪਾਕਿਸਤਾਨੀ ਪੰਜਾਬ ਦੀ ਰਾਜਧਾਨੀ ਹੈ । ਲੋਕ ਗਿਣਤੀ ਦੇ ਨਾਲ ਕਰਾਚੀ ਤੋਂ ਬਾਅਦ ਲਹੌਰ ਦੂਜਾ ਸਭ ਤੋਂ ਵੱਡਾ ਸ਼ਹਿਰ ਹੈ । ਲਹੌਰ ਪਾਕਿਸਤਾਨ ਦਾ ਸਿਆਸੀ, ਰਹਤਲੀ ਤੇ ਪੜ੍ਹਾਈ ਦਾ ਗੜ੍ਹ ਹੈ ਅਤੇ ਇਸ ਲਈ ਇਹਨੂੰ ਪਾਕਿਸਤਾਨ ਦਾ ਦਿਲ ਵੀ ਕਿਹਾ ਜਾਂਦਾ ਹੈ । ਲਹੌਰ ਦਰਿਆ-ਏ-ਰਾਵੀ ਦੇ ਕੰਢੇ ਤੇ ਵਸਦਾ ਹੈ ਤੇ ਇਸਦੀ ਲੋਕ ਗਿਣਤੀ ਇੱਕ ਕਰੋੜ ਦੇ ਨੇੜੇ ਹੈ ।",
"shahmukhi": "لہور پاکستانی پنجاب دا دارالحکومت اے۔ لوک گنتی دے نال کراچی توں بعد لہور دوجا سبھ توں وڈا شہر اے۔ لہور پاکستان دا سیاسی، رہتلی تے پڑھائی دا گڑھ اے تے اس لئی ایھنوں پاکستان دا دل وی کیھا جاندا اے۔ لہور دریاۓ راوی دے کنڈھے تے وسدا اے اسدی لوک گنتی اک کروڑ دے نیڑے اے ۔",
"tranliteration": "lahor pākistān panjāb dā dārul hakūmat ē. lōk giṇtī dē nāḷ karācī tō᷈ bāad lahor dūjā sab tō᷈ vaḍḍā shahr ē. lahor pākistān dā siāsī, rahtalī tē paṛā̀ī dā gā́ṛ ē tē is laī ihnū᷈ pākistān dā dil vī kehā jāndā ē. lahor dariāē rāvī dē kanḍē tē vasdā ē. isdī lōk giṇtī ikk karōṛ dē nēṛē ē."
},
"employees": {
"wc": [
"෴ - 0xdf4 - 1",
"ණ - 0xdab - 1",
"් - 0xdca - 0",
"ණ - 0xdab - 1",
"្ - 0x17d2 - 0",
"෴ - 0xdf4 - 1",
"1 - 0x31 - 1",
"͏ - 0x34f - 0",
"2 - 0x32 - 1",
"⃝ - 0x20dd - 0"
],
"fancy": "1͏2⃝",
"v1": "γιγνώσκειν",
"v2": "ὦ ἄνδρες ᾿Αθηναῖοι",
"v1": "ახლავე გაიაროთ რეგისტრაცია",
"v2": "Unicode-ის მეათე საერთაშორისო",
"width": 55,
"sinhala": "෴ණ්ණ෴",
"width": 4,
"sinhala": "෴",
"width": 1,
"sinhala": "෴ණ්ණ෴෴ණ්ණ෴",
"width": 8,
"not_sinhala": "123456",
"tag": "ර්‍ඝ",
"width": 2,
"employee": [
{
"first_name": "Jim",
"nic_name": "\"რეგტ\"",
"last_name": "გთხოვთ ახ",
"department": 431,
"percent_time": 90,
"benefits": "full"
},
{
"first_name": "Terry",
"nic_name": "\"<one\"",
"last_name": "Οὐχὶ ταὐτὰ παρίσταταί μοι Jones",
"department": 660,
"percent_time": 90,
"benefits": "full"
},
{
"first_name": "Leslie",
"nic_name": "\"Les\"",
"last_name": "Patterson",
"department": 341,
"percent_time": 60,
"benefits": "full"
},
{
"first_name": "Ashley",
"nic_name": "\"Ash\"",
"last_name": "Meter & Smith",
"department": 1440,
"percent_time": 40
},
{
"first_name": "0123456789",
"nic_name": "\"0123456789\"",
"last_name": "012345678901234567890",
"department": 1440,
"percent_time": 40
},
{
"first_name": "ახლა",
"nic_name": "\"გაიარო\"",
"last_name": "საერთაშორისო",
"department": 123,
"percent_time": 90,
"benefits": "full"
},
{
"first_name": "෴ණ්ණ෴෴ණ්ණ෴",
"nic_name": "\"Mick\"",
"last_name": "෴ණ්ණ෴෴ණ්ණ෴෴ණ්ණ෴෴෴",
"department": 110,
"percent_time": 20
}
]
}
}

View File

@ -0,0 +1,21 @@
{
"employees": {
"employee": [
{
"first_name": "Terry",
"last_name": "Jones",
"department": 660
},
{
"first_name": "Leslie",
"last_name": "Patterson",
"department": 341
},
{
"first_name": "Ashley",
"last_name": "Smith",
"department": 1440
}
]
}
}

View File

@ -0,0 +1,71 @@
{
"employees": {
"test": [
{
"filename": "(null)"
}
],
"v1": "γιγνώσκειν",
"v2": "ὦ ἄνδρες ᾿Αθηναῖοι",
"columns": 28,
"columns": 2,
"v1": "ახლავე გაიაროთ რეგისტრაცია",
"v2": "Unicode-ის მეათე საერთაშორისო",
"columns": 55,
"columns": 0,
"employee": [
{
"first_name": "Jim",
"nic_name": "\"რეგტ\"",
"last_name": "გთხოვთ ახ",
"department": 431,
"percent_time": 90,
"columns": 23,
"benefits": "full"
},
{
"first_name": "Terry",
"nic_name": "\"<one\"",
"last_name": "Οὐχὶ ταὐτὰ παρίσταταί μοι Jones",
"department": 660,
"percent_time": 90,
"columns": 47,
"benefits": "full"
},
{
"first_name": "Leslie",
"nic_name": "\"Les\"",
"last_name": "Patterson",
"department": 341,
"percent_time": 60,
"columns": 25,
"benefits": "full"
},
{
"first_name": "Ashley",
"nic_name": "\"Ash\"",
"last_name": "Meter & Smith",
"department": 1440,
"percent_time": 40,
"columns": 30
},
{
"first_name": "0123456789",
"nic_name": "\"0123456789\"",
"last_name": "012345678901234567890",
"department": 1440,
"percent_time": 40,
"columns": 49
},
{
"first_name": "ახლა",
"nic_name": "\"გაიარო\"",
"last_name": "საერთაშორისო",
"department": 123,
"percent_time": 90,
"columns": 29,
"benefits": "full"
}
]
}
}

View File

@ -0,0 +1,18 @@
test: close (xo_close_container) fails at marker 'm1'; not found 'data3'
test: close (xo_close_container) fails at marker 'm2'; not found 'data4'
test: close (xo_close_container) fails at marker 'm2'; not found 'data4'
test: close (xo_close_container) fails at marker 'm2'; not found 'data4'
test: close (xo_close_container) fails at marker 'm2'; not found 'data4'
test: close (xo_close_container) fails at marker 'm2'; not found 'data4'
test: close (xo_close_container) fails at marker 'm2'; not found 'data4'
test: close (xo_close_container) fails at marker 'm2'; not found 'data4'
test: close (xo_close_container) fails at marker 'm2'; not found 'data4'
test: close (xo_close_container) fails at marker 'm2'; not found 'data4'
test: close (xo_close_container) fails at marker 'm2'; not found 'data4'
test: close (xo_close_container) fails at marker 'm2'; not found 'data4'
test: close (xo_close_container) fails at marker 'm2'; not found 'data4'
test: close (xo_close_container) fails at marker 'm2'; not found 'data4'
test: close (xo_close_container) fails at marker 'm2'; not found 'data4'
test: close (xo_close_container) fails at marker 'm2'; not found 'data4'
test: close (xo_close_container) fails at marker 'm1'; not found 'data4'
test: close (xo_close_container) fails at marker 'm1'; not found 'top'

View File

@ -0,0 +1,185 @@
{
"top": {
"data": {
"contents": {
"item": [
{
"name": "gum",
"count": 1412
},
{
"name": "rope",
"count": 85
},
{
"name": "ladder",
"count": 0
},
{
"name": "bolt",
"count": 4123
},
{
"name": "water",
"count": 17
}
]
}
},
"data2": {
"contents": {
"item": [
{
"name": "gum",
"count": 1412
},
{
"name": "rope",
"count": 85
},
{
"name": "ladder",
"count": 0
},
{
"name": "bolt",
"count": 4123
},
{
"name": "water",
"count": 17
}
]
}
},
"data3": {
"contents": {
"item": [
{
"name": "gum",
"count": 1412
},
{
"name": "rope",
"count": 85
},
{
"name": "ladder",
"count": 0
},
{
"name": "bolt",
"count": 4123
},
{
"name": "water",
"count": 17,
"test": "one"
}
]
}
},
"data4": {
"contents": {
"item": [
{
"name": "gum",
"count": 1412,
"sub": [
{
"name": 0,
"next": 1
},
{
"name": 1,
"next": 2
},
{
"name": 2,
"next": 3
}
],
"last": 3
},
{
"name": "rope",
"count": 85,
"sub": [
{
"name": 0,
"next": 1
},
{
"name": 1,
"next": 2
},
{
"name": 2,
"next": 3
}
],
"last": 3
},
{
"name": "ladder",
"count": 0,
"sub": [
{
"name": 0,
"next": 1
},
{
"name": 1,
"next": 2
},
{
"name": 2,
"next": 3
}
],
"last": 3
},
{
"name": "bolt",
"count": 4123,
"sub": [
{
"name": 0,
"next": 1
},
{
"name": 1,
"next": 2
},
{
"name": 2,
"next": 3
}
],
"last": 3
},
{
"name": "water",
"count": 17,
"sub": [
{
"name": 0,
"next": 1
},
{
"name": 1,
"next": 2
},
{
"name": 2,
"next": 3
}
],
"last": 3,
"test": "one"
}
]
}
}
}
}

View File

@ -0,0 +1,39 @@
{
"top": {
"data": {
"contents": {
"name": [
"gum",
"rope",
"ladder",
"bolt",
"water"
]
},
"contents": {
"item": [
"gum",
"rope",
"ladder",
"bolt",
"water"
]
},
"contents": {
"item": [
"gum",
"rope",
"ladder",
"bolt",
"water"
],
"total": "six",
"one": "one",
"two": [
"two"
],
"three": "three"
}
}
}
}

View File

@ -0,0 +1,113 @@
{
"__version": "3.1.4",
"top": {
"data": {
"item": [
],
"data": "bold",
"data": "bold-ul",
"data": "triple",
"data": "inv-ul",
"data": "underline",
"data": "plain",
"item": [
{
"sku": "GRO-000-415",
"name": "gum",
"sold": 1412,
"in_stock": 54,
"on_order": 10
},
{
"sku": "HRD-000-212",
"name": "rope",
"sold": 85,
"in_stock": 4,
"on_order": 2
},
{
"sku": "HRD-000-517",
"name": "ladder",
"sold": 0,
"in_stock": 2,
"on_order": 1
},
{
"sku": "HRD-000-632",
"name": "bolt",
"sold": 4123,
"in_stock": 144,
"on_order": 42
},
{
"sku": "GRO-000-2331",
"name": "water",
"sold": 17,
"in_stock": 14,
"on_order": 2
}
]
},
"data": {
"item": [
{
"sku": "GRO-000-415",
"name": "gum",
"sold": 1412.0,
"in_stock": 54,
"on_order": 10
},
{
"sku": "HRD-000-212",
"name": "rope",
"sold": 85.0,
"in_stock": 4,
"on_order": 2
},
{
"sku": "HRD-000-517",
"name": "ladder",
"sold": 0,
"in_stock": 2,
"on_order": 1
},
{
"sku": "HRD-000-632",
"name": "bolt",
"sold": 4123.0,
"in_stock": 144,
"on_order": 42
},
{
"sku": "GRO-000-2331",
"name": "water",
"sold": 17.0,
"in_stock": 14,
"on_order": 2
}
]
},
"data": {
"item": [
{
"sku": "GRO-000-533",
"name": "fish",
"sold": 1321.0,
"in_stock": 45,
"on_order": 1
}
]
},
"data": {
"item": [
"gum",
"rope",
"ladder",
"bolt",
"water"
]
},
"cost": 425,
"cost": 455
}
}

View File

@ -0,0 +1,22 @@
{{<14>1 2015-06-23T13:47:09.123-0500 worker-host test-program 222 animal-status [animal-status@42 animal="snake" state="loose"] The snake is loose}}
{{test-program: }}
{{The snake is loose}}
{{<22>1 2015-06-23T13:47:09.123-0500 worker-host test-program 222 animal-consumed [animal-consumed@42 animal="snake" pet="hamster"] My snake ate your hamster}}
{{test-program: }}
{{My snake ate your hamster}}
{{<29>1 2015-06-23T13:47:09.123-0500 worker-host test-program 222 animal-talk [animal-talk@42 count="1" animal="owl" quote="\"e=m\\c[2\]\""] 1 owl said "e=m\c[2]"}}
{{test-program: }}
{{1 owl said "e=m\c[2]"}}
{{<165>1 2015-06-23T13:47:09.123-0500 worker-host test-program 222 ID47 [ID47@32473 iut="3" event-source="application" event-id="1011"] An application 1011 log entry}}
{{test-program: }}
{{An application 1011 log entry}}
{
"__version": "3.1.4",
"top": {
}
}

View File

@ -0,0 +1,4 @@
test_12: invalid XML tag name: '2by4'
test_12: invalid XML tag name: '4x4'
test_12: invalid XML tag name: '2morrow'
test_12: invalid XML tag name: '2by4'

View File

@ -0,0 +1,94 @@
{
"top": {
"data": {
"animal": "fish",
"animal": "fish",
"thing": [
{
"name": "thing",
"color": "green",
"time": "2:15",
"hand": "left",
"color": "blue",
"time": "3:45"
},
{
"name": "thing",
"color": "green",
"time": "2:15",
"hand": "left",
"color": "blue",
"time": "3:45"
},
{
"name": "thing",
"color": "green",
"time": "2:15",
"hand": "left",
"color": "blue",
"time": "3:45"
},
{
"name": "thing",
"color": "green",
"time": "2:15",
"hand": "left",
"color": "blue",
"time": "3:45"
},
{
"name": "thing",
"color": "green",
"time": "2:15",
"hand": "left",
"color": "blue",
"time": "3:45"
},
{
"name": "thing",
"color": "green",
"time": "2:15",
"hand": "left",
"color": "blue",
"time": "3:45"
},
{
"name": "thing",
"color": "green",
"time": "2:15",
"hand": "left",
"color": "blue",
"time": "3:45"
},
{
"name": "thing",
"color": "green",
"time": "2:15",
"hand": "left",
"color": "blue",
"time": "3:45"
},
{
"name": "thing",
"color": "green",
"time": "2:15",
"hand": "left",
"color": "blue",
"time": "3:45"
},
{
"name": "thing",
"color": "green",
"time": "2:15",
"hand": "left",
"color": "blue",
"time": "3:45",
"2by4": {
"4x4": "truck",
"2morrow": "tomorrow"
}
}
]
}
}
}

View File

@ -82,7 +82,7 @@ main (int argc, char **argv)
xo_set_info(NULL, info, -1);
xo_set_flags(NULL, XOF_KEYS);
xo_open_container_h(NULL, "top");
xo_open_container_h(NULL, "top-level");
xo_emit("static {:type/ethernet} {:type/bridge} {:type/%4du} {:type/%3d}",
18, 24);
@ -104,10 +104,17 @@ main (int argc, char **argv)
xo_emit("{La:} {a:}\n", "Label text", "label", "value");
const char *title = "My Title";
xo_emit_field("T", title, "%s\n", NULL, NULL);
xo_emit_field("Vt", "max-chaos", NULL, NULL, " very ");
xo_emit_field("V", "min-chaos", "%d", NULL, 42);
xo_emit_field("V", "some-chaos", "%d\n", "[%d]", 42);
xo_attr("test-attr", "attr-value");
xo_emit_field_h(NULL, ",leaf-list,quotes", "sku", "%s-%u", "%s-000-%u",
"gum", 1412);
xo_emit("Connecting to {:host}.{:domain}...\n", "my-box", "example.com");
xo_attr("test", "value");
@ -248,7 +255,7 @@ main (int argc, char **argv)
"/some/file", (int) 0640, 8, 1,
10, "user", 12, "group");
xo_close_container_h(NULL, "top");
xo_close_container_h(NULL, "top-level");
xo_finish();

View File

@ -85,6 +85,8 @@ main (int argc, char **argv)
for (i = 0; i < 5; i++)
xo_emit("{lw:bytes/%d}{Np:byte,bytes}\n", i);
xo_emit("{Lc:Low\\/warn granularity}{P:\t}{:granularity-lw/%d}{Uw:/%sh}\n",
155, "mA");
xo_emit("{:mbuf-current/%u}/{:mbuf-cache/%u}/{:mbuf-total/%u} "
"{N:mbufs <&> in use (current\\/cache\\/total)}\n",

View File

@ -115,11 +115,11 @@ main (int argc, char **argv)
ip->i_title, ip->i_count);
}
xo_close_container("data3"); /* Should be a noop */
xo_close_container("data3"); /* warn: fails at marker 'm1' */
xo_emit("{:test}", "one");
xo_close_marker("m1");
xo_close_container("data3"); /* Should be a noop */
xo_close_container("data3"); /* this one works, post-marker */
xo_emit("\n\n");
@ -139,13 +139,13 @@ main (int argc, char **argv)
for (i = 0; i < 3; i++) {
xo_open_instance("sub");
xo_emit("{Lwc:/Name}{:name/%d} + 1 = {:next/%d}\n", i, i + 1);
xo_close_container("data4");
xo_close_container("data4"); /* warn: fails at marker 'm2' */
}
xo_close_marker("m2");
xo_emit("{Lwc:/Last}{:last/%d}\n", i);
}
xo_close_container("data4"); /* Should be a noop */
xo_close_container("data4"); /* warn: fails at marker 'm1' */
xo_emit("{:test}", "one");
xo_emit("\n\n");

0
contrib/libxo/tests/xo/xo_01.sh Executable file → Normal file
View File

0
contrib/libxo/tests/xo/xo_02.sh Executable file → Normal file
View File

View File

@ -179,7 +179,7 @@ prepend data to the XPath values used for HTML output style.
.Bd -literal -offset indent
#!/bin/sh
xo --open top/data
xo --depth 2 '{tag}' value
xo --depth 2 '{:tag}' value
xo --close top/data
.Pp
XML:

0
contrib/libxo/xolint/xolint.pl Executable file → Normal file
View File