1

我有一个要验证的 xml 和架构。我不希望架构存储在文件中,而是存储在数据库位置。我xmlSchemaNewMemParserCtxt用来解析模式。问题是这个模式引用了基本类型的另一个模式:<xs:include schemaLocation="CommonTypes.xsd"/>libXml2 在当前工作目录中搜索。有没有办法在内存缓冲区中提供这些额外的模式?

4

2 回答 2

0

这是一个更好的例子:io1.c http://www.xmlsoft.org/examples/

当您可以找到从 Read 函数返回值的好方法时,它可以节省大量时间。

于 2013-10-04T07:56:13.677 回答
0

xmlRegisterInputCallbacks是您可能正在寻找的。

优势在于,它们让您可以构建某种虚拟 I/O 层。缺点是 inputcallbacks 是全局设置的(但是有xmlPopInputCallbacksxmlCleanupInputCallbacks)。

下面的代码(基于http://knol2share.blogspot.be的代码构建)演示了xmlRegisterInputCallbacks的使用。

所有 xml 和 xsd 文件都是从文件系统加载的,除非 URI 包含“DataTypes.xsd”,否则模式是从字符串中获取的。(因为 schemaLocation 只是一个提示,例如前缀模式的

test.xsd ”:主要的 xml 架构(请忽略对peacelane.org 的引用,命名空间来自一个爱好项目,我现在突然想到 www.peacelane.org 可能存在,显然它确实存在......)

<schema xmlns="http://www.w3.org/2001/XMLSchema"
        xmlns:tns="http://peacelane.org/ApplianceType/config/45/LIGHTING1/ARC" 
        xmlns:dt="http://peacelane.org/ApplianceType/config/45/DataTypes"
        targetNamespace="http://peacelane.org/ApplianceType/config/45/LIGHTING1/ARC"
        elementFormDefault="qualified">
    <import namespace="http://peacelane.org/ApplianceType/config/45/DataTypes" schemaLocation="DataTypes.xsd" />
    <complexType name="ConfigType">
        <sequence>
            <element name="housecode" type="dt:char" />
        </sequence>
    </complexType>
    <element name="Config" type="tns:ConfigType"/>
</schema>

test.xml ”:要验证的测试 xml

<?xml version="1.0"?>
<Config xmlns="http://peacelane.org/ApplianceType/config/45/LIGHTING1/ARC">
    <housecode>A</housecode>
</Config>

main.c ”:实际代码(更新“XMLFileName”和“XSDFileName”的路径)

#define LIBXML_SCHEMAS_ENABLED
#include <libxml/xmlschemastypes.h>
#include <stdio.h>

static const char *databaseSchema =
        "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
                "       <schema elementFormDefault=\"qualified\" xmlns:tns=\"http://peacelane.org/ApplianceType/config/45/DataTypes\"  targetNamespace=\"http://peacelane.org/ApplianceType/config/45/DataTypes\" xmlns=\"http://www.w3.org/2001/XMLSchema\">"
                "           <simpleType name=\"char\">"
                "               <restriction base=\"string\">"
                "                   <length value=\"1\" />"
                "               </restriction>"
                "           </simpleType>"
                "       </schema>";

//-----------------------------------------------------------------------------
//-- SQL Callbacks (~ simulated db actions)
//-----------------------------------------------------------------------------
static void* sqlOpen(const char * URI) {
    return ((void *) databaseSchema );
}

static int sqlClose(void * context) {
    return (0);
}

static int sqlRead(void * context, char * buffer, int len) {
    const char* result= (const char *) context;
    int rlen = strlen(result);
    memcpy(buffer, result, rlen);
    return rlen +1;
}

static int sqlMatch(const char * URI) {
    if ((URI != NULL )&& (strstr(URI, "DataTypes.xsd") != NULL) )return 1;
    return 0;
}
//-----------------------------------------------------------------------------
//-- File callbacks
//-----------------------------------------------------------------------------
static void* fileOpen(const char * URI) {
    if (URI == NULL )
        return (NULL );
    FILE* fh = fopen(URI, "rt");
    return ((void *) fh);
}

static int fileClose(void * context) {
    FILE* fh = (FILE*) context;
    if (fh != NULL )
        fclose(fh);
    return (0);
}

static int fileRead(void * context, char * buffer, int len) {
    FILE* fh = (FILE*) context;

    fseek(fh, 0L, SEEK_END);
    long flen = ftell(fh);
    rewind(fh);

    if (buffer != NULL )
        fread(buffer, flen, 1, fh);

    return flen + 1;
}

static int fileMatch(const char * URI) {
    if ((URI != NULL ))
        if (strstr(URI, "DataTypes.xsd") == NULL ) {
            return (1);
        }

    return (0);
}

//-----------------------------------------------------------------------------
//-- Main
//-----------------------------------------------------------------------------
int main(int argc, char *argv[]) {
    xmlDocPtr doc;
    xmlSchemaPtr schema = NULL;
    xmlSchemaParserCtxtPtr ctxt;
    char *XMLFileName =
            "/home/dogguts/Projects/libxml2tests/xsdparse/Debug/test.xml";
    char *XSDFileName =
            "/home/dogguts/Projects/libxml2tests/xsdparse/Debug/test.xsd";

    xmlLineNumbersDefault(1);

    if (xmlRegisterInputCallbacks(fileMatch, fileOpen, fileRead, fileClose)
            < 0) {
        fprintf(stderr, "failed to register File handler\n");
        exit(1);
    }

    if (xmlRegisterInputCallbacks(sqlMatch, sqlOpen, sqlRead, sqlClose) < 0) {
        fprintf(stderr, "failed to register SQL handler\n");
        exit(1);
    }

    ctxt = xmlSchemaNewParserCtxt(XSDFileName);

    xmlSchemaSetParserErrors(ctxt, (xmlSchemaValidityErrorFunc) fprintf,
            (xmlSchemaValidityWarningFunc) fprintf, stderr);
    schema = xmlSchemaParse(ctxt);
    xmlSchemaFreeParserCtxt(ctxt);

    xmlSchemaDump(stdout, schema);

    doc = xmlReadFile(XMLFileName, NULL, 0);

    if (doc == NULL ) {
        fprintf(stderr, "Could not parse %s\n", XMLFileName);
    } else {
        xmlSchemaValidCtxtPtr ctxt;
        int ret;

        ctxt = xmlSchemaNewValidCtxt(schema);
        xmlSchemaSetValidErrors(ctxt, (xmlSchemaValidityErrorFunc) fprintf,
                (xmlSchemaValidityWarningFunc) fprintf, stderr);
        ret = xmlSchemaValidateDoc(ctxt, doc);
        if (ret == 0) {
            printf("%s validates\n", XMLFileName);
        } else if (ret > 0) {
            printf("%s fails to validate\n", XMLFileName);
        } else {
            printf("%s validation generated an internal error\n", XMLFileName);
        }
        xmlSchemaFreeValidCtxt(ctxt);
        xmlFreeDoc(doc);
    }

    if (schema != NULL )
        xmlSchemaFree(schema);

    xmlSchemaCleanupTypes();
    xmlCleanupParser();
    xmlMemoryDump();

    return (0);
}

请注意,为简洁起见,上述代码不执行任何检查(文件、内存等)操作是否成功。

于 2013-02-27T04:18:16.783 回答