In my organizations we use xslt 1.0 with xpath 1.0 in order to make big xml transformations. But now we need to make migration.
I am using VTD-XML to parse and transform a huge xml 200MB and I have over 20 xpath selects so for each of them I want to define:
AutoPilot relationAutoPilot = new AutoPilot();
relationsautoPilot.selectXPath("object[@class='Example']");
AutoPilot first= new AutoPilot();
first.selectXPath("other");
....
public void methodCalulate(final VTDNav partAutoPilot, final AutoPilot partAutoPilot, final AutoPilot first, final AutoPilot second,final AutoPilot third,final AutoPilot fourth) {
navigator.push();
partAutoPilot.bind(navigator);
while ((i = partAutoPilot.evalXPath()) != -1) {
...
method3(navigator,first,second,third,fourth);
..
}
method3(final VTDNav navigator,final AutoPilot first, final AutoPilot second,final AutoPilot third,final AutoPilot fourth) {
navigator.push();
first.bind(navigator);
int i = -1;
while ((i = first.evalXPath()) != -1) {
//Do some buissiness logic
method2(navigator,second,third,fourth);
..
}
}
So I tried to put them in the top of the method hierarchy not in while ,for-each and so on so to be able to spend less processor speed and memory, but have a problem. I am wondering how to pass the objects because:
Simple case
public void methodCalculate(final VTDNav navigator, final AutoPilot partAutoPilot)
OK one AutoPilot ok.
MoreComplex case methodCalculate calls method3->calls method2->calls method 1
public void methodCalculate(final VTDNav navigator, final AutoPilot partAutoPilot, final AutoPilot first,final AutoPilot second,final AutoPilot third,final AutoPilot fourth){
method3(navigator,first,second,third,fourth);
}
public void method3(final VTDNav navigator,final AutoPilot second,final AutoPilot third,final AutoPilot fourth){
method2(navigator,second,third,fourth);
}
....
and every method needs sub select with relative xpath so I need to pass 4 AutoPilots even if there is new rules for the transformation other method_0 can come and I need to add additional AutoPilot. So I am wondering how to proceed in this situation? How to pass AutoObjects more efficiently, because they consume a lot of memory and their calculation is very expensive?
What I try? I put extract the AutoPilot from the top most levels in the method where methodCalulate is called so they are create once. And in methodCalulate create other AutoPilots. It improves the speed but on the next inline calls creating AutoPilots create the performance hell.
Edit: I can add List with AutoPilots, even map and a constant class for key to search the proper AutoPilot for given select. I do not know what is best option here.
AutoPilot compilation should happen outside a loop... but it doesn't consume a lot of memory... you can probably put all autoPilot object in a hash table and use the xpath string as hash key...
As you probably noticed, vtd-xml's xpath evaluation takes place in a loop, which is very different from DOM. While this may be a bit difficult to get used to... it has a lot of merits/benefits in achieving superior performance and low memory usage.
Also for simple xpath, such as those involving one child tag lookup, you can forgo the xpath, and instead base your app logic on the cursor directly... the same rules apply: make sure the cursor position going into a piece of app logic remains unchanged upon leaving that code block.
So you have a couple of options: the most common is push pop(). But for a simple child lookup, after calling toElement(FirstChild) all you have to do is call toElement(Parent) to return to the starting location.