検証したいxmlとスキーマがあります。スキーマをファイルに保存したくないが、データベースの場所に保存したい。xmlSchemaNewMemParserCtxt
スキーマの解析に使用します。問題は、このスキーマが基本タイプの別のスキーマを参照していることです。これは<xs:include schemaLocation="CommonTypes.xsd"/>
、libXml2が現在の作業ディレクトリで検索します。これらの追加スキーマをメモリバッファに提供する方法はありますか?
2 に答える
xmlRegisterInputCallbacksは、おそらく探しているものです。
利点は、ある種の仮想I/Oレイヤーを構築できることです。欠点は、inputcallbacksがグローバルに設定されることです(ただし、xmlPopInputCallbacksとxmlCleanupInputCallbacksがあります)。
以下のコード(http://knol2share.blogspot.beのコードに基づいて作成)は、 xmlRegisterInputCallbacksの使用法を示しています。
URIに「DataTypes.xsd」が含まれている場合を除き、すべてのxmlファイルと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);
}
簡潔にするために、上記のコードは(ファイル、メモリ、...)操作が成功したかどうかのチェックを実行しないことに注意してください。