thank you for quickly attacking the problem! But sorry, but the problem is not fixed.I get the same error.
The parent references within the serialized node fragment should now be correctly resolved. Do you have an idea what could be the reason for the NPE?
[...] I propose to add a standard SAX serializer to BaseX. This would be a very useful extension.
Here is my implementation:
Thanks. I have slightly reworked your code and added it to our code base [1]. Could you give us some feedback if it works as expected? By the way, I have added a parse(Item) function in order to ensure that an item has been specified when starting the parsing process.
By the way, it would be great if you could contribute one or more minimized test methods which we could then embed as JUnit test. This will ensure that your code will continue to work as expected..
Christian
[1] https://github.com/BaseXdb/basex/commit/eb7e1d51de6a6634e9b858976a683d9cb3cf...
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 : ""; }
} _______________________________________________ BaseX-Talk mailing list BaseX-Talk@mailman.uni-konstanz.de https://mailman.uni-konstanz.de/mailman/listinfo/basex-talk