1

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

<?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 来决定提供哪个架构。现在版本号已切换到根元素中的属性,而我的解析器无权访问它。我应该如何找出 XML 文档中的版本LsResourceResolver

4

2 回答 2

4

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

我将做一些与 Pangea 建议的非常相似的事情(从我那里得到 +1),但我不能完全遵循建议,因为文档太大而无法将其全部读入内存,即使一次。通过使用 STAX,我可以最大限度地减少从文件中获取版本的工作量。请参阅此 DeveloperWorks 文章“使用 StAX 高效地筛选 XML 文档”

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 上设置什么模式文档。

于 2012-08-17T20:39:46.093 回答
3

我的建议

  1. 使用 SAX 或 DOM 解析文档
  2. 获取版本属性
  3. 使用 Validator.validate(Source) 方法并使用已解析的文档(来自步骤 1),如下所示

从解析的文档构建 DOMSource

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

domSource = new DOMSource(document);
于 2012-08-17T14:00:58.027 回答