【问题标题】:Resolving which version of an XML Schema to use for XML documents with a version attribute为具有版本属性的 XML 文档解析使用哪个版本的 XML 模式
【发布时间】:2012-08-13 23:28:31
【问题描述】:

我必须编写一些代码来处理读取和验证在其根元素中使用版本属性来声明版本号的 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">

有一堆嵌套的schema,我的代码有一个org.w3c.dom.ls.LsResourceResolver来判断使用什么schema,实现这个方法:

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

架构的先前版本已将架构版本嵌入到命名空间中,因此我可以使用 namespaceURI 和 systemId 来决定提供哪个架构。现在版本号已切换到根元素中的属性,而我的解析器无权访问它。我应该如何找出LsResourceResolver 中XML 文档的版本?

【问题讨论】:

    标签: java xml xsd sax jaxp


    【解决方案1】:

    在此之前我从未处理过模式版本,也不知道其中涉及到什么。当版本是名称空间的一部分时,我可以将所有模式放在一起并让它们整理出来,但是根元素和名称空间中的版本在版本之间共享,因此无法从 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 上设置什么架构文档。

    【讨论】:

      【解决方案2】:

      我的建议

      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);
      

      【讨论】:

      • 有趣的建议。这种方式是否需要将整个文档读入内存?
      • @NathanHughes 是的,但我相信你只做了一次。
      猜你喜欢
      • 2017-03-01
      • 2011-07-17
      • 1970-01-01
      • 1970-01-01
      • 2016-05-19
      • 2019-07-09
      • 2011-11-27
      • 2012-10-17
      • 1970-01-01
      相关资源
      最近更新 更多