More efficient way to parse an XML doc in Java using XPath

Ben00Golden
Ben00Golden used Ask the Experts™
on
I've written a piece of code that works. It uses XPath to extract some values in a XML doc and return each value, however it seems to be a very inefficient way to do it as I have to create new StringReader and InputSource objects for each value I want to read. I have tried re-using the InputSource object for each read, but then I get an error when trying to read the second value: java.io.IOException: Stream closed.

Is there a more efficient way to do this?
package com.xxxxx.myapi;
 
import javax.servlet.http.HttpSession;
 
import javax.xml.xpath.*;
import java.net.*;
import java.io.*;
import org.xml.sax.*;
 
/* SAMPLE XML:
        <myapi>
                <ERROR_CODE>0</ERROR_CODE>
                <ERROR_MESSAGE>SUCCESS</ERROR_MESSAGE>
                <PAN_LENGTH>16</PAN_LENGTH>
                <ISSUE_NR_LENGTH>0</ISSUE_NR_LENGTH>
                <START_DATE>N</START_DATE>
                <SCHEME_LETTER>V</SCHEME_LETTER>
                <SCHEME_NAME>Visa</SCHEME_NAME>
                <PROCESSING_REQUIREMENT>0</PROCESSING_REQUIREMENT>
                <CRM_PAYMENT_TYPE>VISA</CRM_PAYMENT_TYPE>
                <CREDIT_OR_DEBIT>CREDIT</CREDIT_OR_DEBIT>
                <CONTINUITY>CONTINUOUS</CONTINUITY>
        </myapi>
*/
 
public class myapi extends CallOutAction {
 
        protected String xmpCallOutExecute(HttpSession session, Object[] args)
        throws Exception {       
 
                String sXMLResponse = "";
 
        /* -----------------------------------------------------------------
           CODE HERE TO CALL HTTP API THAT RETURNS AN XML DOC IN A String OBJECT
           SIMILAR TO THAT SHOWN IN THE EXAMPLE ABOVE, THIS IS STORED IN
           sXMLResponse
           ----------------------------------------------------------------- */
 
                // DECODE RESPONSE
                try {
                        
                        // CREATE NEW INSTANCES OF XPATH FACTORY OBJECT
                        XPathFactory factory = XPathFactory.newInstance();
                        XPath XPathObject = factory.newXPath();                 
 
                        // COLLECT DATA FROM XML RESPONSE
                        setResult(session, outResultCode, getXMLValue(sXMLResponse, XPathObject, "/myapi/ERROR_CODE")); 
                        setResult(session, outErrorMessage, getXMLValue(sXMLResponse, XPathObject, "/myapi/ERROR_MESSAGE")); 
                        setResult(session, outCardLength, getXMLValue(sXMLResponse, XPathObject, "/myapi/PAN_LENGTH")); 
                        setResult(session, outIssueNumberLength, getXMLValue(sXMLResponse, XPathObject, "/myapi/ISSUE_NR_LENGTH")); 
                        setResult(session, outRequireStartDate, getXMLValue(sXMLResponse, XPathObject, "/myapi/START_DATE")); 
                        setResult(session, outSchemeLetter, getXMLValue(sXMLResponse, XPathObject, "/myapi/SCHEME_LETTER")); 
                        setResult(session, outSchemeName, getXMLValue(sXMLResponse, XPathObject, "/myapi/SCHEME_NAME")); 
                        setResult(session, outCreditDebit, getXMLValue(sXMLResponse, XPathObject, "/myapi/CREDIT_OR_DEBIT")); 
                        setResult(session, outContinuity, getXMLValue(sXMLResponse, XPathObject, "/myapi/CONTINUITY")); 
 
                                                                        
                } catch (Exception e) {
                log.error("MYAPI IDENTIFY FAILED [PARSE XML RESPONSE ERROR]: " + e.getMessage(), session);
                        return fwdFail;             
                }
                
                return fwdSuccess;                  
        }
        
        private String getXMLValue(String sXMLResponse, XPath XPathObject, String sXPath)
        throws XPathExpressionException {
                
                // CREATE INPUT SOURCE
                StringReader sr = new StringReader(sXMLResponse);
                InputSource isXML = new InputSource(sr);
                
                // CREATE XPATH EXPRESSION
                XPathExpression xpeExpr = XPathObject.compile(sXPath);
                
                // RETURN RESULT
                return xpeExpr.evaluate(isXML);
                        
        }
}

Open in new window

Comment
Watch Question

Do more with

Expert Office
EXPERT OFFICE® is a registered trademark of EXPERTS EXCHANGE®

Author

Commented:
No response... so increasing points!
Commented:
Well I'll try and help, but I don't do this sort of thing in Java nor with servlets.

If the number of documents is limited to (say) less than a hundred, I'd parse each document once into a DOM and use XPath on that. I'd put all the DOMs into some persistant storage (memory?) as a collection and just pick out the relevant dom each time for the request.

The time is going to be spent on reading the files and processing the characters. So better once than each time.

Do more with

Expert Office
Submit tech questions to Ask the Experts™ at any time to receive solutions, advice, and new ideas from leading industry professionals.

Start 7-Day Free Trial