2011-10-03 53 views
1

我有一种情况,我们希望验证在内存中作为字节流保存的XML文档,以及在文件系统中放置在其他XSD中的XSD。我们希望避免在XML文件中明确提到文件名,而是告诉XML解析器使用一个或多个XSD文件的目录进行验证。JAXP - 调试XSD目录查找

我尝试创建的DocumentBuilder提供商(对于吉斯3.0)看起来像:

public class ValidatingDocumentBuilderProvider implements 
     Provider<DocumentBuilder> { 

    static final String JAXP_SCHEMA_LANGUAGE = "http://java.sun.com/xml/jaxp/properties/schemaLanguage"; 
    static final String W3C_XML_SCHEMA = "http://www.w3.org/2001/XMLSchema"; 
    static final String JAXP_SCHEMA_SOURCE = "http://java.sun.com/xml/jaxp/properties/schemaSource"; 

    Logger log = getLogger(ValidatingDocumentBuilderProvider.class); 

    DocumentBuilderFactory dbf; 

    public synchronized DocumentBuilder get() { // dbf not thread-safe 

     if (dbf == null) { 
      log.debug("Setting up DocumentBuilderFactory"); 

      // http://download.oracle.com/javaee/1.4/tutorial/doc/JAXPDOM8.html 
      dbf = DocumentBuilderFactory.newInstance(); 
      dbf.setNamespaceAware(true); 
      dbf.setValidating(true); 
      dbf.setAttribute(JAXP_SCHEMA_LANGUAGE, W3C_XML_SCHEMA); 
      // parser should look for schema reference in xml file 

      // Find XSD's in current directory. 

      FilenameFilter fileNameFilter = new FilenameFilter() { 

       public boolean accept(File dir, String name) { 
        return name.toLowerCase().endsWith(".xsd"); 
       } 
      }; 
      File[] schemaFiles = new File(".").listFiles(fileNameFilter); 

      dbf.setAttribute(JAXP_SCHEMA_SOURCE, schemaFiles); 

      log.debug("{} schema files found", schemaFiles.length); 
      for (File file : schemaFiles) { 
       log.debug("schema file: {}", file.getAbsolutePath()); 
      } 

     } 

     try { 
      return dbf.newDocumentBuilder(); 
     } catch (ParserConfigurationException e) { 
      throw new RuntimeException("get DocumentBuilder", e); 
     } 
    } 
} 

(我也试图与文件名太)。 Eclipse接受XSD - 当将其放入目录中时,它可以验证此处处理的XML

看起来,肉眼看来,解析器在尝试验证时会暂时停止。这可能是网络查找。

-Djaxp.debug=1只会增加这些线路

JAXP: find factoryId =javax.xml.parsers.DocumentBuilderFactory 
JAXP: loaded from fallback value: com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl 
JAXP: created new instance of class com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl using ClassLoader: null 

我怎样才能在JDK 6解析器告诉我它在做什么?如果我不能这样做,我该如何检查其中的XML Catalog用法,以了解为什么没有选择提供的XSD?

我忽视了什么显而易见的东西?

回答

0

你说

我们想避免在XML文件中明确提到

那么如何将解析器能够选择适当的模式的文件名?

您可以尝试的方法是使用SchemaFactory基于所有可用模式资源创建Schema,并将其附加到文档生成器工厂。解析器会自动根据这个“超级模式”验证文档。

如果您的模式集具有内部依赖关系(即导入或包含),请确保使用相对URL或专用解析器正确解析这些引用。

UPDATE:

更仔细地看这篇文章,http://java.sun.com/j2ee/1.4/docs/tutorial/doc/JAXPDOM8.html,过一会儿之后,我才知道你的方法应该是我的建议同样的效果,所以别的东西会ñ。我只能说我所描述的工作非常好。

+0

据我了解,每个XSD都提到了它可以验证的命名空间。如果在XML中使用任何这些名称空间,我希望解析器使用相应的XSD。 –