解决使用具有版本属性的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设置。
我的建议
- 使用SAX或DOM
- 获取的版本属性
- 使用Validator.validate(来源)方法和解析文档和使用已经被解析文档(步骤1)如下图所示
建筑DOMSource的从分析的文档
DocumentBuilder builder = factory.newDocumentBuilder();
Document document = builder.parse(new File(args[0]));
domSource = new DOMSource(document);
有趣的建议。这是否需要将整个文档读入内存? – 2012-08-17 14:08:13
@NathanHughes是的,但我相信你只做了一次。 – 2012-08-17 14:12:53