14

If I run this XML validation via xmllint:

xmllint --noout --schema schema.xsd test.xml

I get this success message:

.../test.xml validates

However if I run the same validation via libxml2's C API:

int result = xmlSchemaValidateDoc(...)

I get a return value of 1845 and this failure message:

Element '{http://example.com/XMLSchema/1.0}foo': No matching global declaration available for the validation root.

Which I can make absolutely no sense of. :(


schema.xsd:

<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE xs:schema PUBLIC "-//W3C//DTD XMLSCHEMA 200102//EN" "XMLSchema.dtd" >
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns="http://example.com/XMLSchema/1.0" targetNamespace="http://example.com/XMLSchema/1.0" elementFormDefault="qualified" attributeFormDefault="unqualified">

    <xs:element name="foo">
    </xs:element>
</xs:schema>

test.xml:

<?xml version="1.0" encoding="UTF-8"?>

<foo xmlns="http://example.com/XMLSchema/1.0">
</foo>

main.c:

#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <string.h>

#include <libxml/parser.h>
#include <libxml/valid.h>
#include <libxml/xmlschemas.h>

u_int32_t get_file_size(const char *file_name) {
    struct stat buf;
    if ( stat(file_name, &buf) != 0 ) return(0);
    return (unsigned int)buf.st_size;
}

void handleValidationError(void *ctx, const char *format, ...) {
    char *errMsg;
    va_list args;
    va_start(args, format);
    vasprintf(&errMsg, format, args);
    va_end(args);
    fprintf(stderr, "Validation Error: %s", errMsg);
    free(errMsg);
}

int main (int argc, const char * argv[]) {
    const char *xsdPath = argv[1];
    const char *xmlPath = argv[2];

    printf("\n");

    printf("XSD File: %s\n", xsdPath);
    printf("XML File: %s\n", xmlPath);

    int xmlLength = get_file_size(xmlPath);
    char *xmlSource = (char *)malloc(sizeof(char) * xmlLength);

    FILE *p = fopen(xmlPath, "r");
    char c;
    unsigned int i = 0;
    while ((c = fgetc(p)) != EOF) {
        xmlSource[i++] = c;
    }
    printf("\n");

    printf("XML Source:\n\n%s\n", xmlSource);
    fclose(p);

    printf("\n");

    int result = 42;
    xmlSchemaParserCtxtPtr parserCtxt = NULL;
    xmlSchemaPtr schema = NULL;
    xmlSchemaValidCtxtPtr validCtxt = NULL;

    xmlDocPtr xmlDocumentPointer = xmlParseMemory(xmlSource, xmlLength);
    parserCtxt = xmlSchemaNewParserCtxt(xsdPath);

    if (parserCtxt == NULL) {
        fprintf(stderr, "Could not create XSD schema parsing context.\n");
        goto leave;
    }

    schema = xmlSchemaParse(parserCtxt);

    if (schema == NULL) {
        fprintf(stderr, "Could not parse XSD schema.\n");
        goto leave;
    }

    validCtxt = xmlSchemaNewValidCtxt(schema);

    if (!validCtxt) {
        fprintf(stderr, "Could not create XSD schema validation context.\n");
        goto leave;
    }

    xmlSetStructuredErrorFunc(NULL, NULL);
    xmlSetGenericErrorFunc(NULL, handleValidationError);
    xmlThrDefSetStructuredErrorFunc(NULL, NULL);
    xmlThrDefSetGenericErrorFunc(NULL, handleValidationError);

    result = xmlSchemaValidateDoc(validCtxt, xmlDocumentPointer);

leave:

    if (parserCtxt) {
        xmlSchemaFreeParserCtxt(parserCtxt);
    }

    if (schema) {
        xmlSchemaFree(schema);
    }

    if (validCtxt) {
        xmlSchemaFreeValidCtxt(validCtxt);
    }
    printf("\n");
    printf("Validation successful: %s (result: %d)\n", (result == 0) ? "YES" : "NO", result);

    return 0;
}

console output:

XSD File: /Users/dephiniteloop/Desktop/xml_validate/schema.xsd
XML File: /Users/dephiniteloop/Desktop/xml_validate/test.gkml

XML Source:

<?xml version="1.0" encoding="UTF-8"?>

<foo xmlns="http://example.com/XMLSchema/1.0">
</foo>

Validation Error: Element '{http://example.com/XMLSchema/1.0}foo': No matching global declaration available for the validation root.

Validation successful: NO (result: 1845)

In case it matters: I'm on OSX 10.6.7 with its default libxml2.dylib
(/Developer/SDKs/MacOSX10.6.sdk/usr/lib/libxml2.2.7.3.dylib)

mtree
  • 617
  • 2
  • 6
  • 18
  • 1
    Are you sure you're providing the schema to libxml2? You left out the critical part of the invocation in your code sample. – Jim Garrison Jun 08 '11 at 20:41
  • @JimGarrison Well, if I introduce a typo or wrong semantic to my xsd schema, then `xmlSchemaParse(…)` fails and I get an appropriate error message (e.g. "The attribute 'use' is not allowed"). Same goes for adding syntax errors to my xml file. Throws appropriate errors. So I suppose, yes I do. I however cannot get this particular error to go away, even though from my point of view it makes absolutely no sense whatsoever. *sigh* – mtree Jun 08 '11 at 22:10
  • @jim-garrison: I added the straight forward C code that I'm using along with the one console output it produces for me, every single time I run it. – mtree Jun 09 '11 at 10:25

3 Answers3

8

After getting some help on the gnome project's xml mailing-list it appears as if my error is not caused by a bug of mine, but rather by a bug of OSX 10.6.x's distribution (v2.7.3) of libxml2.
(as in: same code works for others, yet fails for me OSX' legacy distribution)

I checked the libxml2 release notes and found two candidates:

Release notes of Update 2.7.4 list the following bug fix:

  • "579746 XSD validation not correct / nilable groups (Daniel Veillard)"

Release notes of Update 2.7.8 list the following bug fix:

  • "Fix errors in XSD double validation check (Csaba Raduly)"

Haven't yet had success getting the latest build (v2.7.8) of libxml2 to work with my project (or rather Xcode in general) though.

mtree
  • 617
  • 2
  • 6
  • 18
4

I tried your content and code on Ubuntu Linux. Worked without any objection.

Build command:

gcc -Wall -I/usr/include/libxml2 main.c -lxml2 -o xmlvalid 

Run command:

./xmlvalid ./schema.xsd ./test.xml

Output:

XSD File: ./schema.xsd
XML File: ./test.xml

XML Source:

<?xml version="1.0" encoding="UTF-8"?>

<foo xmlns="http://example.com/XMLSchema/1.0">
</foo>

Validation successful: YES (result: 0)

Aamir Rind
  • 38,793
  • 23
  • 126
  • 164
jsa
  • 369
  • 2
  • 7
1

Your schema puts the element foo into the targetNamespace (that's what elementdefault="qualified" means), but your instance document doesn't declare that namespace or any other. So the foos don't actually match.

John Cowan
  • 1,497
  • 12
  • 13
  • Would you mind posting a snippet of what I have to change and to what? The XML/XSD/XMLNS terminology is still rather new to me. Would be much appreciated. :) – mtree Jun 08 '11 at 22:16
  • Stackoverflow is very confusing because it allows questions to be changed after they have been answered: but the version of the instance document I see in front of me is indeed in a namespace. – Michael Kay Jun 08 '11 at 22:17
  • I certainly didn't change anything in the meanwhile. – mtree Jun 08 '11 at 22:24
  • cowan, @michael-kay: I added the straight forward C code that I'm using along with the one console output it produces for me, every single time I run it. – mtree Jun 09 '11 at 10:23