本站首页    管理页面    写新日志    退出


«August 2025»
12
3456789
10111213141516
17181920212223
24252627282930
31


公告

戒除浮躁,读好书,交益友


我的分类(专题)

日志更新

最新评论

留言板

链接

Blog信息
blog名称:邢红瑞的blog
日志总数:523
评论数量:1142
留言数量:0
访问次数:9692122
建立时间:2004年12月20日




[java语言]使用saxon的xpath的问题 
原创空间,  软件技术,  电脑与网络

邢红瑞 发表于 2007/12/9 18:25:13

很久不写blog了,最近用xpath,发现xpath 1.0不够用了,想起来xquery也许不错,发现支持xquery的java库只有saxon。大多数xpath的支持库jdom dom4j jaxp还有jaxen仅支持xpath 1.0,xpath2.0久不支持,还好xpath 2.0是xquery的子集,可以使用saxon了。第一次运行saxon的例子就出现了问题,这是saxon提供的使用sun的jaxp的xpath的例子,其中没有用到saxon。import org.w3c.dom.Node;import org.w3c.dom.NodeList;import org.xml.sax.InputSource; import javax.xml.namespace.QName;import javax.xml.parsers.DocumentBuilder;import javax.xml.parsers.DocumentBuilderFactory;import javax.xml.xpath.*;import java.io.BufferedReader;import java.io.File;import java.io.InputStreamReader; /**  * Class XPathExampleDOM:  *  * This is a variant of the XPathExample application written to use DOM interfaces. Using the DOM  * rather than Saxon's native tree model is not recommended unless the application has other reasons  * to use the DOM model, but this application shows how it can be done when necessary.  *  * This class illustrates the use of the JAXP XPath API. It is a simple command-line application,  * which prompts the user for a word, and replies with a list of all the lines containing that  * word within a Shakespeare play.  *  *  * @author Michael H. Kay (Michael.H.Kay@ntlworld.com)  * @version Auguest 2005: modified to use DOM interfaces  */ public class XPathExampleDOM implements XPathVariableResolver {     private String currentWord;     /**      * main()<BR>      * Expects one argument, the input filename<BR>      */     public static void main (String args[])    throws Exception    {        // Check the command-line arguments         if (args.length != 1) {            System.err.println("Usage: java XPathExampleDOM input-file");            System.exit(1);        }        XPathExampleDOM app = new XPathExampleDOM();        app.go(args[0]);    }     /**    * Run the application    */     public void go(String filename) throws Exception {         XPathFactory xpf = XPathFactory.newInstance(XPathConstants.DOM_OBJECT_MODEL);        XPath xpe = xpf.newXPath();        System.err.println("Loaded XPath Provider " + xpe.getClass().getName());         // Build the source document.        DocumentBuilderFactory dfactory = DocumentBuilderFactory.newInstance();        System.err.println("Using DocumentBuilderFactory " + dfactory.getClass());         dfactory.setNamespaceAware(true);         DocumentBuilder docBuilder = dfactory.newDocumentBuilder();            System.err.println("Using DocumentBuilder " + docBuilder.getClass());         Node doc =            docBuilder.parse(new InputSource(new File(filename).toURL().toString()));         // Declare a variable resolver to return the value of variables used in XPath expressions        xpe.setXPathVariableResolver(this);         // Compile the XPath expressions used by the application         XPathExpression findLine =            xpe.compile("//LINE[contains(., $word)]");        XPathExpression findLocation =            xpe.compile("concat(ancestor::ACT/TITLE, ' ', ancestor::SCENE/TITLE)");        XPathExpression findSpeaker =            xpe.compile("string(ancestor::SPEECH/SPEAKER[1])");         // Create a reader for reading input from the console         BufferedReader in = new BufferedReader(new InputStreamReader(System.in));         // Loop until the user enters "." to end the application         while (true) {             // Prompt for input            System.out.println("\n>>>> Enter a word to search for, or '.' to quit:\n");             // Read the input            String word = in.readLine().trim();            if (word.equals(".")) {                break;            }            if (!word.equals("")) {                 // Set the value of the XPath variable                currentWord = word;                 // Find the lines containing the requested word                NodeList matchedLines = (NodeList)findLine.evaluate(doc, XPathConstants.NODESET);                 // Process these lines                boolean found = false;                final int len = matchedLines.getLength();                for (int i=0; i<len; i++) {                     // Note that we have found at least one line                    found = true;                     // Get the next matching line                    Node line = matchedLines.item(i);                     // Find where it appears in the play                    System.out.println('\n' + findLocation.evaluate(line));                     // Output the name of the speaker and the content of the line                    System.out.println(findSpeaker.evaluate(line) + ":  " + line.getTextContent());                }                 // If no lines were found, say so                if (!found) {                    System.err.println("No lines were found containing the word '" + word + '\'');                }            }        }         // Finish when the user enters "."        System.out.println("Finished.");    }     /**     * This class serves as a variable resolver. The only variable used is $word.     * @param qName the name of the variable required     * @return the current value of the variable     */     public Object resolveVariable(QName qName) {        if (qName.getLocalPart().equals("word")) {            return currentWord;        } else {            return null;        }    } }我也是第一次发现xpath中居然可以定义变量,看了看sun的文档还可以定义函数呢。这段代码在没有saxon的saxon9-xpath.jar,运行ok,如果有saxon9-xpath.jar,抛出Exception in thread "main" javax.xml.xpath.XPathExpressionException: Cannot locate an object model implementation for nodes of class com.sun.org.apache.xerces.internal.dom.DeferredDocumentImpl高人maomaode说是classpath有问题,我比较了一次两次的日志Loaded XPath Provider com.sun.org.apache.xpath.internal.jaxp.XPathImplUsing DocumentBuilderFactory class com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImplUsing DocumentBuilder class com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderImplLoaded XPath Provider net.sf.saxon.xpath.XPathEvaluatorUsing DocumentBuilderFactory class com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImplUsing DocumentBuilder class com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderImplxpath的提供者不同,导致出了问题,看了看sun的javadocJAXP提供的接口可以自定义Xpath的实现,抽象类XPathFactory 有两个静态newInstance()方法初始化一个具体的工厂用来封装实现.  newInstance() 可以使用system property 来决定使用那一个实现.Xalan-Java 2的预配置META-INF/services/javax.xml.xpath.XPathFactory,里面的值为org.apache.xpath.jaxp.XPathFactoryImpl.也可以动态设置,sun的javadoc说明public static final XPathFactory newInstance(String uri)                                      throws XPathFactoryConfigurationException获取使用指定对象模型的新 XPathFactory 实例。为了查找 XPathFactory 对象,此方法按以下顺序查找以下位置,其中“类加载器”指上下文类加载器:如果存在系统属性 DEFAULT_PROPERTY_NAME + ":uri"(其中 uri 是此方法的参数),则其值作为类名称读取。该方法将试图通过使用类加载器创建此类的新实例,如果创建成功,则返回它。 读取 ${java.home}/lib/jaxp.properties,并查找与作为系统属性的键关联的值。如果存在,则按上面的方式处理该值。 类加载器要求服务提供者的提供者配置文件与资源目录 META-INF/services 中的 javax.xml.xpath.XPathFactory 匹配。有关文件格式和解析规则,请参阅 JAR File Specification。每个可能的服务提供者均要实现该方法:        isObjectModelSupported(String objectModel)返回支持指定对象模型的类加载器顺序中的第一个服务提供者。 以特定于平台的方式来定位平台默认的 XPathFactory。必须存在 W3C DOM 的平台默认 的 XPathFactory,即 DEFAULT_OBJECT_MODEL_URI。 如果这些都失败,则抛出 XPathFactoryConfigurationException。疑难解答提示:有关如何精确解析属性文件的信息,请参阅 Properties.load(java.io.InputStream)。尤其是,冒号 ':'在属性文件中需要转义,因此要确保 URI 在其中进行正确转义。例如:    http\://java.sun.com/jaxp/xpath/dom=org.acme.DomXPathFactory 参数:uri - 标识底层对象模型。规范只定义了 URI DEFAULT_OBJECT_MODEL_URI、用于 W3C DOM 的 http://java.sun.com/jaxp/xpath/dom、org.w3c.dom 包。至于其他对象模型,实现可随意引入其他 URI。 返回:XPathFactory 的实例。 抛出: XPathFactoryConfigurationException - 如果指定的对象模型不可用。 NullPointerException - 如果 uri 为 null。 IllegalArgumentException - 如果 uri 为 null 或 uri.length() == 0。但是设置System.setProperty("javax.xml.xpath.XPathFactory:"+NamespaceConstant.OBJECT_MODEL_SAXON,                "com.sun.org.apache.xpath.internal.jaxp.XPathImpl");        XPathFactory xpf = XPathFactory.newInstance(XPathConstants.DOM_OBJECT_MODEL);        System.out.println(XPathConstants.DOM_OBJECT_MODEL);没有任何作用,没有办法,只有使用软件的爆破了,打开saxon9-xpath.jar,将里面的META-INF\services下javax.xml.xpath.XPathFactory改为net.sf.saxon.xpath.XPathFactoryImplhttp\://java.sun.com/jaxp/xpath/dom:    com.sun.org.apache.xpath.internal.jaxp.XPathImplhttp\://saxon.sf.net/jaxp/xpath/om:     net.sf.saxon.xpath.XPathFactoryImplhttp\://www.xom.nu/jaxp/xpath/xom:      net.sf.saxon.xpath.XPathFactoryImplhttp\://jdom.org/jaxp/xpath/jdom:       net.sf.saxon.xpath.XPathFactoryImplhttp\://www.dom4j.org/jaxp/xpath/dom4j: net.sf.saxon.xpath.XPathFactoryImpl原因是这样的.即时你定义了http://java.sun.com/jaxp/xpath/dom,但是http://java.sun.com/jaxp/xpath/dom被改为net.sf.saxon.xpath.XPathFactoryImpl,不出问题就怪了.打包运行,一切ok.


阅读全文(10816) | 回复(0) | 编辑 | 精华
 



发表评论:
昵称:
密码:
主页:
标题:
验证码:  (不区分大小写,请仔细填写,输错需重写评论内容!)



站点首页 | 联系我们 | 博客注册 | 博客登陆

Sponsored By W3CHINA
W3CHINA Blog 0.8 Processed in 0.344 second(s), page refreshed 144767792 times.
《全国人大常委会关于维护互联网安全的决定》  《计算机信息网络国际联网安全保护管理办法》
苏ICP备05006046号