解决使用具有版本属性的XML文档的XML Schema版本

问题描述:

我必须编写一些代码来处理读取和验证在其根元素中使用version属性来声明版本号的XML文档,如下所示:解决使用具有版本属性的XML文档的XML Schema版本

<?xml version="1.0" encoding="UTF-8" standalone="yes" ?> 
<Junk xmlns="urn:com:initech:tps" 
    xmlns:xsi="http://www3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="urn:com:initech.tps:schemas/foo/Junk.xsd" 
    VersionAttribute="2.0"> 

还有一堆嵌套模式,我的代码中有一个org.w3c.dom.ls.LsResourceResolver找出使用的模式,实施该方法:

LSInput resolveResource(String type, 
         String namespaceURI, 
         String publicId, 
         String systemId, 
         String baseURI) 

上的架构版本的嵌入式架构的版本为命名空间,所以我可以使用namespaceURI和systemId来决定提供哪个模式。现在,版本号已切换到根元素中的属性,并且我的解析器无法访问该属性。我该如何弄清LsResourceResolver中XML文档的版本?

我从来没有必须在此之前处理模式版本,并不知道涉及到什么。当版本是命名空间的一部分时,我可以将所有模式放在一起并让它们整理出来,但是在根元素中的版本和在版本*享的命名空间中,不会从XML读取版本信息之前开始SAX解析。

我打算做一些非常类似于Pangea建议的东西(从我得到+1),但我无法完全遵循这个建议,因为文档太大而无法全部读入内存,甚至一次。通过使用STAX,我可以最大限度地减少从文件中获取版本的工作量。看到这个developerWorks文章,"Screen XML documents efficiently with StAX"

筛选或XML文档的分类是一个常见的问题, 尤其是在XML的中间件。将XML文档路由到特定的 处理器可能需要分析文档类型和 文档内容。这里的问题是以尽可能少的开销从文档中获取所需的 信息。 传统分析器(如DOM或SAX)不适合此 任务。例如,DOM在将控制权返回给客户端之前,解析整个文档并在内存中构造一个完整的文档树。即使使用延迟节点扩展的DOM解析器,并且因此 也能够部分解析文档,具有高资源需求 ,因为文档树必须至少部分地在 存储器中构建。这对于筛选目的来说是不可接受的。

的代码来获取版本信息会看起来像:

def map = [:] 
def startElementCount = 0 
def inputStream = new File(inputFile).newInputStream() 
try { 
    XMLStreamReader reader = 
     XMLInputFactory.newInstance().createXMLStreamReader(inputStream) 
    for (int event; (event = reader.next()) != XMLStreamConstants.END_DOCUMENT;) { 
     if (event == XMLStreamConstants.START_ELEMENT) { 
      if (startElementCount > 0) return map 
      startElementCount += 1 
      map.rootElementName = reader.localName 
      for (int i = 0; i < reader.attributeCount; i++) { 
       if (reader.getAttributeName(i).toString() == 'VersionAttribute') { 
        map.versionIdentifier = reader.getAttributeValue(i).toString() 
        return map 
       } 
      } 
     } 
    } 
} finally { 
    inputStream.close() 
} 

然后,我可以使用的版本信息,以确定用什么解析器,什么模式文档对SaxFactory设置。

我的建议

  1. 使用SAX或DOM
  2. 获取的版本属性
  3. 使用Validator.validate(来源)方法和解析文档和使用已经被解析文档(步骤1)如下图所示

建筑DOMSource的从分析的文档

DocumentBuilder builder = factory.newDocumentBuilder(); 
Document document = builder.parse(new File(args[0])); 

domSource = new DOMSource(document); 
+0

有趣的建议。这是否需要将整个文档读入内存? – 2012-08-17 14:08:13

+0

@NathanHughes是的,但我相信你只做了一次。 – 2012-08-17 14:12:53