Syntax error in javax.xml.xpath.XPathFactory provider-configuration file of Saxon-HE 9.3
我在Mac OS X和Saxon-HE 9.3.0.5上使用Java SE 6。 ServiceLoader无法找到
1 2 3 4 | mac:test2 ludo$ java -version java version"1.6.0_26" Java(TM) SE Runtime Environment (build 1.6.0_26-b03-383-11A511) Java HotSpot(TM) 64-Bit Server VM (build 20.1-b02-383, mixed mode) |
The class loader is asked for service provider provider-configuration files matching javax.xml.xpath.XPathFactory in the resource directory META-INF/services. See the JAR File Specification for file format and parsing rules.
JAR文件规范的"服务提供者"部分指出:
The file should contain a newline-separated list of unique concrete provider-class names.
但是,如果我提取saxon9he.jar文件并查看META-INF目录,则会看到:
1 2 3 4 5 6 7 | mac:Java ludo$ mkdir test mac:Java ludo$ cd test mac:test ludo$ jar fx ../saxon9he.jar mac:test ludo$ cat META-INF/services/javax.xml.xpath.XPathFactory net.sf.saxon.xpath.XPathFactoryImpl http\\://java.sun.com/jaxp/xpath/dom: net.sf.saxon.xpath.XPathFactoryImpl http\\://saxon.sf.net/jaxp/xpath/om: net.sf.saxon.xpath.XPathFactoryImpl |
第一行是正确的,但我看不到为什么有两行多余的行,并且看起来这些行给ServiceLoader造成了麻烦。我看到了一个测试示例的问题,该示例编写了理解用于查找提供程序的机制。我们可以看到saxon9he.jar在CLASSPATH中。
1 2 3 4 | mac:services ludo$ java ServicesTest CLASSPATH = ..., /Users/ludo/Library/Java/saxon9he.jar, ... Service XPathFactory: java.util.ServiceLoader[javax.xml.xpath.XPathFactory] ServiceConfigurationError: javax.xml.xpath.XPathFactory: jar:file:/Users/ludo/Library/Java/saxon9he.jar!/META-INF/services/javax.xml.xpath.XPathFactory:2: Illegal configuration-file syntax |
兴趣线是:
1 | jar:file:/Users/ludo/Library/Java/saxon9he.jar!/META-INF/services/javax.xml.xpath.XPathFactory:2: Illegal configuration-file syntax |
这是Saxon的错误还是系统不支持的扩展语法?我该怎么做才能解决这个问题?
请注意,如果我明确选择实现的类,则可以获得工厂。但是我想使用服务机制。以下代码有效:
1 2 3 4 | XPathFactory xpf = XPathFactory.newInstance( XPathFactory.DEFAULT_OBJECT_MODEL_URI, "net.sf.saxon.xpath.XPathFactoryImpl", ClassLoader.getSystemClassLoader()); |
我在下面添加了整个Java测试程序。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 | import java.net.URL; import java.net.URLClassLoader; import java.util.Iterator; import java.util.ServiceConfigurationError; import java.util.ServiceLoader; import javax.xml.xpath.XPathFactory; public class ServicesTest { public static String getClasspathString() { StringBuilder classpath = new StringBuilder(); ClassLoader classLoader = ClassLoader.getSystemClassLoader(); URL[] urls = ((URLClassLoader) classLoader).getURLs(); for (int i = 0; i < urls.length - 1; i++) { classpath.append(urls[i].getFile()).append(","); } if (urls.length > 0) { classpath.append(urls[urls.length - 1].getFile()); } return classpath.toString(); } public static void availableProviders(ServiceLoader sl) { Iterator it = sl.iterator(); int index = 0; for (;;) { try { if (!it.hasNext()) { break; } index++; Object o = it.next(); System.out.printf("%03d Concrete class name: %s\ ", index, o.getClass().getName()); } catch (ServiceConfigurationError e) { System.err.printf("ServiceConfigurationError: %s\ ", e.getMessage()); } } } public static void main(String[] args) { System.out.printf("CLASSPATH = %s\ ", getClasspathString()); System.out.println(); ServiceLoader<XPathFactory> slXPathFactory = ServiceLoader.load(XPathFactory.class); System.out.printf("Service XPathFactory: %s\ ", slXPathFactory.toString()); availableProviders(slXPathFactory); } } |
Michael Kay在SourceForge论坛上回答了这个问题。 他说过:
The format of the file was chosen to circumvent a JDK5 bug.
还有:
Actually, I wouldn't recommend using the JAXP search mechanism anyway. It's very slow, and it delivers an XPath engine that won't necessarily work with your application. You have no way of knowing whether you get an XPath 1.0 or 2.0 implementation back, and the API is so weakly defined that there's very little chance your application will work with a particular provider unless you have tested it with that provider first. So even without this bug, I would steer clear of it.
我认为它可以回答问题,即使它没有为该问题提供明确的解决方案。 因此,我们可以通过以下方式选择实现:
1 2 3 4 | XPathFactory xpf = XPathFactory.newInstance( XPathFactory.DEFAULT_OBJECT_MODEL_URI, "net.sf.saxon.xpath.XPathFactoryImpl", ClassLoader.getSystemClassLoader()); |
我知道这是一个较旧的主题,但是我的这个帖子可能使您对该问题有所了解。 它使用我从未见过的-D参数找到XPathFactory。