Index: SRUClient/trunk/src/main/java/eu/clarin/sru/client/SRUAbstractRequest.java
===================================================================
--- SRUClient/trunk/src/main/java/eu/clarin/sru/client/SRUAbstractRequest.java	(revision 6080)
+++ SRUClient/trunk/src/main/java/eu/clarin/sru/client/SRUAbstractRequest.java	(revision 6903)
@@ -34,26 +34,40 @@
  */
 abstract class SRUAbstractRequest {
-    static final String PARAM_OPERATION                = "operation";
-    static final String PARAM_VERSION                  = "version";
-    static final String PARAM_RECORD_PACKING           = "recordPacking";
-    static final String PARAM_STYLESHEET               = "stylesheet";
-    static final String PARAM_QUERY                    = "query";
-    static final String PARAM_START_RECORD             = "startRecord";
-    static final String PARAM_MAXIMUM_RECORDS          = "maximumRecords";
-    static final String PARAM_RECORD_SCHEMA            = "recordSchema";
-    static final String PARAM_RECORD_X_PATH            = "recordXPath";
-    static final String PARAM_RESULT_SET_TTL           = "resultSetTTL";
-    static final String PARAM_SORT_KEYS                = "sortKeys";
-    static final String PARAM_SCAN_CLAUSE              = "scanClause";
-    static final String PARAM_RESPONSE_POSITION        = "responsePosition";
-    static final String PARAM_MAXIMUM_TERMS            = "maximumTerms";
-    static final String RECORD_PACKING_XML             = "xml";
-    static final String RECORD_PACKING_STRING          = "string";
-    private static final String OP_EXPLAIN             = "explain";
-    private static final String OP_SCAN                = "scan";
-    private static final String OP_SEARCH_RETRIEVE     = "searchRetrieve";
-    private static final String VERSION_1_1            = "1.1";
-    private static final String VERSION_1_2            = "1.2";
-    private static final String PARAM_EXTENSION_PREFIX = "x-";
+    /* general / explain related parameter names */
+    protected static final String PARAM_OPERATION            = "operation";
+    protected static final String PARAM_VERSION              = "version";
+    protected static final String PARAM_STYLESHEET           = "stylesheet";
+    protected static final String PARAM_RENDER_BY            = "renderedBy";
+    protected static final String PARAM_HTTP_ACCEPT          = "httpAccept";
+    protected static final String PARAM_RESPONSE_TYPE        = "responseType";
+    /* searchRetrieve related parameter names */
+    protected static final String PARAM_QUERY                = "query";
+    protected static final String PARAM_QUERY_TYPE           = "queryType";
+    protected static final String PARAM_START_RECORD         = "startRecord";
+    protected static final String PARAM_MAXIMUM_RECORDS      = "maximumRecords";
+    protected static final String PARAM_RECORD_XML_ESCAPING  = "recordXMLEscaping";
+    protected static final String PARAM_RECORD_PACKING       = "recordPacking";
+    protected static final String PARAM_RECORD_SCHEMA        = "recordSchema";
+    protected static final String PARAM_RECORD_X_PATH        = "recordXPath";
+    protected static final String PARAM_RESULT_SET_TTL       = "resultSetTTL";
+    protected static final String PARAM_SORT_KEYS            = "sortKeys";
+    /* scan related parameter names */
+    protected static final String PARAM_SCAN_CLAUSE          = "scanClause";
+    protected static final String PARAM_RESPONSE_POSITION    = "responsePosition";
+    protected static final String PARAM_MAXIMUM_TERMS        = "maximumTerms";
+    /* operations */
+    protected static final String OP_EXPLAIN                 = "explain";
+    protected static final String OP_SCAN                    = "scan";
+    protected static final String OP_SEARCH_RETRIEVE         = "searchRetrieve";
+    protected static final String VERSION_1_1                = "1.1";
+    protected static final String VERSION_1_2                = "1.2";
+    /* various parameter values */
+    protected static final String RECORD_XML_ESCAPING_XML    = "xml";
+    protected static final String RECORD_XML_ESCPAING_STRING = "string";
+    protected static final String RECORD_PACKING_PACKED      = "packed";
+    protected static final String RECORD_PACKING_UNPACKED    = "unpacked";
+    protected static final String RENDER_BY_CLIENT           = "client";
+    protected static final String RENDER_BY_SERVER           = "server";
+    protected static final String PARAM_EXTENSION_PREFIX = "x-";
     /** for end-point conformance testing only. never use in production. */
     public static final String X_MALFORMED_OPERATION   =
@@ -220,5 +234,5 @@
      * Get the version for this request.
      *
-     * @return version for this request or <code>null</code> of client default
+     * @return version for this request or <code>null</code> if client default
      *         is used
      */
@@ -347,66 +361,88 @@
                     new URIHelper(new URIBuilder(baseURI));
 
-            /*
-             * append operation parameter
-             *
-             * NB: Setting "x-malformed-operation" as an extra request parameter
-             * makes the client send invalid requests. This is intended to
-             * use for testing SRU servers for protocol conformance (i.e.
-             * provoke an error) and SHOULD NEVER be used in production!
-             */
-            final String malformedOperation =
-                    getExtraRequestData(X_MALFORMED_OPERATION);
-            if (malformedOperation == null) {
-                switch (getOperation()) {
-                case EXPLAIN:
-                    uriBuilder.append(PARAM_OPERATION, OP_EXPLAIN);
-                    break;
-                case SCAN:
-                    uriBuilder.append(PARAM_OPERATION, OP_SCAN);
-                    break;
-                case SEARCH_RETRIEVE:
-                    uriBuilder.append(PARAM_OPERATION, OP_SEARCH_RETRIEVE);
-                    break;
-                default:
-                    throw new SRUClientException("unsupported operation: " +
-                            getOperation());
-                } // switch
-            } else {
-                if (!malformedOperation.equals(MALFORMED_OMIT)) {
-                    uriBuilder.append(PARAM_OPERATION, malformedOperation);
+            /* store the version, we use for this request */
+            versionRequested = (version != null) ? version : defaultVersion;
+
+            switch (versionRequested) {
+            case VERSION_1_1:
+                /* $FALL-THROUGH$ */
+            case VERSION_1_2:
+                /*
+                 * append operation parameter
+                 *
+                 * NB: Setting "x-malformed-operation" as an extra request parameter
+                 * makes the client send invalid requests. This is intended to
+                 * use for testing SRU servers for protocol conformance (i.e.
+                 * provoke an error) and SHOULD NEVER be used in production!
+                 */
+                final String malformedOperation =
+                        getExtraRequestData(X_MALFORMED_OPERATION);
+                if (malformedOperation == null) {
+                    switch (getOperation()) {
+                    case EXPLAIN:
+                        uriBuilder.append(PARAM_OPERATION, OP_EXPLAIN);
+                        break;
+                    case SCAN:
+                        uriBuilder.append(PARAM_OPERATION, OP_SCAN);
+                        break;
+                    case SEARCH_RETRIEVE:
+                        uriBuilder.append(PARAM_OPERATION, OP_SEARCH_RETRIEVE);
+                        break;
+                    default:
+                    } // switch
+                } else {
+                    if (!malformedOperation.equals(MALFORMED_OMIT)) {
+                        uriBuilder.append(PARAM_OPERATION, malformedOperation);
+                    }
                 }
-            }
-
-            /*
-             * append version parameter
-             *
-             * NB: Setting "x-malformed-version" as an extra request parameter
-             * makes the client send invalid requests. This is intended to
-             * use for testing SRU servers for protocol conformance (i.e.
-             * provoke an error) and SHOULD NEVER be used in production!
-             */
-            final String malformedVersion =
-                    getExtraRequestData(X_MALFORMED_VERSION);
-            if (malformedVersion == null) {
-                versionRequested = (version != null) ? version : defaultVersion;
-                switch (versionRequested) {
-                case VERSION_1_1:
-                    uriBuilder.append(PARAM_VERSION, VERSION_1_1);
-                    break;
-                case VERSION_1_2:
-                    uriBuilder.append(PARAM_VERSION, VERSION_1_2);
-                    break;
-                default:
-                    throw new SRUClientException("unsupported version: " +
-                            versionRequested);
-                } // switch
-            } else {
-                if (!malformedVersion.equalsIgnoreCase(MALFORMED_OMIT)) {
-                    uriBuilder.append(PARAM_VERSION, malformedVersion);
+
+                /*
+                 * append version parameter
+                 *
+                 * NB: Setting "x-malformed-version" as an extra request parameter
+                 * makes the client send invalid requests. This is intended to
+                 * use for testing SRU servers for protocol conformance (i.e.
+                 * provoke an error) and SHOULD NEVER be used in production!
+                 */
+                final String malformedVersion =
+                        getExtraRequestData(X_MALFORMED_VERSION);
+                if (malformedVersion == null) {
+                    versionRequested = (version != null) ? version : defaultVersion;
+                    switch (versionRequested) {
+                    case VERSION_1_1:
+                        uriBuilder.append(PARAM_VERSION, VERSION_1_1);
+                        break;
+                    case VERSION_1_2:
+                        uriBuilder.append(PARAM_VERSION, VERSION_1_2);
+                        break;
+                    default:
+                        throw new SRUClientException("unsupported version: " +
+                                versionRequested);
+                    } // switch
+                } else {
+                    if (!malformedVersion.equalsIgnoreCase(MALFORMED_OMIT)) {
+                        uriBuilder.append(PARAM_VERSION, malformedVersion);
+                    }
                 }
+                break;
+            case VERSION_2_0:
+                if (getExtraRequestData(X_MALFORMED_OPERATION) != null) {
+                    throw new SRUClientException("parameter '" +
+                            X_MALFORMED_OPERATION +
+                            "' is not supported when using version 2.0");
+                }
+                if (getExtraRequestData(X_MALFORMED_VERSION) != null) {
+                    throw new SRUClientException("parameter '" +
+                            X_MALFORMED_VERSION +
+                            "' is not supported when using version 2.0");
+                }
+                break;
+            default:
+                throw new SRUClientException("unsupported version: " +
+                        versionRequested);
             }
 
             // request specific parameters
-            addParametersToURI(uriBuilder);
+            addParametersToURI(uriBuilder, versionRequested);
 
             // extraRequestData
@@ -418,5 +454,5 @@
                     /*
                      * make sure, we skip the client-internal parameters
-                     * to generate invalid requests ...
+                     * used to generate invalid requests ...
                      */
                     if (!key.startsWith(MALFORMED_KEY_PREFIX)) {
@@ -442,5 +478,5 @@
 
 
-    abstract void addParametersToURI(URIHelper uriBuilder)
+    abstract void addParametersToURI(URIHelper uriBuilder, SRUVersion version)
             throws SRUClientException;
 
Index: SRUClient/trunk/src/main/java/eu/clarin/sru/client/SRUClientConstants.java
===================================================================
--- SRUClient/trunk/src/main/java/eu/clarin/sru/client/SRUClientConstants.java	(revision 6080)
+++ SRUClient/trunk/src/main/java/eu/clarin/sru/client/SRUClientConstants.java	(revision 6903)
@@ -25,3 +25,6 @@
     public static final String RECORD_DATA_PARSER_SCHEMA_ANY = "*";
 
+    /** constant for CQL query type */
+    public static final String QUERY_TYPE_CQL = "cql";
+
 } // class SRUClientConstants
Index: SRUClient/trunk/src/main/java/eu/clarin/sru/client/SRUExplainRecordDataParser.java
===================================================================
--- SRUClient/trunk/src/main/java/eu/clarin/sru/client/SRUExplainRecordDataParser.java	(revision 6080)
+++ SRUClient/trunk/src/main/java/eu/clarin/sru/client/SRUExplainRecordDataParser.java	(revision 6903)
@@ -52,4 +52,6 @@
     private static final String VERSION_1_1     = "1.1";
     private static final String VERSION_1_2     = "1.2";
+    private static final String VERSION_2       = "2";
+    private static final String VERSION_2_0     = "2.0";
     private static final String TRANSPORT_HTTP  = "http";
     private static final String TRANSPORT_HTTPS = "https";
@@ -180,7 +182,9 @@
             } else if (VERSION_1_2.equals(s)) {
                 version = SRUVersion.VERSION_1_2;
+            } else if (VERSION_2.equals(s) || VERSION_2_0.equals(s)) {
+                version = SRUVersion.VERSION_2_0;
             } else {
                 throw new SRUClientException("invalid or unsupported value '" +
-                        s + "'for attribute 'version' on element '" +
+                        s + " 'for attribute 'version' on element '" +
                         reader.getName() + "'");
             }
Index: SRUClient/trunk/src/main/java/eu/clarin/sru/client/SRUExplainRequest.java
===================================================================
--- SRUClient/trunk/src/main/java/eu/clarin/sru/client/SRUExplainRequest.java	(revision 6080)
+++ SRUClient/trunk/src/main/java/eu/clarin/sru/client/SRUExplainRequest.java	(revision 6903)
@@ -26,5 +26,5 @@
  */
 public class SRUExplainRequest extends SRUAbstractRequest {
-    private SRURecordPacking recordPacking;
+    private SRURecordXmlEscaping recordXmlEscaping;
     private boolean parseRecordDataEnabled = false;
 
@@ -52,26 +52,40 @@
 
     /**
-     * Set the requested record packing.
+     * Get the <em>recordXmlEscpaing</em> (SRU 2.0) or <em>recordPacking</em>
+     * (SRU 1.1 and SRU 1.2) parameter of this request.
      *
-     * @param recordPacking
-     *            the requested record packing
-     * @see SRURecordPacking
+     * @return the requested record packing
+     * @see SRURecordXmlEscaping
      */
-    public void setRecordPacking(SRURecordPacking recordPacking) {
-        if (recordPacking == null) {
-            throw new NullPointerException("recordPacking == null");
-        }
-        this.recordPacking = recordPacking;
+    public SRURecordXmlEscaping getRecordXmlEscaping() {
+        return recordXmlEscaping;
     }
 
 
     /**
-     * Get the requested record packing.
+     * Set the <em>recordXmlEscpaing</em> (SRU 2.0) or <em>recordPacking</em>
+     * (SRU 1.1 and SRU 1.2) parameter of this request.
      *
-     * @return the requested record packing
-     * @see SRURecordPacking
+     * @param getRecordXmlEscaping
+     *            the requested record XML escaping
+     * @see SRURecordXmlEscaping
      */
-    public SRURecordPacking getRecordPacking() {
-        return recordPacking;
+    public void setRecordXmlEscaping(SRURecordXmlEscaping getRecordXmlEscaping) {
+        if (getRecordXmlEscaping == null) {
+            throw new NullPointerException("getRecordXmlEscaping == null");
+        }
+        this.recordXmlEscaping = getRecordXmlEscaping;
+    }
+
+
+    /**
+     * Check, whether the record data of a explain response (ZeeRex record)
+     * shall be parsed or not.
+     *
+     * @return <code>true</code> if parsing is enabled, <code>false</code>
+     *         otherwise
+     */
+    public boolean isParseRecordDataEnabled() {
+        return parseRecordDataEnabled;
     }
 
@@ -90,16 +104,4 @@
 
 
-    /**
-     * Check, whether the record data of a explain response (ZeeRex record)
-     * shall be parsed or not.
-     *
-     * @return <code>true</code> if parsing is enabled, <code>false</code>
-     *         otherwise
-     */
-    public boolean isParseRecordDataEnabled() {
-        return parseRecordDataEnabled;
-    }
-
-
     @Override
     SRUOperation getOperation() {
@@ -109,18 +111,46 @@
 
     @Override
-    void addParametersToURI(URIHelper uriHelper) throws SRUClientException {
-        // recordPacking
-        if (recordPacking != null) {
-            switch (recordPacking) {
-            case XML:
-                uriHelper.append(PARAM_RECORD_PACKING, RECORD_PACKING_XML);
+    void addParametersToURI(URIHelper uriHelper, SRUVersion version)
+            throws SRUClientException {
+        // recordXMLEscaping / recordPacking
+        if (recordXmlEscaping != null) {
+            switch (version) {
+            case VERSION_1_1:
+                /* $FALL-THROUGH$ */
+            case VERSION_1_2:
+                switch (recordXmlEscaping) {
+                case XML:
+                    uriHelper.append(PARAM_RECORD_PACKING,
+                            RECORD_XML_ESCAPING_XML);
+                    break;
+                case STRING:
+                    uriHelper.append(PARAM_RECORD_PACKING,
+                            RECORD_XML_ESCPAING_STRING);
+                    break;
+                default:
+                    throw new SRUClientException("unsupported record packing: " +
+                            recordXmlEscaping);
+                } // switch
                 break;
-            case STRING:
-                uriHelper.append(PARAM_RECORD_PACKING, RECORD_PACKING_STRING);
+            case VERSION_2_0:
+                switch (recordXmlEscaping) {
+                case XML:
+                    uriHelper.append(PARAM_RECORD_XML_ESCAPING,
+                            RECORD_XML_ESCAPING_XML);
+                    break;
+                case STRING:
+                    uriHelper.append(PARAM_RECORD_XML_ESCAPING,
+                            RECORD_XML_ESCPAING_STRING);
+                    break;
+                default:
+                    throw new SRUClientException(
+                            "unsupported record packing: " +
+                                    recordXmlEscaping);
+                }
                 break;
             default:
-                throw new SRUClientException("unsupported record packing: " +
-                        recordPacking);
-            } // switch
+                /* cannot happen */
+                break;
+            }
         }
     }
Index: SRUClient/trunk/src/main/java/eu/clarin/sru/client/SRURecordPacking.java
===================================================================
--- SRUClient/trunk/src/main/java/eu/clarin/sru/client/SRURecordPacking.java	(revision 6080)
+++ SRUClient/trunk/src/main/java/eu/clarin/sru/client/SRURecordPacking.java	(revision 6903)
@@ -1,4 +1,4 @@
 /**
- * This software is copyright (c) 2012-2014 by
+ * This software is copyright (c) 2011-2015 by
  *  - Institut fuer Deutsche Sprache (http://www.ids-mannheim.de)
  * This is free software. You can redistribute it
@@ -18,28 +18,17 @@
 
 /**
- * SRU record packing
+ * SRU 2.0 record packing.
  */
 public enum SRURecordPacking {
     /**
-     * XML record packing
+     * The client requests that the server should supply records strictly
+     * according to the requested schema.
      */
-    XML {
-        @Override
-        String getStringValue() {
-            return "xml";
-        }
-    },
+    PACKED,
 
     /**
-     * String record packing
+     * The server is free to allow the location of application data to vary
+     * within the record.
      */
-    STRING {
-        @Override
-        String getStringValue() {
-            return "string";
-        }
-    };
-
-    abstract String getStringValue();
-
+    UNPACKED
 } // enum SRURecordPacking
Index: SRUClient/trunk/src/main/java/eu/clarin/sru/client/SRURecordXmlEscaping.java
===================================================================
--- SRUClient/trunk/src/main/java/eu/clarin/sru/client/SRURecordXmlEscaping.java	(revision 6903)
+++ SRUClient/trunk/src/main/java/eu/clarin/sru/client/SRURecordXmlEscaping.java	(revision 6903)
@@ -0,0 +1,45 @@
+/**
+ * This software is copyright (c) 2012-2014 by
+ *  - Institut fuer Deutsche Sprache (http://www.ids-mannheim.de)
+ * This is free software. You can redistribute it
+ * and/or modify it under the terms described in
+ * the GNU General Public License v3 of which you
+ * should have received a copy. Otherwise you can download
+ * it from
+ *
+ *   http://www.gnu.org/licenses/gpl-3.0.txt
+ *
+ * @copyright Institut fuer Deutsche Sprache (http://www.ids-mannheim.de)
+ *
+ * @license http://www.gnu.org/licenses/gpl-3.0.txt
+ *  GNU General Public License v3
+ */
+package eu.clarin.sru.client;
+
+/**
+ * SRU record packing
+ */
+public enum SRURecordXmlEscaping {
+    /**
+     * XML record packing
+     */
+    XML {
+        @Override
+        String getStringValue() {
+            return "xml";
+        }
+    },
+
+    /**
+     * String record packing
+     */
+    STRING {
+        @Override
+        String getStringValue() {
+            return "string";
+        }
+    };
+
+    abstract String getStringValue();
+
+} // enum SRURecordPacking
Index: SRUClient/trunk/src/main/java/eu/clarin/sru/client/SRUScanRequest.java
===================================================================
--- SRUClient/trunk/src/main/java/eu/clarin/sru/client/SRUScanRequest.java	(revision 6080)
+++ SRUClient/trunk/src/main/java/eu/clarin/sru/client/SRUScanRequest.java	(revision 6903)
@@ -158,5 +158,6 @@
 
     @Override
-    void addParametersToURI(URIHelper uriHelper) throws SRUClientException {
+    void addParametersToURI(URIHelper uriHelper, SRUVersion version)
+            throws SRUClientException {
         // scanClause
         final String malformedScan =
Index: SRUClient/trunk/src/main/java/eu/clarin/sru/client/SRUSearchRetrieveRequest.java
===================================================================
--- SRUClient/trunk/src/main/java/eu/clarin/sru/client/SRUSearchRetrieveRequest.java	(revision 6080)
+++ SRUClient/trunk/src/main/java/eu/clarin/sru/client/SRUSearchRetrieveRequest.java	(revision 6903)
@@ -43,9 +43,11 @@
             "x-malformed-maximumRecords";
     /** for end-point conformance testing only. never use in production. */
-    public static final String X_MALFORMED_RECORD_PACKING =
+    public static final String X_MALFORMED_RECORD_XML_ESCAPING =
             "x-malformed-recordPacking";
+    private String queryType;
     private String query;
     private int startRecord = -1;
     private int maximumRecords = -1;
+    private SRURecordXmlEscaping recordXmlEscaping;
     private SRURecordPacking recordPacking;
     private String recordSchema;
@@ -72,4 +74,48 @@
     public SRUSearchRetrieveRequest(String baseURI) {
         super(baseURI);
+    }
+
+
+    /**
+     * (SRU 2.0) Get the value of the <em>queryType</em> argument for this
+     * request.
+     *
+     * @return the value for the <em>queryType</em> argument or
+     *         <code>null</code> of none was set
+     */
+    public String getQueryType() {
+        return queryType;
+    }
+
+
+    /**
+     * (SRU 2.0) Set the value of the <em>queryType</em> argument for this
+     * request.
+     *
+     * @param queryType
+     *            the value for the <em>queryType</em> argument
+     * @throws NullPointerException
+     *             if any required argument is <code>null</code>
+     * @throws IllegalArgumentException
+     *             if any argument is invalid
+     */
+    public void setQueryType(String queryType) {
+        if (queryType == null) {
+            throw new NullPointerException("queryType == null");
+        }
+        if (queryType.isEmpty()) {
+            throw new IllegalArgumentException("queryType is an empty string");
+        }
+        for (int i = 0; i < queryType.length(); i++) {
+            final char ch = queryType.charAt(i);
+            if (!((ch >= 'a' && ch <= 'z') ||
+                    (ch >= 'A' && ch <= 'Z') ||
+                    (ch >= '0' && ch <= '9') ||
+                    ((i > 0) && ((ch == '-') || ch == '_')))) {
+                throw new IllegalArgumentException(
+                        "queryType contains illegal characters");
+            }
+        }
+        this.queryType = queryType;
     }
 
@@ -188,8 +234,36 @@
 
     /**
-     * Get the value of the <em>recordSchema</em> argument for this request.
-     *
-     * @return the value for the <em>recordSchema</em> argument or
-     *         <code>null</code> of none was set
+     * Get the <em>recordXmlEscpaing</em> (SRU 2.0) or <em>recordPacking</em>
+     * (SRU 1.1 and SRU 1.2) parameter of this request.
+     *
+     * @return the requested record XML escaping
+     * @see SRURecordXmlEscaping
+     */
+    public SRURecordXmlEscaping getRecordXmlEscaping() {
+        return recordXmlEscaping;
+    }
+
+
+    /**
+     * Set the <em>recordXmlEscpaing</em> (SRU 2.0) or <em>recordPacking</em>
+     * (SRU 1.1 and SRU 1.2) parameter of this request.
+     *
+     * @param recordXmlEscaping
+     *            the requested record XML escaping
+     * @see SRURecordXmlEscaping
+     */
+    public void setRecordXmlEscaping(SRURecordXmlEscaping recordXmlEscaping) {
+        if (recordXmlEscaping == null) {
+            throw new NullPointerException("recordXmlEscaping == null");
+        }
+        this.recordXmlEscaping = recordXmlEscaping;
+    }
+
+
+    /**
+     * Get the <em>recordPacking</em> (SRU 2.0) parameter of this request.
+     *
+     * @return the requested record packing
+     * @see SRURecordPacking
      */
     public SRURecordPacking getRecordPacking() {
@@ -199,10 +273,9 @@
 
     /**
-     * Set the value of the <em>recordPacking</em> argument for this request.
-     *
-     * @param recordPacking
-     *            the value for the <em>recordPacking</em> argument
-     * @throws NullPointerException
-     *             if any required argument is <code>null</code>
+     * Set the <em>recordPacking</em> (SRU 2.0) parameter of this request.
+     *
+     * @param getRecordXmlEscaping
+     *            the requested record XML escaping
+     * @see SRURecordXmlEscaping
      */
     public void setRecordPacking(SRURecordPacking recordPacking) {
@@ -245,5 +318,6 @@
 
     @Override
-    void addParametersToURI(URIHelper uriHelper) throws SRUClientException {
+    void addParametersToURI(URIHelper uriHelper, SRUVersion version)
+            throws SRUClientException {
         /*
          * append query argument (mandatory)
@@ -268,4 +342,13 @@
 
         /*
+         * append queryType parameter (SRU 2.0, optional)
+         */
+        if ((version == SRUVersion.VERSION_2_0) && (queryType != null)) {
+            if (!SRUClientConstants.QUERY_TYPE_CQL.equals(queryType)) {
+                uriHelper.append(PARAM_QUERY_TYPE, queryType);
+            }
+        }
+
+        /*
          * append startRecord argument (optional)
          *
@@ -309,5 +392,5 @@
 
         /*
-         * append recordPacking argument (optional)
+         * append record XML escaping argument (optional)
          *
          * NB: Setting "x-malformed-recordPacking" as an extra request
@@ -316,25 +399,58 @@
          * (i.e. provoke an error) and SHOULD NEVER be used in production!
          */
-        final String malformedRecordPacking =
-                getExtraRequestData(X_MALFORMED_RECORD_PACKING);
-        if (malformedRecordPacking == null) {
-            if (recordPacking != null) {
-                switch (recordPacking) {
+        final String malformedRecordXmlEscaping =
+                getExtraRequestData(X_MALFORMED_RECORD_XML_ESCAPING);
+        if (malformedRecordXmlEscaping == null) {
+            if (recordXmlEscaping != null) {
+                switch (recordXmlEscaping) {
                 case XML:
-                    uriHelper.append(PARAM_RECORD_PACKING, RECORD_PACKING_XML);
+                    if (version == SRUVersion.VERSION_2_0) {
+                        uriHelper.append(PARAM_RECORD_XML_ESCAPING,
+                                RECORD_XML_ESCAPING_XML);
+                    } else {
+                        uriHelper.append(PARAM_RECORD_PACKING,
+                                RECORD_XML_ESCAPING_XML);
+                    }
                     break;
                 case STRING:
-                    uriHelper.append(PARAM_RECORD_PACKING,
-                            RECORD_PACKING_STRING);
+                    if (version == SRUVersion.VERSION_2_0) {
+                        uriHelper.append(PARAM_RECORD_XML_ESCAPING,
+                                RECORD_XML_ESCPAING_STRING);
+                    } else {
+                        uriHelper.append(PARAM_RECORD_PACKING,
+                                RECORD_XML_ESCPAING_STRING);
+                    }
                     break;
                 default:
                     throw new SRUClientException(
-                            "unsupported record packing: " + recordPacking);
+                            "unsupported record XML escpaing: " + recordXmlEscaping);
                 } // switch
             }
         } else {
-            if (!malformedRecordPacking.equalsIgnoreCase(MALFORMED_OMIT)) {
-                uriHelper.append(PARAM_RECORD_PACKING, malformedRecordPacking);
-            }
+            if (!malformedRecordXmlEscaping.equalsIgnoreCase(MALFORMED_OMIT)) {
+                if (version == SRUVersion.VERSION_2_0) {
+                    uriHelper.append(PARAM_RECORD_XML_ESCAPING,
+                            malformedRecordXmlEscaping);
+                } else {
+                    uriHelper.append(PARAM_RECORD_PACKING,
+                            malformedRecordXmlEscaping);
+                }
+            }
+        }
+
+        /*
+         * (SRU 2.0) append recordPacking argument (optional)
+         */
+        if ((version == SRUVersion.VERSION_2_0) && (recordPacking != null)) {
+            String s = null;
+            switch (recordPacking) {
+            case PACKED:
+                s = "packed";
+                break;
+            case UNPACKED:
+                s = "unpacked";
+                break;
+            }
+            uriHelper.append(PARAM_RECORD_PACKING, s);
         }
 
Index: SRUClient/trunk/src/main/java/eu/clarin/sru/client/SRUSimpleClient.java
===================================================================
--- SRUClient/trunk/src/main/java/eu/clarin/sru/client/SRUSimpleClient.java	(revision 6080)
+++ SRUClient/trunk/src/main/java/eu/clarin/sru/client/SRUSimpleClient.java	(revision 6903)
@@ -69,14 +69,17 @@
     private static final String USER_AGENT = "SRU-Client/1.0.0";
     /** default version the client will use, if not otherwise specified */
-    private static final String SRU_NS =
-            "http://www.loc.gov/zing/srw/";
-    private static final String SRU_DIAGNOSIC_NS =
-            "http://www.loc.gov/zing/srw/diagnostic/";
+//    private static final String SRU_NS =
+//            "http://www.loc.gov/zing/srw/";
+//    private static final String SRU_DIAGNOSIC_NS =
+//            "http://www.loc.gov/zing/srw/diagnostic/";
     private static final String SRU_DIAGNOSTIC_RECORD_SCHEMA =
             "info:srw/schema/1/diagnostics-v1.1";
     private static final String VERSION_1_1 = "1.1";
     private static final String VERSION_1_2 = "1.2";
-    private static final String RECORD_PACKING_XML = "xml";
-    private static final String RECORD_PACKING_STRING = "string";
+    private static final String VERSION_2_0 = "2.0";
+    private static final String RECORD_PACKING_PACKED = "packed";
+    private static final String RECORD_PACKING_UNPACKED = "unpacked";
+    private static final String RECORD_ESCAPING_XML = "xml";
+    private static final String RECORD_ESCAPING_STRING = "string";
     private static final Logger logger =
             LoggerFactory.getLogger(SRUSimpleClient.class);
@@ -454,4 +457,9 @@
         logger.debug("parsing 'explain' response (mode = {})",
                 (request.isStrictMode() ? "strict" : "non-strict"));
+
+        /* detect response namespaces */
+        final SRUNamespaces ns =
+                detectNamespace(reader, request.getRequestedVersion());
+
         /*
          * Eventually, SRUClient should always parse explain record data.
@@ -462,31 +470,37 @@
             logger.debug("parsing of explain record data skipped");
         }
-        doParseExplainResponse(reader, request, handler, parse);
+        doParseExplainResponse(reader, ns, request, handler, parse);
     }
 
 
     private void doParseExplainResponse(SRUXMLStreamReader reader,
-            SRUAbstractRequest request, SRUExplainHandler handler,
-            boolean parseRecordData) throws SRUClientException {
+            SRUNamespaces ns, SRUAbstractRequest request,
+            SRUExplainHandler handler, boolean parseRecordData)
+                    throws SRUClientException {
         try {
             final boolean strictMode = request.isStrictMode();
 
             // explainResponse
-            reader.readStart(SRU_NS, "explainResponse", true);
+            reader.readStart(ns.sruNS(), "explainResponse", true);
 
             // explainResponse/version
-            SRUVersion version = parseVersion(reader);
+            final SRUVersion version = parseVersion(reader, ns.sruNS());
             logger.debug("version = {}, requested = {}", version,
                     request.getRequestedVersion());
 
             // explainResponse/record
-            reader.readStart(SRU_NS, "record", true);
+            reader.readStart(ns.sruNS(), "record", true);
             if (parseRecordData) {
                 handler.onStartRecords(-1, null, -1);
 
-                SRURecordPacking packing = null;
-                if (!strictMode && reader.peekStart(SRU_NS, "recordPacking")) {
-                    packing = parseRecordPacking(reader, false);
-                    if (packing != null) {
+                /*
+                 * common error: recordEscaping / recordPacking (SRU 1.2) in
+                 * wrong order
+                 */
+                SRURecordXmlEscaping recordXmlEscaping = null;
+                if (!strictMode && reader.peekStart(ns.sruNS(), "recordPacking")) {
+                    recordXmlEscaping = parseRecordXmlEscaping(reader, ns,
+                            request.getRequestedVersion(), false);
+                    if (recordXmlEscaping != null) {
                         logger.error("element <recordPacking> must apperear " +
                                 "after element <recordSchema> within " +
@@ -494,13 +508,25 @@
                     }
                 }
+
                 String schema =
-                        reader.readContent(SRU_NS, "recordSchema", true);
-                if (packing == null) {
-                    packing = parseRecordPacking(reader, strictMode);
-                }
-                logger.debug("schema = {}, packing = {}", schema, packing);
+                        reader.readContent(ns.sruNS(), "recordSchema", true);
+
+                // (SRU 2.0) recordPacking (optional)
+                // XXX: what to do with it?
+                SRURecordPacking recordPacking = null;
+                if (version == SRUVersion.VERSION_2_0) {
+                    recordPacking = parseRecordPacking(reader,
+                            ns.sruNS(), strictMode);
+                }
+
+                if (recordXmlEscaping == null) {
+                    recordXmlEscaping = parseRecordXmlEscaping(reader, ns,
+                            request.getRequestedVersion(), strictMode);
+                }
+                logger.debug("schema = {}, escaping = {}, packing = {}",
+                        schema, recordXmlEscaping, recordPacking);
 
                 // explainResponse/record/recordData
-                reader.readStart(SRU_NS, "recordData", true);
+                reader.readStart(ns.sruNS(), "recordData", true);
                 reader.consumeWhitespace();
 
@@ -508,5 +534,5 @@
                 SRUXMLStreamReader recordReader = null;
 
-                if (packing == SRURecordPacking.STRING) {
+                if (recordXmlEscaping == SRURecordXmlEscaping.STRING) {
                     /*
                      * read content into temporary buffer and then use a new XML
@@ -538,5 +564,5 @@
                      * string record packing
                      */
-                    if (packing == SRURecordPacking.STRING) {
+                    if (recordXmlEscaping == SRURecordXmlEscaping.STRING) {
                         recordReader.closeCompletly();
                     }
@@ -547,15 +573,15 @@
                 }
                 reader.consumeWhitespace();
-                reader.readEnd(SRU_NS, "recordData", true);
+                reader.readEnd(ns.sruNS(), "recordData", true);
 
                 if (version == SRUVersion.VERSION_1_2) {
-                    reader.readContent(SRU_NS, "recordIdentifier", false);
-                }
-                reader.readContent(SRU_NS, "recordPosition", false, -1);
+                    reader.readContent(ns.sruNS(), "recordIdentifier", false);
+                }
+                reader.readContent(ns.sruNS(), "recordPosition", false, -1);
 
                 // notify handler
                 handler.onRecord(null, -1, recordData);
 
-                if (reader.readStart(SRU_NS, "extraRecordData", false)) {
+                if (reader.readStart(ns.sruNS(), "extraRecordData", false)) {
                     reader.consumeWhitespace();
                     proxy.reset(reader);
@@ -569,10 +595,10 @@
                     }
                     reader.consumeWhitespace();
-                    reader.readEnd(SRU_NS, "extraRecordData", true);
+                    reader.readEnd(ns.sruNS(), "extraRecordData", true);
                 }
 
                 handler.onFinishRecords(-1);
 
-                reader.readEnd(SRU_NS, "record");
+                reader.readEnd(ns.sruNS(), "record");
             } else {
                 /*
@@ -580,10 +606,10 @@
                  * until <record> end tag
                  */
-                reader.readEnd(SRU_NS, "record", true);
+                reader.readEnd(ns.sruNS(), "record", true);
             }
 
             // explainResponse/echoedExplainRequest
-            if (reader.readStart(SRU_NS, "echoedExplainRequest", false)) {
-                reader.readEnd(SRU_NS, "echoedExplainRequest", true);
+            if (reader.readStart(ns.sruNS(), "echoedExplainRequest", false)) {
+                reader.readEnd(ns.sruNS(), "echoedExplainRequest", true);
             }
 
@@ -604,5 +630,5 @@
             // explainResponse/diagnostics
             final List<SRUDiagnostic> diagnostics =
-                    parseDiagnostics(reader, strictMode);
+                    parseDiagnostics(reader, ns, ns.scanNS(), strictMode);
             if (diagnostics != null) {
                 handler.onDiagnostics(diagnostics);
@@ -610,5 +636,5 @@
 
             // explainResponse/extraResponseData
-            if (reader.readStart(SRU_NS, "extraResponseData", false)) {
+            if (reader.readStart(ns.sruNS(), "extraResponseData", false)) {
                 reader.consumeWhitespace();
                 proxy.reset(reader);
@@ -621,8 +647,8 @@
                 }
                 reader.consumeWhitespace();
-                reader.readEnd(SRU_NS, "extraResponseData", true);
-            }
-
-            reader.readEnd(SRU_NS, "explainResponse");
+                reader.readEnd(ns.sruNS(), "extraResponseData", true);
+            }
+
+            reader.readEnd(ns.sruNS(), "explainResponse");
         } catch (XMLStreamException e) {
             throw new SRUClientException(e.getMessage(), e);
@@ -635,10 +661,14 @@
             throws SRUClientException {
         try {
+            /* detect response namespaces */
+            final SRUNamespaces ns =
+                    detectNamespace(reader, request.getRequestedVersion());
+
             /*
              * if the endpoint cannot determine the operation, it should create
              * a explain response.
              */
-            if (reader.peekStart(SRU_NS, "explainResponse")) {
-                doParseExplainResponse(reader, request, new SRUExplainHandler() {
+            if (reader.peekStart(ns.sruNS(), "explainResponse")) {
+                doParseExplainResponse(reader, ns, request, new SRUExplainHandler() {
                     @Override
                     public void onRequestStatistics(int bytes, long millisTotal,
@@ -691,17 +721,16 @@
                         (strictMode ? "strict" : "non-strict"));
 
-
                 // scanResponse
-                reader.readStart(SRU_NS, "scanResponse", true);
+                reader.readStart(ns.scanNS(), "scanResponse", true);
 
                 // scanResponse/version
-                SRUVersion version = parseVersion(reader);
+                final SRUVersion version = parseVersion(reader, ns.scanNS());
                 logger.debug("version = {}, requested = {}", version,
                         request.getRequestedVersion());
 
                 // scanResponse/terms
-                if (reader.readStart(SRU_NS, "terms", false)) {
+                if (reader.readStart(ns.scanNS(), "terms", false)) {
                     boolean first = true;
-                    while (reader.readStart(SRU_NS, "term", first)) {
+                    while (reader.readStart(ns.scanNS(), "term", first)) {
                         if (first) {
                             first = false;
@@ -711,16 +740,16 @@
                         // scanResponse/terms/value
                         String value =
-                                reader.readContent(SRU_NS, "value", true);
+                                reader.readContent(ns.scanNS(), "value", true);
 
                         // scanResponse/terms/numberOfRecords
-                        int numberOfRecords = reader.readContent(SRU_NS,
+                        int numberOfRecords = reader.readContent(ns.scanNS(),
                                 "numberOfRecords", false, -1);
 
                         // scanResponse/terms/displayTerm
-                        String displayTerm = reader.readContent(SRU_NS,
+                        String displayTerm = reader.readContent(ns.scanNS(),
                                 "displayTerm", false);
 
                         // scanResponse/terms/whereInList
-                        String s = reader.readContent(SRU_NS,
+                        String s = reader.readContent(ns.scanNS(),
                                 "whereInList", false);
                         SRUWhereInList whereInList = null;
@@ -746,5 +775,5 @@
 
                         // scanResponse/terms/extraTermData
-                        if (reader.readStart(SRU_NS, "extraTermData", first)) {
+                        if (reader.readStart(ns.scanNS(), "extraTermData", first)) {
                             reader.consumeWhitespace();
                             proxy.reset(reader);
@@ -757,16 +786,16 @@
                             }
                             reader.consumeWhitespace();
-                            reader.readEnd(SRU_NS, "extraTermData", true);
+                            reader.readEnd(ns.scanNS(), "extraTermData", true);
                         }
-                        reader.readEnd(SRU_NS, "term", true);
+                        reader.readEnd(ns.scanNS(), "term", true);
 
                     } // while
-                    reader.readEnd(SRU_NS, "terms");
+                    reader.readEnd(ns.scanNS(), "terms");
                     handler.onFinishTerms();
                 }
 
                 // scanResponse/echoedScanRequest
-                if (reader.readStart(SRU_NS, "echoedScanRequest", false)) {
-                    reader.readEnd(SRU_NS, "echoedScanRequest", true);
+                if (reader.readStart(ns.scanNS(), "echoedScanRequest", false)) {
+                    reader.readEnd(ns.scanNS(), "echoedScanRequest", true);
                 }
 
@@ -784,5 +813,5 @@
                 // scanResponse/diagnostics
                 final List<SRUDiagnostic> diagnostics =
-                        parseDiagnostics(reader, strictMode);
+                        parseDiagnostics(reader, ns, ns.scanNS(), strictMode);
                 if (diagnostics != null) {
                     handler.onDiagnostics(diagnostics);
@@ -790,5 +819,5 @@
 
                 // scanResponse/extraResponseData
-                if (reader.readStart(SRU_NS, "extraResponseData", false)) {
+                if (reader.readStart(ns.scanNS(), "extraResponseData", false)) {
                     reader.consumeWhitespace();
                     proxy.reset(reader);
@@ -801,8 +830,8 @@
                     }
                     reader.consumeWhitespace();
-                    reader.readEnd(SRU_NS, "extraResponseData", true);
-                }
-
-                reader.readEnd(SRU_NS, "scanResponse");
+                    reader.readEnd(ns.scanNS(), "extraResponseData", true);
+                }
+
+                reader.readEnd(ns.scanNS(), "scanResponse");
             }
         } catch (XMLStreamException e) {
@@ -816,10 +845,14 @@
             final SRUSearchRetrieveHandler handler) throws SRUClientException {
         try {
+            /* detect response namespaces */
+            final SRUNamespaces ns =
+                    detectNamespace(reader, request.getRequestedVersion());
+
             /*
              * if the endpoint cannot determine the operation, it should create
              * a explain response.
              */
-            if (reader.peekStart(SRU_NS, "explainResponse")) {
-                doParseExplainResponse(reader, request, new SRUExplainHandler() {
+            if (reader.peekStart(ns.sruNS(), "explainResponse")) {
+                doParseExplainResponse(reader, ns, request, new SRUExplainHandler() {
                     @Override
                     public void onRequestStatistics(int bytes, long millisTotal,
@@ -873,21 +906,21 @@
 
                 // searchRetrieveResponse
-                reader.readStart(SRU_NS, "searchRetrieveResponse", true);
+                reader.readStart(ns.sruNS(), "searchRetrieveResponse", true);
 
                 // searchRetrieveResponse/version
-                SRUVersion version = parseVersion(reader);
+                final SRUVersion version = parseVersion(reader, ns.sruNS());
                 logger.debug("version = {}, requested = {}", version,
                         request.getRequestedVersion());
 
                 // searchRetrieveResponse/numberOfRecords
-                int numberOfRecords = reader.readContent(SRU_NS,
+                int numberOfRecords = reader.readContent(ns.sruNS(),
                         "numberOfRecords", true, -1);
 
                 // searchRetrieveResponse/resultSetId
-                String resultSetId = reader.readContent(SRU_NS,
+                String resultSetId = reader.readContent(ns.sruNS(),
                         "resultSetId", false);
 
                 // searchRetrieveResponse/resultSetIdleTime
-                int resultSetIdleTime = reader.readContent(SRU_NS,
+                int resultSetIdleTime = reader.readContent(ns.sruNS(),
                         "resultSetIdleTime", false, -1);
 
@@ -904,8 +937,8 @@
                      */
                     int recordCount = 0;
-                    if (reader.readStart(SRU_NS, "records", false)) {
+                    if (reader.readStart(ns.sruNS(), "records", false)) {
                         // searchRetrieveResponse/records/record
                         boolean first = true;
-                        while (reader.readStart(SRU_NS, "record", first)) {
+                        while (reader.readStart(ns.sruNS(), "record", first)) {
                             if (first) {
                                 first = false;
@@ -915,11 +948,14 @@
 
                             /*
-                             * common error: recordPacking before recordSchema
+                             * common error: recordEscaping / recordPacking
+                             * (SRU 1.2) in wrong order
                              */
-                            SRURecordPacking packing = null;
+                            SRURecordXmlEscaping recordXmlEscaping = null;
                             if (!strictMode &&
-                                    reader.peekStart(SRU_NS, "recordPacking")) {
-                                packing = parseRecordPacking(reader, false);
-                                if (packing != null) {
+                                    reader.peekStart(ns.sruNS(), "recordPacking")) {
+                                recordXmlEscaping =
+                                        parseRecordXmlEscaping(reader, ns,
+                                                version, false);
+                                if (recordXmlEscaping != null) {
                                     logger.error("element <recordPacking> " +
                                             "must appear after element " +
@@ -928,24 +964,38 @@
                                 }
                             }
-                            String schema = reader.readContent(SRU_NS,
+
+                            String schema = reader.readContent(ns.sruNS(),
                                     "recordSchema", true);
-                            if (packing == null) {
-                                packing = parseRecordPacking(reader, strictMode);
+
+                            // (SRU 2.0) recordPacking (optional)
+                            // XXX: what to do with it?
+                            SRURecordPacking recordPacking = null;
+                            if (version == SRUVersion.VERSION_2_0) {
+                                recordPacking = parseRecordPacking(reader,
+                                        ns.sruNS(), strictMode);
                             }
 
-                            logger.debug("schema = {}, packing = {}, " +
+                            if (recordXmlEscaping == null) {
+                                recordXmlEscaping =
+                                        parseRecordXmlEscaping(reader, ns,
+                                                version, strictMode);
+                            }
+
+                            logger.debug("schema = {}, escpaing = {}, " +
+                                    "packing = {}, requested escaping = {}, " +
                                     "requested packing = {}",
-                                    schema, packing,
+                                    schema, recordXmlEscaping, recordPacking,
+                                    request.getRecordXmlEscaping(),
                                     request.getRecordPacking());
 
-                            if ((request.getRecordPacking() != null) &&
-                                    (packing != request.getRecordPacking())) {
-                                final SRURecordPacking p =
-                                        request.getRecordPacking();
-                                logger.error("requested '{}' record packing, " +
+                            if ((request.getRecordXmlEscaping() != null) &&
+                                    (recordXmlEscaping != request.getRecordXmlEscaping())) {
+                                final SRURecordXmlEscaping p =
+                                        request.getRecordXmlEscaping();
+                                logger.error("requested '{}' record XML escaping, " +
                                         "but server responded with '{}' " +
-                                        "record packing",
+                                        "record XML escaping",
                                         p.getStringValue(),
-                                        packing.getStringValue());
+                                        recordXmlEscaping.getStringValue());
                                 if (strictMode) {
                                     throw new SRUClientException("requested '" +
@@ -953,5 +1003,5 @@
                                             "' record packing, but server " +
                                             "responded with '" +
-                                            packing.getStringValue() +
+                                            recordXmlEscaping.getStringValue() +
                                             "' record packing");
                                 }
@@ -959,5 +1009,5 @@
 
                             // searchRetrieveResponse/record/recordData
-                            reader.readStart(SRU_NS, "recordData", true);
+                            reader.readStart(ns.sruNS(), "recordData", true);
                             reader.consumeWhitespace();
 
@@ -966,5 +1016,5 @@
                             SRUXMLStreamReader recordReader = null;
 
-                            if (packing == SRURecordPacking.STRING) {
+                            if (recordXmlEscaping == SRURecordXmlEscaping.STRING) {
                                 /*
                                  * read content into temporary buffer and then
@@ -981,6 +1031,6 @@
 
                             if (SRU_DIAGNOSTIC_RECORD_SCHEMA.equals(schema)) {
-                                surrogate = parseDiagnostic(recordReader, true,
-                                        strictMode);
+                                surrogate = parseDiagnostic(recordReader, ns,
+                                        true, strictMode);
                             } else {
                                 SRURecordDataParser parser = findParser(schema);
@@ -998,5 +1048,5 @@
                                          * packing
                                          */
-                                        if (packing == SRURecordPacking.STRING) {
+                                        if (recordXmlEscaping == SRURecordXmlEscaping.STRING) {
                                             recordReader.closeCompletly();
                                         }
@@ -1036,13 +1086,13 @@
 
                             reader.consumeWhitespace();
-                            reader.readEnd(SRU_NS, "recordData", true);
+                            reader.readEnd(ns.sruNS(), "recordData", true);
 
                             String identifier = null;
                             if (version == SRUVersion.VERSION_1_2) {
-                                identifier = reader.readContent(SRU_NS,
+                                identifier = reader.readContent(ns.sruNS(),
                                         "recordIdentifier", false);
                             }
 
-                            int position = reader.readContent(SRU_NS,
+                            int position = reader.readContent(ns.sruNS(),
                                     "recordPosition", false, -1);
 
@@ -1062,5 +1112,5 @@
                             }
 
-                            if (reader.readStart(SRU_NS,
+                            if (reader.readStart(ns.sruNS(),
                                     "extraRecordData", false)) {
                                 reader.consumeWhitespace();
@@ -1075,11 +1125,11 @@
                                 }
                                 reader.consumeWhitespace();
-                                reader.readEnd(SRU_NS, "extraRecordData", true);
+                                reader.readEnd(ns.sruNS(), "extraRecordData", true);
                             }
 
-                            reader.readEnd(SRU_NS, "record");
+                            reader.readEnd(ns.sruNS(), "record");
                             recordCount++;
                         } // while
-                        reader.readEnd(SRU_NS, "records");
+                        reader.readEnd(ns.sruNS(), "records");
                     }
                     if (recordCount == 0) {
@@ -1093,11 +1143,11 @@
                      * an empty <records> element
                      */
-                    if (reader.readStart(SRU_NS, "records", false)) {
+                    if (reader.readStart(ns.sruNS(), "records", false)) {
                         int bad = 0;
-                        while (reader.readStart(SRU_NS, "record", false)) {
+                        while (reader.readStart(ns.sruNS(), "record", false)) {
                             bad++;
-                            reader.readEnd(SRU_NS, "record", true);
+                            reader.readEnd(ns.sruNS(), "record", true);
                         }
-                        reader.readEnd(SRU_NS, "records", true);
+                        reader.readEnd(ns.sruNS(), "records", true);
                         if (bad == 0) {
                             logger.error("endpoint declared 0 results, but " +
@@ -1126,5 +1176,5 @@
                 }
 
-                int nextRecordPosition = reader.readContent(SRU_NS,
+                int nextRecordPosition = reader.readContent(ns.sruNS(),
                         "nextRecordPosition", false, -1);
                 logger.debug("nextRecordPosition = {}", nextRecordPosition);
@@ -1132,7 +1182,7 @@
 
                 // searchRetrieveResponse/echoedSearchRetrieveResponse
-                if (reader.readStart(SRU_NS,
+                if (reader.readStart(ns.sruNS(),
                         "echoedSearchRetrieveRequest", false)) {
-                    reader.readEnd(SRU_NS, "echoedSearchRetrieveRequest", true);
+                    reader.readEnd(ns.sruNS(), "echoedSearchRetrieveRequest", true);
                 }
 
@@ -1156,5 +1206,5 @@
                 // searchRetrieveResponse/diagnostics
                 final List<SRUDiagnostic> diagnostics =
-                        parseDiagnostics(reader, strictMode);
+                        parseDiagnostics(reader, ns, ns.toString(), strictMode);
                 if (diagnostics != null) {
                     handler.onDiagnostics(diagnostics);
@@ -1162,5 +1212,5 @@
 
                 // explainResponse/extraResponseData
-                if (reader.readStart(SRU_NS, "extraResponseData", false)) {
+                if (reader.readStart(ns.sruNS(), "extraResponseData", false)) {
                     reader.consumeWhitespace();
                     proxy.reset(reader);
@@ -1172,8 +1222,18 @@
                     }
                     reader.consumeWhitespace();
-                    reader.readEnd(SRU_NS, "extraResponseData", true);
-                }
-
-                reader.readEnd(SRU_NS, "searchRetrieveResponse");
+                    reader.readEnd(ns.sruNS(), "extraResponseData", true);
+                }
+
+                if (version == SRUVersion.VERSION_2_0) {
+                    // SRU (2.0) arbitrary stuff
+                    // SRU (2.0) resultSetTTL (replaces resultSetIdleTime)
+                    // SRU (2.0) resultCountPrecision
+                    if (reader.readStart(ns.sruNS(), "resultCountPrecision", false)) {
+                        reader.readEnd(ns.sruNS(), "resultCountPrecision", true);
+                    }
+                    // SRU (2.0) facetedResults
+                    // SRU (2.0) searchResultAnalysis
+                }
+                reader.readEnd(ns.sruNS(), "searchRetrieveResponse");
             }
         } catch (XMLStreamException e) {
@@ -1183,11 +1243,13 @@
 
 
-    private static SRUVersion parseVersion(SRUXMLStreamReader reader)
-        throws XMLStreamException, SRUClientException {
-        final String v = reader.readContent(SRU_NS, "version", true);
+    private static SRUVersion parseVersion(SRUXMLStreamReader reader,
+            String envelopNs) throws XMLStreamException, SRUClientException {
+        final String v = reader.readContent(envelopNs, "version", true);
         if (VERSION_1_1.equals(v)) {
             return SRUVersion.VERSION_1_1;
         } else if (VERSION_1_2.equals(v)) {
             return SRUVersion.VERSION_1_2;
+        } else if (VERSION_2_0.equals(v)) {
+            return SRUVersion.VERSION_2_0;
         } else {
             throw new SRUClientException("invalid value '" + v +
@@ -1199,11 +1261,11 @@
 
     private static List<SRUDiagnostic> parseDiagnostics(
-            SRUXMLStreamReader reader, boolean strictMode)
+            SRUXMLStreamReader reader, SRUNamespaces ns, String responseNs, boolean strictMode)
             throws XMLStreamException, SRUClientException {
-        if (reader.readStart(SRU_NS, "diagnostics", false)) {
+        if (reader.readStart(responseNs, "diagnostics", false)) {
             List<SRUDiagnostic> diagnostics = null;
 
             SRUDiagnostic diagnostic = null;
-            while ((diagnostic = parseDiagnostic(reader,
+            while ((diagnostic = parseDiagnostic(reader, ns,
                     (diagnostics == null), strictMode)) != null) {
                 if (diagnostics == null) {
@@ -1212,5 +1274,5 @@
                 diagnostics.add(diagnostic);
             } // while
-            reader.readEnd(SRU_NS, "diagnostics");
+            reader.readEnd(responseNs, "diagnostics");
             return diagnostics;
         } else {
@@ -1221,10 +1283,10 @@
 
     private static SRUDiagnostic parseDiagnostic(SRUXMLStreamReader reader,
-            boolean required, boolean strictMode) throws XMLStreamException,
+            SRUNamespaces ns, boolean required, boolean strictMode) throws XMLStreamException,
             SRUClientException {
-        if (reader.readStart(SRU_DIAGNOSIC_NS, "diagnostic", required)) {
+        if (reader.readStart(ns.diagnosticNS(), "diagnostic", required)) {
 
             // diagnostic/uri
-            String uri = reader.readContent(SRU_DIAGNOSIC_NS, "uri", true);
+            String uri = reader.readContent(ns.diagnosticNS(), "uri", true);
 
             String details = null;
@@ -1232,9 +1294,9 @@
             if (strictMode) {
                 // diagnostic/details
-                details = reader.readContent(SRU_DIAGNOSIC_NS, "details",
+                details = reader.readContent(ns.diagnosticNS(), "details",
                         false, true);
 
                 // diagnostic/message
-                message = reader.readContent(SRU_DIAGNOSIC_NS, "message",
+                message = reader.readContent(ns.diagnosticNS(), "message",
                         false, true);
             } else {
@@ -1243,13 +1305,13 @@
                  * appear in any order
                  */
-                if (reader.peekStart(SRU_DIAGNOSIC_NS, "details")) {
-                    details = reader.readContent(SRU_DIAGNOSIC_NS, "details",
+                if (reader.peekStart(ns.diagnosticNS(), "details")) {
+                    details = reader.readContent(ns.diagnosticNS(), "details",
                             false, false);
-                    message = reader.readContent(SRU_DIAGNOSIC_NS, "message",
+                    message = reader.readContent(ns.diagnosticNS(), "message",
                             false, false);
                 } else {
-                    message = reader.readContent(SRU_DIAGNOSIC_NS, "message",
+                    message = reader.readContent(ns.diagnosticNS(), "message",
                             false, false);
-                    details = reader.readContent(SRU_DIAGNOSIC_NS, "details",
+                    details = reader.readContent(ns.diagnosticNS(), "details",
                             false, false);
                     if ((message != null) && (details != null)) {
@@ -1272,5 +1334,5 @@
             }
 
-            reader.readEnd(SRU_DIAGNOSIC_NS, "diagnostic");
+            reader.readEnd(ns.diagnosticNS(), "diagnostic");
 
             logger.debug("diagnostic: uri={}, detail={}, message={}",
@@ -1284,25 +1346,55 @@
 
     private static SRURecordPacking parseRecordPacking(
-            SRUXMLStreamReader reader, boolean strictMode)
+            SRUXMLStreamReader reader, String envelopNs, boolean strictMode)
+                    throws XMLStreamException, SRUClientException {
+        final String s = reader.readContent(envelopNs, "recordPacking", false);
+        if (s != null) {
+            if (RECORD_PACKING_PACKED.equals(s)) {
+                return SRURecordPacking.PACKED;
+            } else if (RECORD_PACKING_UNPACKED.equals(s)) {
+                return SRURecordPacking.UNPACKED;
+            } else if (!strictMode && RECORD_PACKING_PACKED.equalsIgnoreCase(s)) {
+                logger.error("invalid value '{}' for '<recordPacking>', should be '{}'",
+                             s, RECORD_PACKING_PACKED);
+                return SRURecordPacking.PACKED;
+            } else if (!strictMode && RECORD_PACKING_UNPACKED.equalsIgnoreCase(s)) {
+                logger.error("invalid value '{}' for '<recordPacking>', should be '{}'",
+                             s, RECORD_PACKING_UNPACKED);
+                return SRURecordPacking.UNPACKED;
+            } else {
+                throw new SRUClientException("invalid value '" + s +
+                        "' for '<recordPacking>' (valid values are: '" +
+                        RECORD_PACKING_PACKED + "' and '" + RECORD_PACKING_UNPACKED +
+                        "')");
+            }
+        }
+        return null;
+    }
+
+
+    private static SRURecordXmlEscaping parseRecordXmlEscaping(
+            SRUXMLStreamReader reader, SRUNamespaces ns, SRUVersion version, boolean strictMode)
             throws XMLStreamException, SRUClientException {
-        final String v = reader.readContent(SRU_NS, "recordPacking", true);
-
-        if (RECORD_PACKING_XML.equals(v)) {
-            return SRURecordPacking.XML;
-        } else if (RECORD_PACKING_STRING.equals(v)) {
-            return SRURecordPacking.STRING;
-        } else if (!strictMode && RECORD_PACKING_XML.equalsIgnoreCase(v)) {
-            logger.error("invalid value '{}' for record packing, should be '{}'",
-                         v, RECORD_PACKING_XML);
-            return SRURecordPacking.XML;
-        } else if (!strictMode && RECORD_PACKING_STRING.equalsIgnoreCase(v)) {
-            logger.error("invalid value '{}' for record packing, should be '{}'",
-                         v, RECORD_PACKING_STRING);
-            return SRURecordPacking.STRING;
-
+
+        final String name = (version == SRUVersion.VERSION_2_0)
+                          ? "recordXMLEscaping" : "recordPacking";
+        final String s = reader.readContent(ns.sruNS(), name, true);
+
+        if (RECORD_ESCAPING_XML.equals(s)) {
+            return SRURecordXmlEscaping.XML;
+        } else if (RECORD_ESCAPING_STRING.equals(s)) {
+            return SRURecordXmlEscaping.STRING;
+        } else if (!strictMode && RECORD_ESCAPING_XML.equalsIgnoreCase(s)) {
+            logger.error("invalid value '{}' for '<{}>', should be '{}'",
+                         s, name, RECORD_ESCAPING_XML);
+            return SRURecordXmlEscaping.XML;
+        } else if (!strictMode && RECORD_ESCAPING_STRING.equalsIgnoreCase(s)) {
+            logger.error("invalid value '{}' for '<{}>', should be '{}'",
+                         s, name, RECORD_ESCAPING_STRING);
+            return SRURecordXmlEscaping.STRING;
         } else {
-            throw new SRUClientException("invalid value '" + v +
-                    "' for record packing (valid values are: '" +
-                    RECORD_PACKING_XML + "' and '" + RECORD_PACKING_STRING +
+            throw new SRUClientException("invalid value '" + s +
+                    "' for '<" + name + ">' (valid values are: '" +
+                    RECORD_ESCAPING_XML + "' and '" + RECORD_ESCAPING_STRING +
                     "')");
         }
@@ -1358,3 +1450,107 @@
     }
 
+
+    private static SRUNamespaces detectNamespace(XMLStreamReader reader,
+            SRUVersion requestedVersion)
+                    throws SRUClientException {
+        try {
+            // skip to first start tag
+            reader.nextTag();
+
+            final String namespaceURI = reader.getNamespaceURI();
+            logger.debug("found namespace URI '{}', requested version = {}",
+                    namespaceURI, requestedVersion);
+
+            if (NAMESPACES_LEGACY_LOC.foo(namespaceURI)) {
+                return NAMESPACES_LEGACY_LOC;
+            } else if (NAMESPACES_OASIS.foo(namespaceURI)) {
+                return NAMESPACES_OASIS;
+            } else {
+                throw new SRUClientException(
+                        "invalid namespace '" + reader.getNamespaceURI() + "'");
+            }
+        } catch (XMLStreamException e) {
+            throw new SRUClientException("error detecting namespace", e);
+        }
+    }
+
+
+    private interface SRUNamespaces {
+        public String sruNS();
+
+        public String scanNS();
+
+        public String diagnosticNS();
+
+        public boolean foo(String namespaceURI);
+
+    } // interface SRUNamespace
+
+
+    private static final SRUNamespaces NAMESPACES_LEGACY_LOC = new SRUNamespaces() {
+        private static final String SRU_NS =
+                "http://www.loc.gov/zing/srw/";
+        private static final String SRU_DIAGNOSIC_NS =
+                "http://www.loc.gov/zing/srw/diagnostic/";
+
+
+        @Override
+        public String sruNS() {
+            return SRU_NS;
+        }
+
+
+        @Override
+        public String scanNS() {
+            return SRU_NS;
+        }
+
+
+        @Override
+        public String diagnosticNS() {
+            return SRU_DIAGNOSIC_NS;
+        }
+
+
+        @Override
+        public boolean foo(String namespaceURI) {
+            return SRU_NS.equals(namespaceURI);
+        }
+    };
+
+
+    private static final SRUNamespaces NAMESPACES_OASIS = new SRUNamespaces() {
+        private static final String SRU_NS =
+                "http://docs.oasis-open.org/ns/search-ws/sruResponse";
+        private static final String SRU_SCAN_NS =
+                "http://docs.oasis-open.org/ns/search-ws/scan";
+        private static final String SRU_DIAGNOSIC_NS =
+                "http://docs.oasis-open.org/ns/search-ws/diagnostic";
+
+
+        @Override
+        public String sruNS() {
+            return SRU_NS;
+        }
+
+
+        @Override
+        public String scanNS() {
+            return SRU_SCAN_NS;
+
+        }
+
+
+        @Override
+        public String diagnosticNS() {
+            return SRU_DIAGNOSIC_NS;
+        }
+
+
+        @Override
+        public boolean foo(String namespaceURI) {
+            return SRU_NS.equals(namespaceURI) || SRU_SCAN_NS.equals(namespaceURI);
+        }
+    };
+
 } // class SRUSimpleClient
Index: SRUClient/trunk/src/main/java/eu/clarin/sru/client/SRUVersion.java
===================================================================
--- SRUClient/trunk/src/main/java/eu/clarin/sru/client/SRUVersion.java	(revision 6080)
+++ SRUClient/trunk/src/main/java/eu/clarin/sru/client/SRUVersion.java	(revision 6903)
@@ -29,5 +29,10 @@
      * SRU/CQL version 1.2
      */
-    VERSION_1_2
+    VERSION_1_2,
+
+    /**
+     * SRU/CQL version 2.0
+     */
+    VERSION_2_0;
 
 } // enum SRUVersion
Index: SRUClient/trunk/src/main/java/eu/clarin/sru/client/fcs/ClarinFCSEndpointDescriptionParser.java
===================================================================
--- SRUClient/trunk/src/main/java/eu/clarin/sru/client/fcs/ClarinFCSEndpointDescriptionParser.java	(revision 6080)
+++ SRUClient/trunk/src/main/java/eu/clarin/sru/client/fcs/ClarinFCSEndpointDescriptionParser.java	(revision 6903)
@@ -105,5 +105,6 @@
             throws XMLStreamException, SRUClientException {
         final int version = parseVersion(reader);
-        if (version != EXPECTED_VERSION) {
+        // FIXME: actually handle other version
+        if ((version != EXPECTED_VERSION) && (version != 2)) {
             throw new SRUClientException("Attribute 'version' of " +
                     "element '<EndpointDescription>' must be of value '1'");
@@ -201,4 +202,12 @@
                     MIMETYPE_HITS_DATAVIEW +
                     "') to conform to CLARIN-FCS specification");
+        }
+
+        // SupportedLayers
+        // FIXME: actually do something useful
+        if (XmlStreamReaderUtils.readStart(reader, ED_NS_URI,
+                "SupportedLayers", false)) {
+            XmlStreamReaderUtils.readEnd(reader, ED_NS_URI,
+                    "SupportedLayers", true);
         }
 
@@ -315,4 +324,14 @@
             logger.debug("DataViews: {}", dataviews);
 
+
+            // FIXME: actually do something useful
+            if (XmlStreamReaderUtils.readStart(reader, ED_NS_URI, "AvailableLayers", false, true)) {
+                final String ls = XmlStreamReaderUtils.readAttributeValue(reader, null, "ref", true);
+                reader.next(); // consume start tag
+                XmlStreamReaderUtils.readEnd(reader, ED_NS_URI, "AvailableLayers");
+                logger.debug("Layers: {}", dataviews);
+            }
+
+
             List<ResourceInfo> subResources = null;
             if (XmlStreamReaderUtils.peekStart(reader,
Index: SRUClient/trunk/src/test/java/eu/clarin/sru/client/TestClient.java
===================================================================
--- SRUClient/trunk/src/test/java/eu/clarin/sru/client/TestClient.java	(revision 6080)
+++ SRUClient/trunk/src/test/java/eu/clarin/sru/client/TestClient.java	(revision 6903)
@@ -35,4 +35,5 @@
             SRUClient client = new ClarinFCSClientBuilder()
                     .addDefaultDataViewParsers()
+                    .setDefaultSRUVersion(SRUVersion.VERSION_2_0)
                     .unknownDataViewAsString()
                     .enableLegacySupport()
Index: SRUClient/trunk/src/test/java/eu/clarin/sru/client/TestUtils.java
===================================================================
--- SRUClient/trunk/src/test/java/eu/clarin/sru/client/TestUtils.java	(revision 6080)
+++ SRUClient/trunk/src/test/java/eu/clarin/sru/client/TestUtils.java	(revision 6903)
@@ -65,5 +65,6 @@
 //        request.setRecordSchema(ClarinFCSRecordData.LEGACY_RECORD_SCHEMA);
         request.setMaximumRecords(5);
-        request.setRecordPacking(SRURecordPacking.XML);
+        request.setRecordXmlEscaping(SRURecordXmlEscaping.XML);
+        request.setRecordPacking(SRURecordPacking.PACKED);
         request.setExtraRequestData("x-indent-response", "4");
         return request;
