【问题标题】:Add additional xsd schemas with libXml2使用 libXml2 添加其他 xsd 模式
【发布时间】:2012-11-20 09:32:00
【问题描述】:

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

【问题讨论】:

    标签: libxml2


    【解决方案1】:

    xmlRegisterInputCallbacks 是您可能正在寻找的。​​p>

    优势在于,它们让您可以构建某种虚拟 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>
    

    ma​​in.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);
    }
    

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

    【讨论】:

    • 我看到这个问题可以追溯到 11 月。 2012. 如果您(或其他人)有机会找到更好/其他的解决方案,愿意在这里分享吗?
    • xmlSchemaCleanupTypes 多线程安全吗? xmlCleanupParser() 不是,但xmlSchemaCleanupTypes() 的文档比较简短,没有提到这方面。
    【解决方案2】:

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

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

    【讨论】:

    • 请注意 link-only answers 是不鼓励的,所以答案应该是寻找解决方案的终点(与另一个中途停留的参考相比,随着时间的推移往往会变得陈旧)。请考虑在此处添加独立的概要,并保留链接作为参考。
    猜你喜欢
    • 1970-01-01
    • 2017-08-28
    • 1970-01-01
    • 2013-12-17
    • 2015-12-15
    • 2020-09-20
    • 1970-01-01
    • 1970-01-01
    • 2019-05-23
    相关资源
    最近更新 更多