0
<RmtInf>
    <Strd>
        <RfrdDocInf>
            <Tp>
                <CdOrPrtry>
                    <Cd>CINV</Cd>
                </CdOrPrtry>
            </Tp>
            <Nb>3501870</Nb>
        </RfrdDocInf>
        <RfrdDocInf>
            <Tp>
                <CdOrPrtry>
                    <Prtry>AGJ</Prtry>
                </CdOrPrtry>
            </Tp>
            <Nb>10090187000155438</Nb>
        </RfrdDocInf>
        <RfrdDocAmt>
            <DuePyblAmt Ccy="SEK">5453.29</DuePyblAmt>
        </RfrdDocAmt>
    </Strd>
    <Strd>
        <RfrdDocInf>
            <Tp>
                <CdOrPrtry>
                    <Cd>CINV</Cd>
                </CdOrPrtry>
            </Tp>
            <Nb>160120</Nb>
        </RfrdDocInf>
        <RfrdDocInf>
            <Tp>
                <CdOrPrtry>
                    <Prtry>AGJ</Prtry>
                </CdOrPrtry>
            </Tp>
            <Nb>10090187000155438</Nb>
        </RfrdDocInf>
        <AddtlRmtInf>/ARI/</AddtlRmtInf>
    </Strd>
</RmtInf>   
 while (ap.evalXPath() != -1)
    {
    if (vn.toElement(VTDNav.FIRST_CHILD, "AmtDtls")) {

    do {
        amtDetails = getXpathValue(vn, ".//TxAmt/Amt/text()");
        // System.out.println("amtDetails:::" + amtDetails);
        if (amtDetails != null)
            creditNotification.setAmount(new BigDecimal(amtDetails));
    } while (vn.toElement(VTDNav.NEXT_SIBLING, "AmtDtls"));

    }   

        vn.push();

        // System.out.println("transIndex::" + transIndex);
        ap1.selectXPath("/Document/BkToCstmrDbtCdtNtfctn/Ntfctn/Ntry/NtryDtls/TxDtls[" + transIndex
                + "]/RmtInf/Strd");

        while (ap1.evalXPath() != -1) {
            // System.out.println("sCount::::"+sCount);
            custInvType = getXpathValue(vn, "RfrdDocInf[1]/Tp/CdOrPrtry/Cd/text()");
            // System.out.println("custInvType:::" + custInvType);
            creditNotificationFlag = false;
            if (custInvType != null
                    && custInvType.equalsIgnoreCase(IBS2BankConstants.TYPE_DEBITCREDITNOTIFICATION_CINV)) {
                kidNmbr = getXpathValue(vn, "RfrdDocInf[1]/Nb/text()");
                // System.out.println("\tskidNmbr::::" + kidNmbr);
                // added as an required by IBS team
                creditNotification.setMemo3(kidNmbr);

                if (kidNmbr != null) {
                    creditNotification.setKid(kidNmbr);

                    if (kidNmbr.matches("^\\d{18}")) {
                        creditNotification
                                .setCustomerNumber(IBS2BankUtility.getKidsCustomerNumber(kidNmbr));

                        // logger.debug("custNumber:::" +
                        // custNumber);
                        creditNotification.setInvoiceNumber(IBS2BankUtility.getKidsInvoiceNumber(kidNmbr));
                        // logger.debug("custInvoice:::" +
                        // custInvoice);
                    } else if (kidNmbr.matches("^\\d{10}")) {

                        creditNotification.setInvoiceNumber(IBS2BankUtility.getKidsInvoiceNumber(kidNmbr));

                    }
                }

            }

            String prtryCodeType = getXpathValue(vn, "RfrdDocInf[2]/Tp/CdOrPrtry/Prtry/text()");
            // System.out.println("prtryCodeType :::" +
            // prtryCodeType);
            if (prtryCodeType != null
                    && prtryCodeType.equalsIgnoreCase(IBS2BankConstants.PROPRIETARY_CODE_AGJ)) {
                // added as an required by IBS team
                creditNotification.setMemo4(getXpathValue(vn, "RfrdDocInf[2]/Nb/text()"));
            }

            credNotificationList.add(creditNotification);

        }
        ap1.resetXPath();

        vn.pop();

    }

I have updated the xml and the code Push() is use to save the state of current location, the second while is used because RmtInf has multiple Strd and I want to traverse through it. Now the above code works but it takes a lot of time to parse xml with file size is 600 MB.

vtd-xml-author
  • 3,319
  • 4
  • 22
  • 30

1 Answers1

0

First of all, your document's nesting level is quite deep, if you do a large # of xpaths, I suggest you turn on VTDGen's set LC level method and set it to 5 (the default is 3)...

Because your doc is significantly less than the 2GB limit, consider switching to standard vtd-xml (do you have around 1GB memory available?). It is better tuned for performance although it doesn't have memory mapping capability.

To select deeper index level, call VTDGen's selectLcDepth(int i) and set i to 5.

Another thing I noticed is that in your code

getXpathValue(vn, ".//TxAmt/Amt/text())

I would suggest that you move the select xpath expression logic outta the xpath evaluation loop, and instead do the xpath compilation in the code preceding the loop... and it would look something like ...

   Autopilot ap_temp = new AutoPilot(vn);
    ap_tmp.selectXPath("..//TxAmt/Amt/text()");
    ...
    int i=-1;
    while((i=ap.evalXPath())!=-1){

       ...
       //amtDetails = getXpathValue(vn, ".//TxAmt/Amt/text()"); will be replaced by
       amtDetails = getXpathValue(vn, ap_temp);

Also if amtDetails is a string, you can something like evalXPathToString() directly that you can directly convert the output to a string...

Your code has multiple selectXPath, which I suspect kills the performance, you should try taking them out of the loop ...

I wrote a blog on this a while back...https://ximpleware.wordpress.com/2015/10/12/performance-tuning/

the position of push and pop seems to be wrong. Specifically, push() should precede immediately to the code in the main logic... I am very surprised that your code works as you indicated...

Have you noticed that you have two huge XPath evaluation loops nested in each other?? This does not look good...

Overall, I think you have created a piece of code designed to run very very inefficiently.

That is my suggestion for now...

Look forward to your thoughts and comments.

To get the code working, you need to use vtd-xml cursor inside the loop... I assume that you are also aware that you need to maintain the node position inside the while loop so to not affect the correctness of xpath evaluation...

your code will probably look something like this...

VTDNav vn = vg.getNav();
...
while (ap.evalXPath() != -1) { 

     if (vn.toElement(VTDNav.FIRSTCHILD)){
              System.out.println(" node name ===>"+vn.toRawString(vn.getCurrentIndex()));
              vn.toElement(VTDNav.PARENT);
     }
} 
vtd-xml-author
  • 3,319
  • 4
  • 22
  • 30