/* $Id: TestXmlsq.c $ */
/*
* Last updated:
* $Date: 2021-07-18 10:29 $
* $Version: 1.0.0 $
*/
/* Some tests using the diXmlsq C/C++ interface.
* Please report any bugs to <http://cryptosys.net/contact/>
*/
/******************************* LICENSE ***********************************
* Copyright (C) 2020-21 David Ireland, DI Management Services Pty Limited.
* All rights reserved. <https://di-mgt.com.au> <https://cryptosys.net>
* The code in this module is licensed under the terms of the MIT license,
* unless otherwise marked.
* For a copy, see <http://opensource.org/licenses/MIT>
****************************************************************************
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "diXmlsq.h"
/*
* Requires `xmlsq` to be installed on your system, available from <https://cryptosys.net/xmlsq/>.
* In particular that `diXmlsq.dll` is in your library path.
* You must link to `diXmlsq.lib`. In MSVC++ IDE, use
* Project > Properties > Linker > Input > Additional Dependencies and add the full path to `diXmlsq.lib`.
* E.g.
* Additional Dependencies = $(OutDir)diXmlsq.lib;%(AdditionalDependencies)
* Using command-line:
* CL TestXmlsq.c /link ..\Release\diXmlsq.lib
*
* Test files are in `xmlsq-testfiles.zip`.
*/
#ifdef NDEBUG
/* Make sure assertion testing is turned on */
#undef NDEBUG
#endif
#include <assert.h>
/* Print quoted string to stdout */
static void pr_quoted_str(const char *prefix, const char *s, const char * suffix)
{
if (prefix) printf("%s", prefix);
printf("'%s'", s);
if (suffix) printf("%s", suffix);
}
int main(void)
{
long n, i;
const char *xmlfile;
const char *query;
char sbuf[256];
char qbuf[128];
char *buf;
long nchars;
n = XMLSQ_Gen_Version();
printf("Version = %05ld\n", n);
xmlfile = "bookstore.xml";
printf("FILE: %s\n", xmlfile);
query = "/";
printf("Get the root element...\n");
printf("Query: %s\n", query);
nchars = XMLSQ_GetText(NULL, 0, xmlfile, query, 0);
assert(nchars >= 0);
buf = malloc(nchars + 1);
nchars = XMLSQ_GetText(buf, nchars, xmlfile, query, 0);
printf("%s\n", buf);
free(buf);
query = "(//title)[2]";
printf("Get text of the 2nd title element...\n");
printf("Query: %s\n", query);
nchars = XMLSQ_GetText(NULL, 0, xmlfile, query, 0);
assert(nchars >= 0);
buf = malloc(nchars + 1);
nchars = XMLSQ_GetText(buf, nchars, xmlfile, query, 0);
printf("%s\n", buf);
free(buf);
query = "//title";
printf("Get text of the 1st title element...\n");
printf("Query: %s\n", query);
nchars = XMLSQ_GetText(NULL, 0, xmlfile, query, 0);
assert(nchars >= 0);
buf = malloc(nchars + 1);
nchars = XMLSQ_GetText(buf, nchars, xmlfile, query, 0);
printf("%s\n", buf);
free(buf);
query = "//title";
printf("Full Xpath query...\n");
printf("Query: %s\n", query);
nchars = XMLSQ_FullQuery(NULL, 0, xmlfile, query, 0);
assert(nchars >= 0);
buf = malloc(nchars + 1);
nchars = XMLSQ_FullQuery(buf, nchars, xmlfile, query, 0);
printf("%s\n", buf);
free(buf);
query = "//title";
printf("Full Xpath query with `raw` option...\n");
printf("Query: %s\n", query);
nchars = XMLSQ_FullQuery(NULL, 0, xmlfile, query, XMLSQ_RAW);
assert(nchars >= 0);
buf = malloc(nchars + 1);
nchars = XMLSQ_FullQuery(buf, nchars, xmlfile, query, XMLSQ_RAW);
printf("%s\n", buf);
free(buf);
query = "(//title)[3]";
printf("Get text of the 3rd title element (UTF-8-encoded)...\n");
// To show properly in cmd type ``chcp 65001`` before calling.
printf("Query: %s\n", query);
nchars = XMLSQ_GetText(NULL, 0, xmlfile, query, 0);
assert(nchars >= 0);
buf = malloc(nchars + 1);
nchars = XMLSQ_GetText(buf, nchars, xmlfile, query, 0);
printf("%s\n", buf);
free(buf);
query = "(//title)[3]";
printf("Get text of the 3rd title element (asciified)...\n");
printf("Query: %s\n", query);
nchars = XMLSQ_GetText(NULL, 0, xmlfile, query, XMLSQ_ASCIIFY);
assert(nchars >= 0);
buf = malloc(nchars + 1);
nchars = XMLSQ_GetText(buf, nchars, xmlfile, query, XMLSQ_ASCIIFY);
printf("%s\n", buf);
free(buf);
query = "//book/title/@lang";
printf("Get text of `lang` attribute in first title element ...\n");
printf("Query: %s\n", query);
// Use fixed-length output buffer (!DANGER!)
nchars = XMLSQ_GetText(sbuf, sizeof(sbuf) - 1, xmlfile, query, 0);
assert(nchars >= 0);
printf("%s\n", sbuf);
query = "//book/title/@lang";
printf("Same query in full-query mode...\n");
printf("Query: %s\n", query);
// Use fixed-length output buffer (!DANGER!)
nchars = XMLSQ_FullQuery(sbuf, sizeof(sbuf) - 1, xmlfile, query, 0);
assert(nchars >= 0);
printf("%s\n", sbuf);
// USE COUNT TO ITERATE MATCHING ELEMENTS
query = "//title";
printf("Use the Count function to query each matching element in turn...\n");
printf("Query: %s\n", query);
n = XMLSQ_Count(xmlfile, query, 0);
printf("Count: %ld\n", n);
for (i = 1; i <= n; i++) { // NB one-based
// Compose query
sprintf(qbuf, "(//title)[%ld]", i);
printf(" Query: %s\n", qbuf);
// then use it
nchars = XMLSQ_GetText(sbuf, sizeof(sbuf) - 1, xmlfile, qbuf, XMLSQ_ASCIIFY);
assert(nchars >= 0);
printf(" %s\n", sbuf);
}
// HANDLE ERROR STRINGS
printf("\nTEST ERRORS...\n");
// Bad query
query = "///badquery";
printf("Query: %s\n", query);
nchars = XMLSQ_GetText(NULL, 0, xmlfile, query, 0);
assert(nchars < 0);
if (nchars < 0) {
// return -N => error string is of length N
nchars = -nchars;
// Allocate buffer to receive error message
buf = malloc(nchars + 1);
nchars = XMLSQ_GetText(buf, nchars, xmlfile, query, 0);
printf("%s\n", buf);
free(buf);
}
// Missing file
xmlfile = "missing.file";
query = "//a";
printf("FILE: %s\n", xmlfile);
nchars = XMLSQ_GetText(NULL, 0, xmlfile, query, 0);
assert(nchars < 0);
if (nchars < 0) {
// return -N => error string is of length N
nchars = -nchars;
// Allocate buffer to receive error message
buf = malloc(nchars + 1);
nchars = XMLSQ_GetText(buf, nchars, xmlfile, query, 0);
printf("%s\n", buf);
free(buf);
}
// Input not valid XML
xmlfile = "notxml.txt";
query = "//a";
printf("FILE: %s\n", xmlfile);
nchars = XMLSQ_GetText(NULL, 0, xmlfile, query, 0);
assert(nchars < 0);
if (nchars < 0) {
// return -N => error string is of length N
nchars = -nchars;
// Allocate buffer to receive error message
buf = malloc(nchars + 1);
nchars = XMLSQ_GetText(buf, nchars, xmlfile, query, 0);
printf("%s\n", buf);
free(buf);
}
// TEST EMPTY VALUES
printf("\nTESTING FOR EMPTY VALUES...\n");
xmlfile = "<a><b foo=''></b><c>test1</c><e/></a>"; // Pass XML as a string
printf("xml=%s\n", xmlfile);
query = "/";
printf("Query: %s\n", query);
nchars = XMLSQ_GetText(sbuf, sizeof(sbuf) - 1, xmlfile, query, 0);
assert(nchars >= 0);
printf("%s\n", sbuf);
printf("Get text of element b (empty, so add quote delimiters to see something)...\n");
query = "a/b";
printf("Query: %s\n", query);
nchars = XMLSQ_GetText(sbuf, sizeof(sbuf) - 1, xmlfile, query, 0);
assert(nchars >= 0);
pr_quoted_str("", sbuf, "\n");
printf("And empty attribute foo=\"\"...\n");
query = "//b/@foo";
printf("Query: %s\n", query);
nchars = XMLSQ_GetText(sbuf, sizeof(sbuf) - 1, xmlfile, query, 0);
assert(nchars >= 0);
pr_quoted_str("", sbuf, "\n");
printf("And empty element e...\n");
query = "//e";
printf("Query: %s\n", query);
nchars = XMLSQ_GetText(sbuf, sizeof(sbuf) - 1, xmlfile, query, 0);
assert(nchars >= 0);
pr_quoted_str("", sbuf, "\n");
printf("But we get the same result if the element is missing...\n");
query = "//notthere";
printf("Query: %s\n", query);
nchars = XMLSQ_GetText(sbuf, sizeof(sbuf) - 1, xmlfile, query, 0);
assert(nchars >= 0);
pr_quoted_str("", sbuf, "\n");
printf("To differentiate: use the Count function...\n");
query = "//e";
printf("Query: %s\n", query);
n = XMLSQ_Count(xmlfile, query, 0);
printf("Count=%ld\n", n);
assert(n > 0);
query = "//notthere";
printf("Query: %s\n", query);
n = XMLSQ_Count(xmlfile, query, 0);
printf("Count=%ld\n", n);
assert(n == 0);
return 0;
}