/** * Writes to @p stream an XML version of the @p ks object. * * String generated is of the form: * @verbatim <keyset> <key name=...>...</key> <key name=...>...</key> <key name=...>...</key> </keyset> * @endverbatim * * or if KDB_O_HIER is used, the form will be: * @verbatim <keyset parent="user/smallest/parent/name"> <key basename=...>...</key> <key name=...>...</key> <!-- a key thats not under this keyset's parent --> <key basename=...>...</key> </keyset> * @endverbatim * * KDB_O_HEADER will additionally generate a header like: * @verbatim <?xml version="1.0" encoding="UTF-8"?> <!-- Generated by Elektra API. Total of n keys. --> <keyset xmlns="http://www.libelektra.org" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.libelektra.org elektra.xsd"> * @endverbatim * * @param ks the KeySet to serialise * @param stream where to write output: a file or stdout * @param options accepted #option_t ORed: * - @p option_t::KDB_O_NUMBERS \n * Do not convert UID and GID into user and group names. * - @p option_t::KDB_O_FULLNAME \n * The @c user keys are exported with their full names (including * user domains) * - @p option_t::KDB_O_CONDENSED \n * Less human readable, more condensed output. * - @p option_t::KDB_O_XMLHEADERS \n * Exclude the correct XML headers in the output. If not used, the * <?xml?> and schema info inside the <keyset> object will not be generated. * - @p option_t::KDB_O_HIER \n * Will generate a <keyset> node containing a @c parent attribute, and * <key> nodes with a @c basename relative to that @c parent. The @c parent * is calculated by taking the smallest key name in the keyset, so it is a * good idea to have only related keys on the keyset. Otherwise, a valid * consistent XML document still will be generated with regular absolute * @c name attribute for the <key> nodes, due to a * clever keyToStreamBasename() implementation. * * @see keyToStream() * @see commandList() for usage example * @return number of bytes written to output, or -1 if some error occurs * @param ks The keyset to output * @param stream the file pointer where to send the stream * @param options see above text */ ssize_t ksToStream(const KeySet *ks, FILE* stream, option_t options) { size_t written=0; Key *key=0; char *codeset = "UTF-8"; KeySet *cks = ksDup (ks); ksRewind (cks); if (options & KDB_O_HEADER) { written+=fprintf(stream,"<?xml version=\"1.0\" encoding=\"%s\"?>", codeset); if (~options & KDB_O_CONDENSED) written+=fprintf(stream, "\n<!-- Generated by Elektra API. Total of %d keys. -->\n",(int)cks->size); if (~options & KDB_O_CONDENSED) written+=fprintf(stream,"<keyset xmlns=\"http://www.libelektra.org\"\n" "\txmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n" "\txsi:schemaLocation=\"http://www.libelektra.org elektra.xsd\"\n"); else written+=fprintf(stream,"<keyset xmlns=\"http://www.libelektra.org\"" " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"" " xsi:schemaLocation=\"http://www.libelektra.org elektra.xsd\""); } else written+=fprintf(stream,"<keyset"); if (options & KDB_O_HIER) { char commonParent[KDB_MAX_PATH_LENGTH]; ksGetCommonParentName(cks,commonParent,sizeof(commonParent)); if (commonParent[0]) { written+=fprintf(stream," parent=\"%s\">\n", commonParent); ksRewind (cks); while ((key=ksNext (cks)) != 0) written+=keyToStreamBasename(key,stream,commonParent,0,options); } else { written+=fprintf(stream,">\n"); ksRewind (cks); while ((key=ksNext (cks)) != 0) written+=keyToStream(key,stream,options); } } else { /* No KDB_O_HIER*/ written+=fprintf(stream,">\n"); ksRewind (cks); while ((key=ksNext (cks)) != 0) written+=keyToStream(key,stream,options); } written+=fprintf(stream,"</keyset>\n"); ksDel (cks); return written; }
static void test_ksCommonParentName() { char ret [MAX_SIZE+1]; KeySet *ks = ksNew (10, keyNew("system/sw/xorg/Monitors/Monitor1/vrefresh",0), keyNew("system/sw/xorg/Monitors/Monitor1/hrefresh",0), keyNew("system/sw/xorg/Monitors/Monitor2/vrefresh",0), keyNew("system/sw/xorg/Monitors/Monitor2/hrefresh",0), keyNew("system/sw/xorg/Devices/Device1/driver",0), keyNew("system/sw/xorg/Devices/Device1/mode",0),KS_END); printf ("Test common parentname\n"); succeed_if (ksGetCommonParentName(ks, ret, MAX_SIZE) > 0, "could not find correct parentname"); succeed_if_same_string (ret, "system/sw/xorg"); ksDel (ks); ks = ksNew (10, keyNew("system",0), keyNew("user",0),KS_END); succeed_if (ksGetCommonParentName(ks, ret, MAX_SIZE) == 0, "could find correct parentname"); succeed_if_same_string (ret, ""); ksDel (ks); ks = ksNew (10, keyNew("system/some/thing",0), keyNew("system/other/thing",0), KS_END); succeed_if (ksGetCommonParentName(ks, ret, MAX_SIZE) == 7, "could find correct parentname"); succeed_if_same_string (ret, "system"); ksDel (ks); ks = ksNew (10, keyNew("system/here/in/deep/goes/ok/thing",0), keyNew("system/here/in/deep/goes/ok/other/thing",0), KS_END); succeed_if (ksGetCommonParentName(ks, ret, MAX_SIZE) > 0, "could find correct parentname"); succeed_if_same_string (ret, "system/here/in/deep/goes/ok"); ksDel (ks); ks = ksNew (10, keyNew("system/here/in/deep/goes/ok/thing",0), keyNew("system/here/in/deep/goes/ok/other/thing",0), keyNew("user/unique/thing",0),KS_END); succeed_if (ksGetCommonParentName(ks, ret, MAX_SIZE) == 0, "could find correct parentname"); succeed_if_same_string (ret, ""); ksDel (ks); ks = ksNew (10, keyNew("user/unique/thing",0),KS_END); succeed_if (ksGetCommonParentName(ks, ret, MAX_SIZE) > 0, "could find correct parentname"); succeed_if_same_string (ret, "user/unique/thing"); ksDel (ks); }