简体   繁体   English

为什么这个 XML 验证通过 XSD 在 libxml2 中失败(但在 xmllint 中成功),我该如何解决?

[英]Why does this XML validation via XSD fail in libxml2 (but succeed in xmllint) and how do I fix it?

If I run this XML validation via xmllint:如果我通过 xmllint 运行这个XML 验证

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:但是,如果我通过libxml2 的 C API运行相同的验证

int result = xmlSchemaValidateDoc(...)

I get a return value of 1845 and this failure message:我得到一个返回值1845和这个失败消息:

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:架构.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:

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

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

main.c: 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:控制台 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以防万一:我在OSX 10.6.7上使用默认libxml2.dylib
(/Developer/SDKs/MacOSX10.6.sdk/usr/lib/libxml2.2.7.3.dylib) (/Developer/SDKs/MacOSX10.6.sdk/usr/lib/libxml2.2.7.3.dylib)

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 .在获得有关gnome 项目的 xml 邮件列表的帮助后,似乎我的错误不是由我的错误引起的而是由 OSX 10.6.x 的 libxml2 分发 (v2.7.3) 的错误引起的
(as in: same code works for others, yet fails for me OSX' legacy distribution) (如:相同的代码适用于其他人,但对我来说 OSX 的旧版发行版却失败了)

I checked the libxml2 release notes and found two candidates:我检查了 libxml2 发行说明,发现了两个候选者:

Release notes of Update 2.7.4 list the following bug fix:更新 2.7.4 的发行说明列出了以下错误修复:

  • "579746 XSD validation not correct / nilable groups (Daniel Veillard)" “579746 XSD 验证不正确/可空组 (Daniel Veillard)”

Release notes of Update 2.7.8 list the following bug fix:更新 2.7.8 的发行说明列出了以下错误修复:

  • "Fix errors in XSD double validation check (Csaba Raduly)" “修复 XSD 双重验证检查中的错误 (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.不过,还没有成功让 libxml2 的最新版本(v2.7.8)与我的项目(或者更确切地说是 Xcode)一起工作。

I tried your content and code on Ubuntu Linux.我在 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: Output:

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

XML Source: XML 来源:

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

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

Validation successful: YES (result: 0)验证成功:YES(结果:0)

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.您的架构将元素 foo 放入 targetNamespace (这就是 elementdefault="qualified" 的意思),但您的实例文档没有声明该名称空间或任何其他名称空间。 So the foos don't actually match.所以 foos 实际上并不匹配。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM