[英]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 的发行说明列出了以下错误修复:
更新 2.7.8 的发行说明列出了以下错误修复:
不过,还没有成功让 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.