学习使用XML引擎XQEngine
转自:动态网站制作南
| www.knowsky.com
最近我一直在寻找XML搜索工具,我编写的应用程序需要定期的搜索一些有关联的XML文件,我本来的意思是为了看一看文件中是否有与我想要的数据匹配的
数据,但是有时候,我也想把找到的这些数据输出出来。一开始,我试用了一下XSLT和XPath,想通过把搜索的问题转化成使用XSLT能够解决的问题,
但是经过一段时间的试验,我发现,使用XSLT并没有真正解决我想要处理的搜索问题,因为我想要输出的数据是使用逗号隔开的数,而XSLT不能满足这个要
求,而且XLST也不能提供全文搜索功能。然后我想尝试一下使用XML查询语言(XQL),来看看能不能解决,所以我仔细的着了一下XQL的各种版本的实
现,很巧,正好发现一个叫XQEngine的小工具能解决这个问题,所以,在本文中我想介绍一下如何使用XQEngine来在你的XML文件中搜寻你想要
找的字符串数据。
XQEngine可以在www.fatdog.com网站下找到,它是一个JavaBean,使用一个SAX解析器来索引一个或多个XML文档,然后你就可以在这些文档中进行复合式搜索了。它所使用的搜索语言是XQL的超集,与XPath有相似的语法。
使用XQEngine的Java类必须实现一个result()方法,完成搜索后,引擎将调用这个方法把搜索结果传到result()方法中,可以使用
三种显示数据的格式来输出数据结果。使用命令行参数指明你所需要的搜索参数,比如说你可以指明一个文件假如含有stop这个词,就不会被索引;又如你可以
在参数中命令引擎忽略那些少于指定子数的词。
下面,我给出了一个使用XQEngine的例程,现在让我们来分析一下。首先,main
()方法实例化一个搜索引擎:XmlEngine engine = new
XmlEngine(),然后它从命令行中取得文件名、返回结果格式和搜索请求这三个参数,再使用各种配置方法来设置引擎,接着调用
setSaxParserName()方法来设置SAX解析器的全名,因为我们使用的是Xerces解析器,所以要用到
"org.apache.xerces.parsers.SAXParser"。然后我们就需要设置搜索参数,再本例中,我们将不索引数字或任何少于3个
字符的词。在你下载到的XQEngine的API文档当中会有详细的配置参数说明,所以在此我就不细说如何配置参数了,请大家自己参阅相关文档。最后,
setDocument()方法指定XQEngine将要索引或搜索的XML文件。当然,如果你想要索引多个文件的话,只需设置几个相应的
setDocument()方法就可以了。
从下面的代码中我们还可以看到,XQEngine引擎将用三种不同的格式返回搜索结果:
STANDARD、SUMMARY和CSV(使用逗号分开的数值)为了简单起见,我为每种返回结果类型定义了一个数字来代替(1,2,3),然后使用相应
的参数调用setListenerType()方法。我将在后面详细介绍每一种返回结果类型。还有个方法printSessionState()用来输出
索引和引擎的信息,但是我没有把它写进例程中,所以上面的程序只会输出搜索结果;下一步再调用addXQLResultListener()方法,并传递
Search的一个实例,用来实现XQLResultListener的接口;然后再把查询字符串作为一个参数来调用setQuery方法,引擎就会开始
执行查询任务。等到查询结束后,引擎调用Search类的result()方法,把查询结果传回,在我提供的例程中,result()方法只是简单的把结
果输出出来。
代码:
import java.io.*; import com.fatdog.textEngine.XmlEngine; import com.fatdog.textEngine.exceptions.*; import com.fatdog.textEngine.query.XQLResultListener; public class Search implements XQLResultListener { public static void main( String[] args ) { XmlEngine engine = new XmlEngine(); String searchFile = args[0]; String searchType = args[1]; String query = args[2]; try { file://配置引擎 engine.setSaxParserName( "org.apache.xerces.parsers.SAXParser"); engine.setMinIndexableWordLength( 3 ); engine.setDoIndexNumbers( false ); engine.setDocument( searchFile );
if (searchType.equals("1")) { engine.setListenerType( XmlEngine.STANDARD_LISTENER); } else if (searchType.equals("2")) { engine.setListenerType( XmlEngine.SUMMARY_LISTENER); } else { engine.setListenerType( XmlEngine.CSV_LISTENER); } } catch( MissingOrInvalidSaxParserException e ){ System.out.println( "缺少或不可用的 SAX解析器" ); return; } catch( FileNotFoundException e ) { System.out.println( "不能找到 XML 文件: "); return; } catch( CantParseDocumentException e ) { System.out.println( "不能解析 XML 文件: "); return; } // engine.printSessionStats(); engine.addXQLResultListener( new Search() ); try { engine.setQuery( query ); } catch( InvalidQueryException e ) { System.out.println( "不可用的查询请求: " + e.getMessage() ); return; } } public void results( String xqlResults ) { System.out.println( xqlResults ); } }
|
好,我们已经把一个使用XQEngine的程序编写出来了,那么就让我们来运行这段代码,在编译这段代码之前,我们需要下载到XQEngine和SAX解析器。我是从xml.apache.org上下载到Xerces解析器的。我使用的操作系统是Windows 2000
Professional,JDK为1.3版,好,搞定这些以后就跟我来设置CLASSPATH吧,在"环境变量"中修改CLASSPATH,添加"c:
\xql\XQEngine.jar;c:\xql\antlr.jar;
c:\xerces\xerces.jar"。现在就可以编译代码了,不过为了能够运行程序,我们还需要一个XML文件,我使用了Apache
Tomcat里的web.xml文件作为演示。前面我也介绍过了,我们使用1,2,3来分别代替三种返回查询结果格式:
1、使用
STANDARD_LISTENER
(数字1)和查询项"//welcome-file-list/welcome-file",C:\xql\xql1>java Search
web.xml 1 "//welcome-file-list/welcome-file"
Parser.installSaxParser:
<org.apache.xerces.parsers.SAXParser> installed successfully 1: indexing web.xml Query: ( // ( / welcome-file-list welcome-file ) ) 3 hit(s) for file://welcome-file-list/welcome-file <?xml version="1.0"?> <xql:result query="//welcome-file-list/welcome-file" hitCount="3" elemCount="3" docCount="1" xmlns:xql="http://www.fatdog.com/ Standard_Listener.html"> <welcome-file> index.jsp </welcome-file> <welcome-file> index.html </welcome-file> <welcome-file> index.htm </welcome-file> </xql:result>
|
上面的例子中,查询项要求找到任何"welcome-file-list"元素的所有的"welcome-file"子元素。请注意,搜索的结果基本上
是从原XML文档中摘录出来的,不能够建立搜索结果和原文档之间的关系。SUMMARY_LISTENER(2)返回类型则有些不同,它包括一个
"docID"号和一个"elemlx"号,这样就能够把结果和原文档联系起来了。
如下是返回结果的示例:
C:\xql\xql1>java Search web.xml 2 "//welcome-file-list/welcome-file" Parser.installSaxParser: <org.apache.xerces.parsers.SAXParser> installed successfully
1: indexing web.xml
Query: ( // ( / welcome-file-list welcome-file ) )
3 hit(s) for file://welcome-file-list/welcome-file
<?xml version="1.0"?> <xql:result query="//welcome-file-list/welcome-file" hitCount="3" elemCount="3" docCount="1" xmlns:xql="http://www.fatdog.com/ Summary_Listener.html"> <welcome-file xql:docID="0" xql:elemIx="270"/> <welcome-file xql:docID="0" xql:elemIx="271"/> <welcome-file xql:docID="0" xql:elemIx="272"/> </xql:result>
|
我前面也说过,对于我的应用程序来说,最重要的是返回使用逗号隔开的返回结果,所以CSV_LISTENER(3)就很有用了,它能够返回一个使用使用逗号隔开的结果,如下:
C:\xql\xql1>java Search web.xml 3 "//welcome-file-list/welcome-file" Parser.installSaxParser: <org.apache.xerces.parsers.SAXParser> installed successfully
1: indexing web.xml
Query: ( // ( / welcome-file-list welcome-file ) )
3 hit(s) for file://welcome-file-list/welcome-file
3,3,1,0 0,270,welcome-file 0,271,welcome-file 0,272,welcome-file
|
当然,XQEngine还有很多很强大的功能,在此我不可能一一介绍,它所附带的文档中有丰富的源程序和使用方法,你可以对照着自己学习使用,当然,如
果你愿意的话你甚至还可以开发出一个GUI程序,文档中就自带了一个基于GUI的搜索程序:SwingQueryDemo,你可以看一看研究研究。