根据您的企业安全策略,某些(如果不是大多数的话)中间件服务器无法访问Internet。 当您的开发基础结构与Internet(例如银行或安全公司)隔离时,情况甚至更糟。 在这种情况下,根据架构验证XML真是一场噩梦。
当然,您可以将XML模式位置设置为硬盘驱动器上的位置。 但是关于您的同事呢? 他们将不得不在完全相同的文件系统层次结构中拥有模式,这不会解决您有关生产环境的问题...
XML目录
XML目录是您的难题的名义解决方案。 实际上,您插入了一个解析器,该解析器知道如何将在线位置映射到文件系统上的某个位置(或更确切地说是另一个位置)。 此解析器是通过xml.catalog.files
系统属性设置的,该属性对于每个开发人员或在生产环境中可能有所不同:
<catalogxmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog">
<systemsystemId="http://blog.frankel.ch/xmlcatalog/person.xsd"uri="person.xsd"/>
<systemsystemId="http://blog.frankel.ch/xmlcatalog/order.xsd"uri="order.xsd"/>
</catalog>
现在,当验证发生时,它不是查找联机模式URL位置,而是查找本地模式。
如何
XML目录可以与JAXP,SAX,DOM或STaX一起使用。 下面详细说明如何将代码与SAX一起使用的代码。
SAXParserFactoryfactory=SAXParserFactory.newInstance();
factory.setNamespaceAware(true);
factory.setValidating(true);
XMLReaderreader=factory.newSAXParser().getXMLReader();
// Set XSD as the schema language
reader.setProperty("http://java.sun.com/xml/jaxp/properties/schemaLanguage","http://www.w3.org/2001/XMLSchema"); (2)
// Use XML catalogs
reader.setEntityResolver(newCatalogResolver()); (1)
InputStreamstream=getClass().getClassLoader().getResourceAsStream("person.xml");
reader.parse(newInputSource(stream));
有两行很重要:
- 我们告诉读者使用XML目录
- 我们绝对必须使用阅读器,而不是SAX解析器来解析XML或将在线进行验证!
用例
XML目录基本上有两个用例:
- 如上所示,第一个用例是针对缓存的本地模式文件验证XML文件
- 除此之外,XML目录还可以用作
LSResourceResolver
的替代品(如先前在使用导入/包含模式的XML验证中所见)
重要的提示
请注意:JDK中的内部com.sun
包中提供了CatalogResolver
类,但是Apache XML解析器库可以完成此工作。 实际上,内部类只是对Apache类的重新包装。
如果使用Maven,则依赖关系如下:
<dependency>
<groupId> xml-resolver </groupId>
<artifactId> xml-resolver </artifactId>
<version> 1.2 </version>
</dependency>
超越目录
目录是映射在线模式位置的基于文件系统的标准方法。
但是,这并不总是最好的选择策略。 例如,Spring在JAR内提供了其不同的模式,以及类,并针对这些模式进行了验证。
为了执行相同的操作,请替换上面代码中的第13行,而不是CatalogResolver
,而是使用您自己的EntityResolver实现。
您可以在此处找到本文的来源(请注意,关联的测试使用自定义的安全策略文件来防止网络访问,并且,如果要直接在IDE中进行测试,则应重用POM中使用的系统属性)。
翻译自: https://blog.frankel.ch/use-local-resources-when-validating-xml/