/* * Copyright Aduna (http://www.aduna-software.com/) (c) 1997-2007. * * Licensed under the Aduna BSD-style license. */ package org.openrdf.query.resultio.sparqlxml; import static org.openrdf.query.resultio.sparqlxml.SPARQLResultsXMLConstants.BINDING_NAME_ATT; import static org.openrdf.query.resultio.sparqlxml.SPARQLResultsXMLConstants.BINDING_TAG; import static org.openrdf.query.resultio.sparqlxml.SPARQLResultsXMLConstants.BNODE_TAG; import static org.openrdf.query.resultio.sparqlxml.SPARQLResultsXMLConstants.LITERAL_DATATYPE_ATT; import static org.openrdf.query.resultio.sparqlxml.SPARQLResultsXMLConstants.LITERAL_LANG_ATT; import static org.openrdf.query.resultio.sparqlxml.SPARQLResultsXMLConstants.LITERAL_TAG; import static org.openrdf.query.resultio.sparqlxml.SPARQLResultsXMLConstants.RESULT_SET_TAG; import static org.openrdf.query.resultio.sparqlxml.SPARQLResultsXMLConstants.RESULT_TAG; import static org.openrdf.query.resultio.sparqlxml.SPARQLResultsXMLConstants.URI_TAG; import static org.openrdf.query.resultio.sparqlxml.SPARQLResultsXMLConstants.VAR_NAME_ATT; import static org.openrdf.query.resultio.sparqlxml.SPARQLResultsXMLConstants.VAR_TAG; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.List; import java.util.Map; import org.xml.sax.SAXException; import info.aduna.xml.SimpleSAXAdapter; import info.aduna.xml.SimpleSAXParser; import info.aduna.xml.XMLReaderFactory; import org.openrdf.model.Value; import org.openrdf.model.ValueFactory; import org.openrdf.model.impl.ValueFactoryImpl; import org.openrdf.query.TupleQueryResultHandlerException; import org.openrdf.query.impl.MapBindingSet; import org.openrdf.query.resultio.QueryResultParseException; import org.openrdf.query.resultio.TupleQueryResultFormat; import org.openrdf.query.resultio.TupleQueryResultParserBase; /** * Parser for reading tuple query results formatted as SPARQL Results Documents. * See <a href="http://www.w3.org/TR/rdf-sparql-XMLres/">SPARQL Query Results * XML Format</a> for the definition of this format. The parser assumes that * the XML is wellformed. */ public class SPARQLResultsXMLParser extends TupleQueryResultParserBase { /*-------------* * Construtors * *-------------*/ /** * Creates a new parser for the SPARQL Query Results XML Format that will use * an instance of {@link ValueFactoryImpl} to create Value objects. */ public SPARQLResultsXMLParser() { super(); } /** * Creates a new parser for the SPARQL Query Results XML Format that will use * the supplied ValueFactory to create Value objects. */ public SPARQLResultsXMLParser(ValueFactory valueFactory) { super(valueFactory); } /*---------* * Methods * *---------*/ public TupleQueryResultFormat getTupleQueryResultFormat() { return TupleQueryResultFormat.SPARQL; } public void parse(InputStream in) throws IOException, QueryResultParseException, TupleQueryResultHandlerException { try { SimpleSAXParser simpleSAXParser = new SimpleSAXParser(XMLReaderFactory.createXMLReader()); simpleSAXParser.setListener(new SPARQLResultsParser()); simpleSAXParser.parse(in); } catch (SAXException e) { Exception wrappedExc = e.getException(); if (wrappedExc instanceof QueryResultParseException) { throw (QueryResultParseException)wrappedExc; } else if (wrappedExc instanceof TupleQueryResultHandlerException) { throw (TupleQueryResultHandlerException)wrappedExc; } else { throw new QueryResultParseException(wrappedExc); } } } /*---------------------------------* * Inner class SPARQLResultsParser * *---------------------------------*/ private class SPARQLResultsParser extends SimpleSAXAdapter { /*-----------* * Variables * *-----------*/ /** * The variable names that are specified in the header. */ private List<String> bindingNames; /** * The most recently parsed binding name. */ private String currentBindingName; /** * The most recently parsed value. */ private Value currentValue; /** * The bound variables for the current result. */ private MapBindingSet currentSolution; /*---------* * Methods * *---------*/ @Override public void startDocument() throws SAXException { bindingNames = new ArrayList<String>(); currentValue = null; } @Override public void endDocument() throws SAXException { try { handler.endQueryResult(); } catch (TupleQueryResultHandlerException e) { throw new SAXException(e); } } @Override public void startTag(String tagName, Map<String, String> atts, String text) throws SAXException { if (BINDING_TAG.equals(tagName)) { currentBindingName = atts.get(BINDING_NAME_ATT); if (currentBindingName == null) { throw new SAXException(BINDING_NAME_ATT + " attribute missing for " + BINDING_TAG + " element"); } } else if (URI_TAG.equals(tagName)) { try { currentValue = valueFactory.createURI(text); } catch (IllegalArgumentException e) { // Malformed URI throw new SAXException(e.getMessage()); } } else if (BNODE_TAG.equals(tagName)) { currentValue = valueFactory.createBNode(text); } else if (LITERAL_TAG.equals(tagName)) { String xmlLang = atts.get(LITERAL_LANG_ATT); String datatype = atts.get(LITERAL_DATATYPE_ATT); if (datatype != null) { try { currentValue = valueFactory.createLiteral(text, valueFactory.createURI(datatype)); } catch (IllegalArgumentException e) { // Illegal datatype URI throw new SAXException(e.getMessage()); } } else if (xmlLang != null) { currentValue = valueFactory.createLiteral(text, xmlLang); } else { currentValue = valueFactory.createLiteral(text); } } else if (RESULT_TAG.equals(tagName)) { currentSolution = new MapBindingSet(bindingNames.size()); } else if (VAR_TAG.equals(tagName)) { String varName = atts.get(VAR_NAME_ATT); if (varName == null) { throw new SAXException(VAR_NAME_ATT + " missing for " + VAR_TAG + " element"); } bindingNames.add(varName); } else if (RESULT_SET_TAG.equals(tagName)) { try { handler.startQueryResult(bindingNames); } catch (TupleQueryResultHandlerException e) { throw new SAXException(e); } } } @Override public void endTag(String tagName) throws SAXException { if (BINDING_TAG.equals(tagName)) { if (currentValue == null) { throw new SAXException("Value missing for " + BINDING_TAG + " element"); } currentSolution.addBinding(currentBindingName, currentValue); currentBindingName = null; currentValue = null; } else if (RESULT_TAG.equals(tagName)) { try { handler.handleSolution(currentSolution); currentSolution = null; } catch (TupleQueryResultHandlerException e) { throw new SAXException(e); } } } } }