Dear Christian,
thank you for quickly attacking the
problem! But sorry, but the problem is not fixed.I get the same error.
I have a general note.
I have implemented a special serializer
which implements org.xml.sax.XMLReader.
This is used to directly dispatch the query result to JAXB and to created
objects.
I can now extend this technique to
generate a new DOM by implementing a SAX ContentHandler which generates
a DOM.
Unfortunately the serializer API is
not documented nor stable (it changed from 7.3 to 7.5).
I propose to add a standard SAX serializer
to BaseX. This would be a very useful extension.
Here is my implementation:
import static org.basex.util.Token.XMLNS;
import static org.basex.util.Token.startsWith;
import static org.basex.util.Token.string;
import static org.basex.util.Token.substring;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import org.basex.io.serial.Serializer;
import org.basex.query.value.item.Item;
import org.xml.sax.ContentHandler;
import org.xml.sax.DTDHandler;
import org.xml.sax.EntityResolver;
import org.xml.sax.ErrorHandler;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.SAXNotRecognizedException;
import org.xml.sax.SAXNotSupportedException;
import org.xml.sax.XMLReader;
import org.xml.sax.ext.LexicalHandler;
import org.xml.sax.helpers.AttributesImpl;
/**
* Bridge to translate BaseX items
to SAX events.
* The parse() methods does the
following:
* <ol>
* <li>notify startDocument()</li>
* <li>serialize the item</li>
* <li>notify endDocument()</li>
*/
public class FragmentSerializer extends
Serializer implements XMLReader
{
/**
*
The item to be serialized
*/
private
Item item;
private
ContentHandler contentHandler;
private
EntityResolver entityResolver;
private
DTDHandler dtdHandler;
private
ErrorHandler errorHandler;
private
LexicalHandler lexicalHandler;
public
FragmentSerializer()
{
}
public
Item getItem()
{
return item;
}
/**
*
Sets the item to be serialized.
*/
public
void setItem(Item item)
{
this.item = item;
}
//////////////////////////////////////////////////
//
XMLReader
//////////////////////////////////////////////////
@Override
public
ContentHandler getContentHandler()
{
return contentHandler;
}
@Override
public
boolean getFeature(final String name)
{
return false;
}
@Override
public
Object getProperty(final String name)
{
return null;
}
public
void parse() throws SAXException
{
parse("");
}
@Override
public
void parse(final InputSource input) throws SAXException
{
parse("");
}
@Override
public
void parse(final String id) throws SAXException
{
try
{
contentHandler.startDocument();
item.serialize(this);
contentHandler.endDocument();
}
catch (final Exception ex)
{
throw
new SAXException(ex);
}
}
@Override
public
void setContentHandler(final ContentHandler c)
{
contentHandler = c;
}
public
void setLexicalHandler(final LexicalHandler l)
{
lexicalHandler = l;
}
@Override
public
void setEntityResolver(EntityResolver entityResolver)
{
this.entityResolver = entityResolver;
}
@Override
public
EntityResolver getEntityResolver()
{
return entityResolver;
}
@Override
public
void setDTDHandler(DTDHandler dtdHandler)
{
this.dtdHandler = dtdHandler;
}
@Override
public
DTDHandler getDTDHandler()
{
return dtdHandler;
}
@Override
public
void setErrorHandler(ErrorHandler errorHandler)
{
this.errorHandler = errorHandler;
}
@Override
public
ErrorHandler getErrorHandler()
{
return errorHandler;
}
@Override
public
void setFeature(final String name, final boolean value) throws SAXNotRecognizedException,
SAXNotSupportedException
{
throw new SAXNotRecognizedException();
}
@Override
public
void setProperty(final String name, final Object value) throws SAXNotRecognizedException,
SAXNotSupportedException
{
throw new SAXNotRecognizedException();
}
//////////////////////////////////////////////////
//
Serializer
//////////////////////////////////////////////////
private
final HashMap<String, String> attributes = new HashMap<String,
String>();
private
NSDecl namespaces;
@Override
protected
void startOpen(byte[] n) throws IOException
{
attributes.clear();
this.namespaces = new NSDecl(this.namespaces);
}
@Override
protected
void attribute(byte[] n, byte[] v) throws IOException
{
String value = string(v);
String prefix = null;
if (startsWith(n, XMLNS))
{
if (n.length
== 5)
{
prefix = "";
}
else if
(n[5] == ':')
{
prefix = string(substring(n, 6));
}
}
if (prefix != null)
{
namespaces.put(prefix,
value);
}
else
{
String
name = string(n);
attributes.put(name,
value);
}
}
@Override
protected
void finishOpen() throws IOException
{
try
{
AttributesImpl
attrs = new AttributesImpl();
for (Map.Entry<String,
String> e : attributes.entrySet())
{
String rname = e.getKey();
String[] qname = qname(rname);
String ns = namespaces.get(qname[0]);
String lname = qname[1];
attrs.addAttribute(ns, lname, rname, null,
e.getValue());
}
String
rname = string(elem);
String[]
qname = qname(rname);
String
ns = namespaces.get(qname[0]);
String
lname = qname[1];
contentHandler.startElement(ns,
lname, rname, attrs);
//
System.out.println("{"
+ ns + "}" + lname);
//
for
(int i = 0; i < attrs.getLength(); i++)
//
{
//
System.out.println(" {"
+ attrs.getURI(i) + "}" + attrs.getLocalName(i) + "="
+ attrs.getValue(i));
//
}
}
catch (final SAXException e)
{
throw
new IOException(e.getMessage());
}
}
public
String[] qname(String rname)
{
String prefix = "";
String lname = rname;
int i = rname.indexOf(':');
if (i > 0)
{
prefix
= rname.substring(0, i);
lname
= rname.substring(i + 1);
}
return new String[] { prefix, lname };
}
@Override
protected
void finishEmpty() throws IOException
{
finishOpen();
finishClose();
}
@Override
protected
void finishClose() throws IOException
{
try
{
String
name = string(elem);
contentHandler.endElement("",
name, name);
this.namespaces
= namespaces.getParent();
}
catch (final SAXException e)
{
throw
new IOException(e.getMessage());
}
}
@Override
protected
void finishText(byte[] text) throws IOException
{
try
{
String
s = string(text);
final
char[] c = s.toCharArray();
contentHandler.characters(c,
0, c.length);
}
catch (final SAXException e)
{
throw
new IOException(e.getMessage());
}
}
@Override
protected
void finishComment(byte[] comment) throws IOException
{
if (lexicalHandler != null)
{
try
{
String s = string(comment);
final char[] c = s.toCharArray();
lexicalHandler.comment(c, 0, c.length);
}
catch
(final SAXException e)
{
throw new IOException(e.getMessage());
}
}
}
@Override
protected
void finishPi(byte[] n, byte[] v) throws IOException
{
//ignored
}
@Override
protected
void atomic(Item i) throws IOException
{
//ignored
}
}
class NSDecl
{
private
final NSDecl parent;
private
Map<String, String> decls;
public
NSDecl(NSDecl parent)
{
this.parent = parent;
}
public
NSDecl getParent()
{
return parent;
}
public
void put(String prefix, String uri)
{
if (decls == null)
{
decls
= new HashMap<String, String>();
}
decls.put(prefix, uri);
}
public
String get(String prefix)
{
String ns = null;
for (NSDecl c = this; c != null; c = c.parent)
{
if (c.decls
!= null)
{
ns = c.decls.get(prefix);
if (ns != null)
{
break;
}
}
}
return ns != null ? ns : "";
}
}