在我的java应用程序中,我必须同时处理具有不同模式版本(xsd文件)的XML文件。 XML文件的内容在不同的版本之间只有一点点的变化,所以我想主要使用相同的代码来处理它,并且只是根据所使用的模式的版本做一些案例distictions。
现在我正在使用SAX解析器和我自己的ContentHandler
解析XML文件,忽略架构版本,只检查我需要处理的标签是否存在。
我真的很想使用JAXB生成用于解析XML文件的类。这样我就可以从我的java代码中删除所有硬编码字符串(常量),并使用生成的类来处理。
我将架构版本编译为不同的包v1,v2和v3。现在我可以用这种方式创建Unmarshaller
:
JAXBContext jc = JAXBContext.newInstance(
v1.Root.class, v2.Root.class, v3.Root.class );
Unmarshaller u = jc.createUnmarshaller();
现在u.unmarshal( xmlInputStream );
为我提供了与XML文件架构匹配的Root
类。
接下来,我将尝试定义interface
以访问模式的公共部分。 如果您以前做过类似的事情,请告诉我。与此同时,我正在阅读JAXB规范...
答案 0 :(得分:6)
首先,您需要某种方法来识别适合特定实例文档的模式。您说文档具有schemaLocation
属性,因此这是一个解决方案。但请注意,您必须专门配置解析器以使用此属性,并且恶意文档可以指定您无法控制的架构位置。相反,我建议获取属性值,并使用它在内部表中查找适当的模式。
接下来是访问数据。你没有说为什么你使用三种不同的模式。唯一合理的原因是不断发展的数据规范(即,模式代表相同数据的版本1,2和3)。如果这不是您的理由,那么您需要重新考虑您的设计。
如果您正在尝试支持不断发展的数据规范,那么您需要回答“如何处理缺少的数据”这一问题。这有几个答案:一个是维护代码的多个版本。通过重构常用功能,这不是一个坏主意,但它很容易变得不可维护。
另一种方法是使用单个代码库,以及包含规则的某种adapter对象。如果沿着这条路走下去,JAXB是错误的解决方案,因为它与模式相关联。你可以使用一个宽松的XML-> Java转换器:我相信XStream会起作用,我知道Practical XML的1.1版本会起作用(因为我写了它) - 尽管你我必须自己建造它。
另一个更好的替代方案,取决于模式的复杂性,是开发一组使用XPath来检索数据的对象。我可能会在架构的每个变体中使用包含每个字段的XPath表达式的“主”对象来实现。然后创建包含实例文档的DOM版本的轻量级“包装器”对象,并使用适合于模式的XPath。但请注意,这仅限于只读访问。