2014-03-12 32 views
1

我正在使用libxml2实施模式验证。我正在验证的模式导入两个其他模式,如线:如何在没有网络访问的情况下导入XML模式?

<xs:import namespace="http://www.w3.org/XML/1998/namespace" 
      schemaLocation="http://www.somewebsite.com/xsd/xml.xsd"/> 

所有这三个模式文件都位于设备上的同一目录中。

当设备可以访问因特网时,此功能可以正常工作,但当设备无法访问时会失败,因为即使通过,libxml2仍尝试从schemaLocation下载导入的模式。

我试图让libxml2的通过编辑schemaLocation属性为xml.xsd./xml.xsdfile:///data/data/com.company.appname/files/xml.xsd本地加载的文件,但所有这三个导致相同的libxml2错误:

  • 域:16
  • 代码: 3069 (XML_SCHEMAP_INTERNAL)
  • 消息:Internal error: xmlSchemaParse, An internal error occurred.

我也尝试完全删除schemaLocation属性,因为libxml2可能会在原始模式旁边搜索导入的模式,但当模式解析器击中引用导入实体的行时会导致以下错误:

<xs:attribute ref="xml:lang" use="required"/> 
  • 域:16
  • 代码:3004 (XML_SCHEMAP_SRC_RESOLVE)
  • 消息:attribute use (unknown), attribute 'ref': The QName value '{http://www.w3.org/XML/1998/namespace}lang' does not resolve to a(n) attribute declaration.

我也研究过将三个模式手动合并到一个文件中,但由于它们使用不同的名称空间,所以这是不可能的。

此标准的解决办法似乎是XML目录,但我已经通过阅读libxml2's catalog documentation,我无法弄清楚如何(或者甚至它是否可能)添加将通过使用我的映射应用程序部署到设备时。我想我可能需要实现一个xmlExternalEntityLoader,但文档相当薄弱。

如何让libxml2导入这些模式而无需网络访问?显然,我最好喜欢一个可以与未经编辑的模式一起工作的健壮的解决方案,但我已经满足于快速和肮脏的涉及编辑模式的内容,就像我上面描述的那样。

上述错误来自Android设备(使用JNI),但我在iOS上遇到了类似的问题,该解决方案也需要工作。

回答

0

执行此操作的一种方法是拦截libxml2的调用以使用自定义xmlExternalEntityLoader打开导入的URL。

这样做的基本代码如下:

#include <libxml/xmlIO.h> 
#include <libxml/parserinternals.h> 

xmlExternalEntityLoader defaultLoader = NULL; 

xmlParserInputPtr 
xmlMyExternalEntityLoader(const char *URL, const char *ID, 
          xmlParserCtxtPtr ctxt) { 
    xmlParserInputPtr ret; 
    const char *fileID = NULL; 
    /* lookup for the fileID 
    * The documentation suggests using the ID, but for me this was 
    * always NULL so I had to lookup by URL instead. 
    */ 

    ret = xmlNewInputFromFile(ctxt, fileID); 
    if (ret != NULL) 
     return(ret); 
    if (defaultLoader != NULL) 
     ret = defaultLoader(URL, ID, ctxt); 
    return(ret); 
} 

int main(..) { 
    ... 

    /* 
    * Install our own entity loader 
    */ 
    defaultLoader = xmlGetExternalEntityLoader(); 
    xmlSetExternalEntityLoader(xmlMyExternalEntityLoader); 

    ... 
} 

(从样本代码的libxml2的I/O接口文档The entities loader节略调整。)

相关问题