Today we
would talk about common used XML parsers available in Java. They are:
1) DOM
2) STAX
3) SAX
Sample XML
file:
<?xml version="1.0"?><TDRS><TDR><Date>2011-12-6</Date><Time>18:38:1.47</Time><Timestamp>1323196681047</Timestamp><SystemID>TE06</SystemID><TransactionID>425425678</TransactionID><CorrelationID>none</CorrelationID><SCFTransID></SCFTransID><DeveloperApplication></DeveloperApplication><Company></Company><AppId></AppId><Environment></Environment><Bundle></Bundle><AuthMethod></AuthMethod><AuthToken></AuthToken><HTTPMethod>GET</HTTPMethod><APIType></APIType><SLT></SLT><API></API><APIAction>/</APIAction><SOAPAction></SOAPAction><ClientRequestTimestamp>0</ClientRequestTimestamp><APIAppTimestamp>1323196681040</APIAppTimestamp><APITargetRequestTimestamp>0</APITargetRequestTimestamp><APITargetResponseTimestamp>0</APITargetResponseTimestamp><ClientResponseTimestamp>0</ClientResponseTimestamp><Cached>0</Cached><EventType>Error</EventType><ClientEndpoint></ClientEndpoint><ClientIP>10.155.1.233</ClientIP><LocalIP></LocalIP><LocalPort>23394</LocalPort><TargetEndPoint></TargetEndPoint><TargetIP></TargetIP><StatusCode></StatusCode><ProviderCode></ProviderCode><HTTPStatusCode>403</HTTPStatusCode><Multiplier></Multiplier><Cost></Cost><QuotaAction></QuotaAction><OverQuota>0</OverQuota><OverDayQuota>0</OverDayQuota><OverWeekQuota>0</OverWeekQuota><OverMonthQuota>0</OverMonthQuota><PayloadSize>0</PayloadSize><TDRIdentifier>426561727188bae37b32990ee41</TDRIdentifier></TDR></TDRS>
1) DOM
Parser
§
It parses an entire XML document and load it into
memory, modeling it with Object for easy traversal or manipulation.
§
Once the XML loaded in the memory then user can
traverse in any direction i.e. forward or backward.
§
DOM Parser is slow and consume a lot of memory if it
load a XML document which contains a lot of data, So should be used for specific purpose (Traversing) only
I.
DOM Parsing Only
private int domParsing (final String filename) throws SAXException, IOException, JaxenException {
final int Records = 0; final
String textfile = FileUtils.readFileToString(new File (filename)); if ((this.dbf == null) || (this.db == null)) { this.dbf = DocumentBuilderFactory.newInstance (); try { this.db = this.dbf.newDocumentBuilder (); } catch (final ParserConfigurationException e) { } }
if ((this.dbf != null) && (this.db != null)) { this.doc = this.db.parse (new InputSource (new StringReader (textfile))); this.doc.getDocumentElement ().normalize ();// final Element e = this.doc.getDocumentElement ();
final List <Node> tdrNodes = new DOMXPath ("TDRS").selectNodes (this.doc); Long time = 0L; for (int nodeIdx = 0; nodeIdx < tdrNodes.size (); ++nodeIdx) { final Node tdrNode = tdrNodes.get (nodeIdx); while (tdrNode.hasChildNodes ()) { final StringBuffer sb = new StringBuffer (); final Node childNode = tdrNode.getFirstChild (); tdrNode.removeChild (childNode); if (childNode.getNodeType () != 1) { continue; } final Long start = System.currentTimeMillis (); sb.append (childNode.getNodeName () + ":" + childNode.getNodeValue () + ";");
while (childNode.hasChildNodes ()) {
final Node grandchildNode = childNode.getFirstChild (); sb.append (grandchildNode.getNodeName () + ":" + grandchildNode.getTextContent () + ";"); childNode.removeChild (grandchildNode); }
System.out.println (childNode.getNodeName () + "::" + sb.toString ()); final Long end = System.currentTimeMillis (); time = time + (end - start); // System.out.println ("Time::" + (end - start) + " Map::" + params); } System.out.println ("Total Dom Time:" + time); } } return Records;}
The output
is:
TDR::TDR:null;Date:2011-12-6;Time:18:38:1.47;Timestamp:1323196681047;SystemID:TE06;TransactionID:425425678;CorrelationID:none;SCFTransID:;DeveloperApplication:;Company:;AppId:;Environment:;Bundle:;AuthMethod:;AuthToken:;HTTPMethod:GET;APIType:;SLT:;API:;APIAction:/;SOAPAction:;ClientRequestTimestamp:0;APIAppTimestamp:1323196681040;APITargetRequestTimestamp:0;APITargetResponseTimestamp:0;ClientResponseTimestamp:0;Cached:0;EventType:Error;ClientEndpoint:;ClientIP:10.155.1.233;LocalIP:;LocalPort:23394;TargetEndPoint:;TargetIP:;StatusCode:;ProviderCode:;HTTPStatusCode:403;Multiplier:;Cost:;QuotaAction:;OverQuota:0;OverDayQuota:0;OverWeekQuota:0;OverMonthQuota:0;PayloadSize:0;TDRIdentifier:426561727188bae37b32990ee41;
II.
DOM Validation with external XSD
private boolean validateDOM
(final String xmlFile,
final String xsdFile) {
final DocumentBuilderFactory factory =
DocumentBuilderFactory.newInstance
();
factory.setValidating (false);
factory.setNamespaceAware (true);
final SchemaFactory schemaFactory = SchemaFactory.newInstance ("http://www.w3.org/2001/XMLSchema");
try {
factory.setSchema
(schemaFactory.newSchema (new Source[] {new StreamSource (xsdFile)}));
final DocumentBuilder builder = factory.newDocumentBuilder
();
builder.setErrorHandler (new ErrorHandler () {
@Override
public void warning (final SAXParseException arg0) throws SAXException {
// TODO Auto-generated method stub
try {
throw new Exception ();
} catch (final Exception e) {
// TODO Auto-generated catch block
e.printStackTrace ();
}
}
@Override
public void fatalError (final SAXParseException arg0) throws SAXException {
// TODO Auto-generated method stub
}
@Override
public void error (final SAXParseException arg0) throws SAXException {
// TODO Auto-generated method stub
}
});
final Document document = builder.parse (new InputSource (xmlFile));
} catch (final SAXException e)
{
e.printStackTrace ();
return false;
} catch (final
ParserConfigurationException e) {
e.printStackTrace ();
return false;
} catch (final IOException e)
{
e.printStackTrace ();
return false;
}
return true;
}
2) STAX
Parser – A Pull Parser
§
It’s a Pull Parser
§
Events are generated by the
parsing application, thus providing parsing regulation to the client, rather
than the parser
§
Developer can control the
parsing i.e. you
can suspend parsing, skip elements while parsing, and parse multiple documents
§
Parsing events gets generated as the XML document gets parsed
I.
STAX Parsing Only
private void staxParsing (final String filename) {
try {
final FileInputStream fis = new FileInputStream (filename);
// URL u = new
URL(filename);
// InputStream
in = u.openStream();
final XMLInputFactory factory = XMLInputFactory.newInstance ();
final XMLStreamReader parser =
factory.createXMLStreamReader (fis);
HashMap <String,
ValueTypePair> params = null;
String NodeName = null;
Class NodeType = null;
for (int event =
parser.next (); event != XMLStreamConstants.END_DOCUMENT; event = parser.next ()) {
switch (event) {
case XMLStreamConstants.START_ELEMENT:
//
System.out.println (parser.getLocalName ());
if ((parser.getLocalName () != null) && parser.getLocalName
().equalsIgnoreCase ("TDR")) {
params = new HashMap <String, ValueTypePair> ();
}
final int iIndex = this.alBillingXPaths.indexOf
(parser.getLocalName ());
if (iIndex < 0) {
break;
}
NodeName = this.alBillingColumns.get (iIndex);
NodeType = this.alBillingClasses.get (iIndex);
break;
case XMLStreamConstants.END_ELEMENT:
if ((parser.getLocalName () != null) && parser.getLocalName
().equalsIgnoreCase ("TDR")) {
//
System.out.println (params);
}
break;
case XMLStreamConstants.CHARACTERS:
if ((NodeName != null) && (params != null)) {
params.put
(NodeName, new ValueTypePair
(parser.getText (), NodeType));
}
break;
case XMLStreamConstants.CDATA:
if ((NodeName != null) && (params != null)) {
params.put
(NodeName, new ValueTypePair
(parser.getText (), NodeType));
}
break;
}
}
parser.close ();
} catch (final
XMLStreamException ex) {
System.out.println (ex);
} catch (final IOException ex)
{
System.out.println ("IOException
while parsing " + filename);
ex.printStackTrace
();
}
}
II.
STAX Validation
STAX Does not support Validation, which acts as its drawback.
3) SAX
Parser – A Push Parser
§
SAX Parser is a push parser
§
it’s parser which call the
code & user don’t have full control over it
§
User can not stop the
parsing in between
§
Its supports XSD validation
I.
SAX Parsing Only
private static void saxParsing (final String filename) {
try {
final SAXParserFactory factory = SAXParserFactory.newInstance ();
final SAXParser saxParser = factory.newSAXParser ();
final DefaultHandler handler = new DefaultHandler () {
@Override
public void startElement (final String uri,
final String localName,
final String qName,
final Attributes attributes) throws SAXException {
}
@Override
public void endElement (final String uri, final String localName, final String qName) throws SAXException {
}
@Override
public void characters (final char ch[], final int start, final int length) throws SAXException {
}
};
saxParser.parse (filename,
handler);
} catch (final Exception e) {
e.printStackTrace ();
}
System.out.println ("SAX Parsing ends");
}
II.
SAX Validation & Parsing
private static boolean validateSAX (final String xmlFile, final String xsdFile) {
final SAXParserFactory factory = SAXParserFactory.newInstance ();
factory.setValidating (false);
factory.setNamespaceAware (true);
final SchemaFactory schemaFactory = SchemaFactory.newInstance ("http://www.w3.org/2001/XMLSchema");
try {
if (xsdFile != null) {
factory.setSchema
(schemaFactory.newSchema (new Source[] {new StreamSource (xsdFile)}));
}
final SAXParser parser = factory.newSAXParser ();
final XMLReader reader = parser.getXMLReader ();
reader.setErrorHandler (new ErrorHandler () {
@Override
public void warning (final SAXParseException arg0) throws SAXException {
// TODO Auto-generated method stub
try {
System.err.println ("warning::" + arg0);
throw new Exception ();
} catch (final Exception e) {
// TODO Auto-generated catch block
e.printStackTrace ();
}
}
@Override
public void fatalError (final SAXParseException arg0) throws SAXException {
// TODO Auto-generated
method stub
System.err.println ("fatal
Error::" + arg0);
}
@Override
public void error (final SAXParseException arg0) throws SAXException {
// TODO Auto-generated method stub
System.err.println ("Error::" +
arg0.getMessage ());
}
});
reader.parse (new InputSource (xmlFile));
} catch (final SAXException e)
{
e.printStackTrace ();
return false;
} catch (final
ParserConfigurationException e) {
e.printStackTrace ();
return false;
} catch (final IOException e)
{
e.printStackTrace ();
return false;
}
System.out.println ("SAX Parsing ends");
return true;
}
4) Analysis
The
xml file is first being validated using the xsd file & then forwarded for
parsing, the parsing results are as
(result are generated by doing parsing through eclipse having a hepsize of 512 mb )
SNo.
|
# TDRS Nodes
|
Time: Dom Parser (ms)
|
Time: Stax Parser
(ms)
|
Time: SAX Parser
(ms)
|
1
|
10,000
|
6866
|
500
|
469
|
2
|
25,000
|
Out of Memory
|
1234
|
1118
|
3
|
50,000
|
Out of Memory
|
2422
|
2328
|
4
|
1,00,000
|
Out of Memory
|
4906
|
4672
|
Hence we
conclude that SAX & STAX parsers are much more efficient than the DOM
parsers & should be used if to & fro navigation not required in the XML