LIBXO(3)

πŸ“¦ version 15.1, in freebsd 14.5, freebsd 15.1

πŸ’… LIBXO(3) β€” the manual page, bestie edition ✨

ok so this is LIBXO(3) from the Library Functions Manual and it's genuinely so important, like the way these functions keep your XML and JSON from going absolutely feral? obsessed. let's get into it 🫢


🌸 NAME 🌸

xo_open_list, xo_open_list_h, xo_open_list_hd, xo_open_list_d, xo_open_instance, xo_open_instance_h, xo_open_instance_hd, xo_open_instance_d, xo_close_instance, xo_close_instance_h, xo_close_instance_hd, xo_close_instance_d, xo_close_list, xo_close_list_h, xo_close_list_hd, xo_close_list_d β€” open and close lists and instances πŸ’–

like literally all of them. the whole girl group. periodt.

πŸ“š LIBRARY πŸ“š

library β€œlibxo” β€” that's the one, that's the icon πŸ’…

✨ SYNOPSIS ✨

ok copy these EXACTLY, no cap, character for character:

#include <libxo/xo.h>

xo_ssize_t
xo_open_list_h(xo_handle_t *xop, const char *name);

xo_ssize_t
xo_open_list(const char *name);

xo_ssize_t
xo_open_list_hd(xo_handle_t *xop, const char *name);

xo_ssize_t
xo_open_list_d(const char *name);

xo_ssize_t
xo_open_instance_h(xo_handle_t *xop, const char *name);

xo_ssize_t
xo_open_instance(const char *name);

xo_ssize_t
xo_open_instance_hd(xo_handle_t *xop, const char *name);

xo_ssize_t
xo_open_instance_d(const char *name);

xo_ssize_t
xo_close_instance_h(xo_handle_t *xop, const char *name);

xo_ssize_t
xo_close_instance(const char *name);

xo_ssize_t
xo_close_instance_hd(xo_handle_t *xop);

xo_ssize_t
xo_close_instance_d(void);

xo_ssize_t
xo_close_list_h(xo_handle_t *xop, const char *name);

xo_ssize_t
xo_close_list(const char *name);

xo_ssize_t
xo_close_list_hd(xo_handle_t *xop);

xo_ssize_t
xo_close_list_d(void);

look at that. gorgeous. no notes. πŸŽ€

πŸ¦‹ DESCRIPTION πŸ¦‹

okay so picture this: lists are sequences of instances of homogeneous data objects. that's the vibe. and to represent them in the output styles, you need two distinct levels of calls β€” like two separate outfit changes, both necessary. you gotta open and close the list, and then for each instance of data in that list, you gotta make calls to open and close that instance. πŸ’ƒ

⚠️ tiny but crucial: the name you give to all the calls must be identical. and it is strongly suggested (like, do it) that the name be singular, not plural β€” that's a style and usage-expectations thing, iykyk.

a list is a set of one or more instances that appear under the same parent. the instances contain details about a specific object. you can lowkey think of instances as objects or records. one call opens and closes the list, and a distinct call opens and closes each instance of the list:

xo_open_list("item");

for (ip = list; ip->i_title; ip++) {
    xo_open_instance("item");
    xo_emit("{L:Item} '{:name/%s}':\n", ip->i_title);
    xo_close_instance("item");
}

xo_close_list("item");

getting the list and instance calls correct is critical β€” not optional, not a suggestion, like genuinely make-or-break β€” for the proper generation of XML and JSON data. πŸ”₯

EXAMPLE:
    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",
                pw[i].pw_name, pw[i].pw_uid,
                pw[i].pw_gid, pw[i].pw_dir);
        xo_close_instance("user");
    }
    xo_close_list("user");
TEXT:
    phil:1001:1001:/home/phil
    pallavi:1002:1002:/home/pallavi
XML:
    <user>
        <name>phil</name>
        <uid>1001</uid>
        <gid>1001</gid>
        <home>/home/phil</home>
    </user>
    <user>
        <name>pallavi</name>
        <uid>1002</uid>
        <gid>1002</gid>
        <home>/home/pallavi</home>
    </user>
JSON:
    user: [
        {
            "name": "phil",
            "uid": 1001,
            "gid": 1001,
            "home": "/home/phil",
        },
        {
            "name": "pallavi",
            "uid": 1002,
            "gid": 1002,
            "home": "/home/pallavi",
        }
    ]

ate. no crumbs. πŸ’€βœ¨


πŸ“ LEAF LISTS πŸ“

so in contrast to a list of instances, a leaf list is a list of simple values. cute, minimal, main character energy. to emit a leaf list, you call the xo_emit() function using the "l" modifier:

for (ip = list; ip->i_title; ip++) {
    xo_emit("{Lwc:Item}{l:item}\n", ip->i_title);
}
πŸ’‘ the name of the field must match the name of the leaf list. like, they have to be twins. no mismatches.

in JSON, leaf lists are rendered as arrays of values. in XML, they're rendered as multiple leaf elements:

JSON:
    "item": "hammer", "nail"
XML:
    <item>hammer</item>
    <item>nail</item>

slay πŸ’…


πŸ‘€ SEE ALSO πŸ‘€

go read those too, bestie, they're iconic 🌈

⭐ HISTORY ⭐

the libxo library first appeared in FreeBSD 11.0. a legend was born πŸŽ€

πŸ‘‘ AUTHORS πŸ‘‘

libxo was written by Phil Shafer <phil@freebsd.org>. king behavior, honestly 🫢


and that's the whole page, bestie β€” certified Debian release, dated December 4, 2014, filed under LIBXO(3) πŸ’œ go forth and close your lists correctly, i'm begging you 😭

πŸ“¦ where this page comes from