簡體   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?

如果我通過 xmllint 運行這個XML 驗證

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

我收到此成功消息:

.../test.xml validates

但是,如果我通過libxml2 的 C API運行相同的驗證

int result = xmlSchemaValidateDoc(...)

我得到一個返回值1845和這個失敗消息:

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

我完全無法理解。 :(


架構.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>

測試.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;
}

控制台 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)

以防萬一:我在OSX 10.6.7上使用默認libxml2.dylib
(/Developer/SDKs/MacOSX10.6.sdk/usr/lib/libxml2.2.7.3.dylib)

在獲得有關gnome 項目的 xml 郵件列表的幫助后,似乎我的錯誤不是由我的錯誤引起的而是由 OSX 10.6.x 的 libxml2 分發 (v2.7.3) 的錯誤引起的
(如:相同的代碼適用於其他人,但對我來說 OSX 的舊版發行版卻失敗了)

我檢查了 libxml2 發行說明,發現了兩個候選者:

更新 2.7.4 的發行說明列出了以下錯誤修復:

  • “579746 XSD 驗證不正確/可空組 (Daniel Veillard)”

更新 2.7.8 的發行說明列出了以下錯誤修復:

  • “修復 XSD 雙重驗證檢查中的錯誤 (Csaba Raduly)”

不過,還沒有成功讓 libxml2 的最新版本(v2.7.8)與我的項目(或者更確切地說是 Xcode)一起工作。

我在 Ubuntu Linux 上嘗試了您的內容和代碼。 毫無異議地工作。

構建命令:

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

運行命令:

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

Output:

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

XML 來源:

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

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

驗證成功:YES(結果:0)

您的架構將元素 foo 放入 targetNamespace (這就是 elementdefault="qualified" 的意思),但您的實例文檔沒有聲明該名稱空間或任何其他名稱空間。 所以 foos 實際上並不匹配。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM