In an earlier post of mine I had given an example of how to use VTD Xml.We could run into requirements where in we would like to use VTD xml in a multi threaded application.This post provides a working example for integrating VTD xml in a multi threaded application.
The requirement: I have large number of XPATHs that need to be resolved.Due to large number of XPATHS,our application may slow down.So the better way would be to resolve XPATHs in multiple threads.
In the below code an important point that needs to be noted is that after parsing the xml using VTDGen,we store the navigator in a variable by invoking GetNav()
.The GetNav()
call cleans internal state , so we should keep a copy of navigator and pass the “duplicate” of navigator object to each task.
import java.io.File; import java.util.*; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; import com.ximpleware.AutoPilot; import com.ximpleware.EOFException; import com.ximpleware.EncodingException; import com.ximpleware.EntityException; import com.ximpleware.ParseException; import com.ximpleware.VTDGen; import com.ximpleware.VTDNav; public class MultiThread { public static void main(String args[]) throws InterruptedException, ExecutionException, EncodingException, EOFException, EntityException, ParseException { //str contains the sample xml, one can read an xml from a file as well String str="<library><booked>book</booked> <book id=\"1\"> <title>Googled By God</title> </book> </library>"; //Create 5 threads ExecutorService executor = Executors.newFixedThreadPool(5); List<Task> extractorTasks = new ArrayList<Task>(); //Create VTDGen object and parse the xml VTDGen vg = new VTDGen(); vg.setDoc(str.getBytes()); vg.parse(false); //The GetNav() call cleans internal state , so keep a copy of VTDNav VTDNav vn = vg.getNav(); //Create 100 tasks and queue them for(int i=0;i<100;i++) { //pass the duplicates of navigator. //To all my threads I am passing the same xpath, but one might read the list //of xpaths from a file Task d = new Task(str.getBytes(),vn.duplicateNav(),"/library/book/title"); extractorTasks.add(d); } List<Future<String>> output = executor.invokeAll(extractorTasks); executor.shutdown(); } } class Task implements Callable<String> { String xpath = ""; //ba is the byte array byte [] ba=null; VTDNav vn = null; AutoPilot ap = null; Task(byte[] _ba,VTDNav _vn,String _xpath) { ba = _ba; vn = _vn; xpath = _xpath; } public String call() throws Exception { String title = ""; try { ap = new AutoPilot(vn); ap.selectXPath(xpath); //Get all the titles and print each of those while(ap.evalXPath() != -1) { //getText will return the index of the VTDRecord int titleIndex = vn.getText(); //Get the text of the VTDRecord title = vn.toNormalizedString(titleIndex); System.out.println("Title is "+title); } } catch (Exception e) { e.printStackTrace(); System.out.println("Exception Message is "+e.getMessage()); } return title; } }