Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
org.hl7.fhir.utilities.xml.XMLWriter Maven / Gradle / Ivy
package org.hl7.fhir.utilities.xml;
/*
Copyright (c) 2011+, HL7, Inc.
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of HL7 nor the names of its contributors may be used to
endorse or promote products derived from this software without specific
prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import org.hl7.fhir.utilities.ElementDecoration;
/**
* XML Writer class.
*/
public class XMLWriter extends OutputStreamWriter implements IXMLWriter {
private boolean xmlHeader = true;
private String charset;
private boolean prettyBase;
private boolean prettyHeader;
private boolean pendingClose;
private boolean pendingOpen;
private String pendingComment;
private int lineType = LINE_UNIX;
private OutputStream stream;
private boolean started = false;
private String[] specialAttributeNames = new String[] {"id", "name" };
private boolean sortAttributes;
private int attributeLineWrap;
private boolean xml1_1;
public final static int LINE_UNIX = 0;
public final static int LINE_WINDOWS = 1;
public XMLWriter(OutputStream stream, String charset, boolean xml1_1) throws UnsupportedEncodingException {
super(stream, charset);
this.stream = stream;
this.charset = charset;
this.xml1_1 = xml1_1;
}
public XMLWriter(OutputStream stream, String charset) throws UnsupportedEncodingException {
super(stream, charset);
this.stream = stream;
this.charset = charset;
this.xml1_1 = false;
}
protected boolean condition(boolean bTest, String message) throws IOException {
if (!bTest)
throw new IOException(message);
return bTest;
}
// -- writing context ------------------------------------------------
/**
* Returns the encoding.
*
* @param charset
* @return encoding
* @throws IOException
*/
public static String getXMLCharsetName(String charset) throws IOException {
if (charset == null || charset.equals(""))
return "UTF-8";
else if (charset.equals("US-ASCII"))
return "UTF-8";
else if (XMLUtil.charSetImpliesAscii(charset))
return "ISO-8859-1";
else if (charset.equals("UTF-8"))
return "UTF-8";
else if (charset.equals("UTF-16") || charset.equals("UTF-16BE") || charset.equals("UTF-16LE"))
return "UTF-16";
else
throw new IOException("Unknown charset encoding "+charset);
}
/* (non-Javadoc)
* @see org.eclipse.ohf.utilities.xml.IXMLWriter#start()
*/
@Override
public void start() throws IOException {
condition(!started, "attempt to start after starting");
levels.clear();
attributes = null;
try {
if (xmlHeader) {
write("");
if (prettyBase || prettyHeader)
write(lineType == LINE_UNIX ? "\n" : "\r\n");
}
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
throw new IOException(e.getMessage());
}
started = true;
}
private void checkStarted () throws IOException {
condition(started, "not started");
}
private void checkInElement() throws IOException {
condition(levels.size() > 0, "not in an element");
}
// -- attributes ----------------------------------------------------
private String[][] attributes;
private void addAttribute(String name, String value) throws IOException {
addAttribute(name, value, false);
}
private void addAttribute(String name, String value, boolean noLines) throws IOException {
if (!XMLUtil.isNMToken(name))
throw new IOException("XML name "+name+" is not valid for value '"+value+"'");
newLevelIfRequired();
value = XMLUtil.escapeXML(value, charset, noLines);
if (attributes == null)
attributes = new String[][] {{name, value}};
else {
String[][] newattr = new String[attributes.length+1][];
for (int i = 0; i < attributes.length; i++) {
condition(!attributes[i][0].equals(name), "attempt to define attribute with name "+name+" more than once for value '"+value+"'");
newattr[i] = attributes[i];
}
attributes = newattr;
attributes[attributes.length-1] = new String[] {name, value};
}
}
protected String getAttribute(String name) {
if (attributes != null) {
for (int i = 0; i < attributes.length; i++) {
if (attributes[i][0].equals(name)) {
return attributes[i][1];
}
}
}
return null;
}
protected void setAttribute(String name, String value) throws IOException {
newLevelIfRequired();
if (attributes == null)
addAttribute(name, value, false);
else {
for (int i = 0; i < attributes.length; i++) {
if (attributes[i][0].equals(name)) {
attributes[i][1] = XMLUtil.escapeXML(value, charset, false);
return;
}
}
addAttribute(name, value);
}
}
protected void commitAttributes() throws IOException {
}
private boolean nameIsSpecial(String name) {
for (int i = 0; i < specialAttributeNames.length; i++) {
String n = specialAttributeNames[i];
if (n.equalsIgnoreCase(name))
return true;
}
return false;
}
private void writeAttributes(int col) throws IOException {
commitAttributes();
if (attributes != null && sortAttributes)
sortAttributes();
int c = col;
c = writeAttributeSet(true, c, col);
writeAttributeSet(false, c, col);
attributes = null;
}
private void sortAttributes() {
// bubble sort - look, it's easy
for (int i = 0; i < attributes.length - 1; i++) {
for (int j = 0; j < attributes.length - 1; j++) {
if (String.CASE_INSENSITIVE_ORDER.compare(attributes[j][0], attributes[j+1][0]) < 0) {
String[] t = attributes[j];
attributes[j] = attributes[j+1];
attributes[j+1] = t;
}
}
}
}
private int writeAttributeSet(boolean special, int col, int wrap) throws IOException {
// first pass: name, id
if (attributes != null) {
for (int i=0; i < attributes.length; i++) {
String[] element = attributes[i];
if (nameIsSpecial(element[0]) == special) {
col = col + element[0].length()+element[1].length() + 4;
if (isPretty() && attributeLineWrap > 0 && col > attributeLineWrap && col > wrap) {
write(lineType == LINE_UNIX ? "\n" : "\r\n");
for (int j = 0; j < wrap; j++)
write(" ");
col = wrap;
}
write(' ');
write(element[0]);
write("=\"");
if (element[1] != null)
write(xmlEscape(element[1]));
write("\"");
}
}
}
return col;
}
protected String xmlEscape(String s) {
StringBuilder b = new StringBuilder();
for (char c : s.toCharArray()) {
if (c < ' ') {
b.append("");
b.append(Integer.toHexString(c).toUpperCase());
b.append(";");
} else
b.append(c);
}
return b.toString();
}
/* (non-Javadoc)
* @see org.eclipse.ohf.utilities.xml.IXMLWriter#attribute(java.lang.String, java.lang.String, java.lang.String, boolean)
*/
@Override
public void attribute(String namespace, String name, String value, boolean onlyIfNotEmpty) throws IOException {
if (!onlyIfNotEmpty || value != null && !value.equals(""))
attribute(namespace, name, value);
}
/* (non-Javadoc)
* @see org.eclipse.ohf.utilities.xml.IXMLWriter#attribute(java.lang.String, java.lang.String, java.lang.String)
*/
@Override
public void attribute(String namespace, String name, String value) throws IOException {
checkStarted();
if (namespace == null || namespace.equals(""))
addAttribute(name, value);
else
addAttribute(getNSAbbreviation(namespace)+name, value);
}
/* (non-Javadoc)
* @see org.eclipse.ohf.utilities.xml.IXMLWriter#attribute(java.lang.String, java.lang.String, boolean)
*/
@Override
public void attribute(String name, String value, boolean onlyIfNotEmpty) throws IOException {
if (!onlyIfNotEmpty || value != null && !value.equals(""))
attribute(name, value);
}
/* (non-Javadoc)
* @see org.eclipse.ohf.utilities.xml.IXMLWriter#attribute(java.lang.String, java.lang.String)
*/
@Override
public void attribute(String name, String value) throws IOException {
checkStarted();
addAttribute(name, value);
}
/* (non-Javadoc)
* @see org.eclipse.ohf.utilities.xml.IXMLWriter#attributeNoLines(java.lang.String, java.lang.String)
*/
@Override
public void attributeNoLines(String name, String value) throws IOException {
checkStarted();
addAttribute(name, value, true);
}
// -- levels -------------------------------------------------
private XMLWriterStateStack levels = new XMLWriterStateStack();
private void newLevelIfRequired() throws IOException {
if (!pendingOpen) {
if (!levels.empty())
levels.current().seeChild();
XMLWriterState level = new XMLWriterState();
level.setPretty(isPretty());
levels.push(level);
pendingOpen = true;
}
}
// -- namespaces ---------------------------------------------
private void defineNamespace(String namespace, String abbrev) throws IOException {
checkStarted();
if (namespace != null && !namespace.equals("")) {
if ("".equals(abbrev))
abbrev = null;
newLevelIfRequired();
levels.current().addNamespaceDefn(namespace, abbrev);
if (abbrev == null)
addAttribute("xmlns", namespace);
else
addAttribute("xmlns:"+abbrev, namespace);
}
}
/* (non-Javadoc)
* @see org.eclipse.ohf.utilities.xml.IXMLWriter#findByNamespace(java.lang.String)
*/
public XMLNamespace findByNamespace(String namespace) {
for (int i = levels.size() - 1; i >= 0; i--) {
XMLNamespace ns = levels.item(i).getDefnByNamespace(namespace);
if (ns != null)
return ns;
}
return null;
}
/* (non-Javadoc)
* @see org.eclipse.ohf.utilities.xml.IXMLWriter#namespaceDefined(java.lang.String)
*/
@Override
public boolean namespaceDefined(String namespace) {
return namespace == null || namespace.equals("") || findByNamespace(namespace) != null;
}
/* (non-Javadoc)
* @see org.eclipse.ohf.utilities.xml.IXMLWriter#findByAbbreviation(java.lang.String)
*/
public XMLNamespace findByAbbreviation(String abbreviation) {
for (int i = levels.size() - 1; i >= 0; i--) {
XMLNamespace ns = levels.item(i).getDefnByAbbreviation(abbreviation);
if (ns != null)
return ns;
}
return null;
}
/* (non-Javadoc)
* @see org.eclipse.ohf.utilities.xml.IXMLWriter#abbreviationDefined(java.lang.String)
*/
@Override
public boolean abbreviationDefined(String abbreviation) {
return findByAbbreviation(abbreviation) != null;
}
protected XMLNamespace findDefaultNamespace() {
for (int i = levels.size() - 1; i >= 0; i--) {
XMLNamespace ns = levels.item(i).getDefaultNamespace();
if (ns != null)
return ns;
}
return null;
}
/* (non-Javadoc)
* @see org.eclipse.ohf.utilities.xml.IXMLWriter#getDefaultNamespace()
*/
@Override
public String getDefaultNamespace() {
XMLNamespace ns = findDefaultNamespace();
if (ns == null)
return null;
else
return ns.getNamespace();
}
/* (non-Javadoc)
* @see org.eclipse.ohf.utilities.xml.IXMLWriter#namespace(java.lang.String)
*/
@Override
public void namespace(String namespace) throws IOException {
if (!namespaceDefined(namespace)) {
int index = 0;
while (abbreviationDefined("ns"+Integer.toString(index)))
index++;
defineNamespace(namespace, "ns"+Integer.toString(index));
}
}
/* (non-Javadoc)
* @see org.eclipse.ohf.utilities.xml.IXMLWriter#defaultNamespace(java.lang.String)
*
* Replace defaultNamespace()
*/
@Override
public void setDefaultNamespace(String namespace) throws IOException {
if ((namespace == null && getDefaultNamespace() != null) ||
(namespace != null && !namespace.equals(getDefaultNamespace())))
defineNamespace(namespace, "");
}
/* (non-Javadoc)
* @see org.eclipse.ohf.utilities.xml.IXMLWriter#namespace(java.lang.String, java.lang.String)
*/
@Override
public void namespace(String namespace, String abbreviation) throws IOException {
XMLNamespace ns = findByAbbreviation(abbreviation);
if (ns == null || !ns.getNamespace().equals(namespace))
defineNamespace(namespace, abbreviation);
}
private String getNSAbbreviation(String namespace) throws IOException {
if ("http://www.w3.org/XML/1998/namespace".equals(namespace))
return "xml:";
if (namespace == null || "".equals(namespace) || "noNamespace".equals(namespace))
return "";
XMLNamespace ns = findByNamespace(namespace);
if (ns == null)
throw new IOException("Namespace "+namespace+" is not defined");
else if (ns.getAbbreviation() == null)
return "";
else
return ns.getAbbreviation()+":";
}
// -- public API -----------------------------------------------------------
/* (non-Javadoc)
* @see org.eclipse.ohf.utilities.xml.IXMLWriter#comment(java.lang.String, boolean)
*/
@Override
public void comment(String comment, boolean doPretty) throws IOException {
checkStarted();
if (pendingClose) {
write('>');
writePendingComment();
pendingClose = false;
}
if (doPretty) {
writePretty();
}
if (levels.inComment())
write(" ");
if (doPretty && !isPretty())
writePretty();
}
private void writePendingComment() throws IOException {
if (pendingComment != null) {
if (isPretty())
write(" ");
if (levels.inComment())
write("");
}
}
/* (non-Javadoc)
* @see org.eclipse.ohf.utilities.xml.IXMLWriter#open(java.lang.String, java.lang.String)
*/
@Override
public void enter(String namespace, String name) throws IOException {
enter(namespace, name, null);
}
/* (non-Javadoc)
* @see org.eclipse.ohf.utilities.xml.IXMLWriter#open(java.lang.String, java.lang.String, java.lang.String)
*/
@Override
public void enter(String namespace, String name, String comment) throws IOException {
if (name == null)
throw new Error("name == null");
if (!XMLUtil.isNMToken(name))
throw new IOException("XML name "+name+" is not valid");
checkStarted();
if (pendingClose) {
write('>');
writePendingComment();
pendingClose = false;
}
if (name == null) {
throw new IOException("name is null");
}
newLevelIfRequired();
levels.current().setName(name);
levels.current().setNamespace(namespace);
int col = writePretty();
write('<');
if (namespace == null) {
write(name);
col = col + name.length()+1;
} else {
String n = getNSAbbreviation(namespace)+name;
write(n);
col = col + n.length()+1;
}
writeAttributes(col);
pendingOpen = false;
pendingClose = true;
pendingComment = comment;
}
/* (non-Javadoc)
* @see org.eclipse.ohf.utilities.xml.IXMLWriter#close(java.lang.String)
*/
@Override
public void exit(String name) throws IOException {
checkStarted();
if (levels.empty())
throw new IOException("Unable to close null|"+name+", nothing to close");
if (levels.current().getNamespace() != null || !levels.current().getName().equals(name))
throw new IOException("Unable to close null|"+name+", found "+levels.current().getNamespace()+"|"+levels.current().getName());
exit();
}
/* (non-Javadoc)
* @see org.eclipse.ohf.utilities.xml.IXMLWriter#close(java.lang.String, java.lang.String)
*/
@Override
public void exit(String namespace, String name) throws IOException {
checkStarted();
if (levels.empty())
throw new IOException("Unable to close "+namespace+"|"+name+", nothing to close");
if (levels == null)
throw new Error("levels = null");
if (levels.current() == null)
throw new Error("levels.current() = null");
if (levels.current().getName() == null)
throw new Error("levels.current().getName() = null");
if (levels.current().getNamespace() == null)
throw new Error("levels.current().getNamespace() = null");
if (name == null)
throw new Error("name = null");
if (namespace == null)
throw new Error("namespace = null");
if (!levels.current().getNamespace().equals(namespace) || !levels.current().getName().equals(name))
throw new IOException("Unable to close "+namespace+"|"+name+", found "+levels.current().getNamespace()+"|"+levels.current().getName());
exit();
}
/* (non-Javadoc)
* @see org.eclipse.ohf.utilities.xml.IXMLWriter#closeToLevel(int)
*/
@Override
public void exitToLevel(int count) throws IOException {
checkStarted();
while (levels.size() > count)
exit();
}
/* (non-Javadoc)
* @see org.eclipse.ohf.utilities.xml.IXMLWriter#close()
*/
@Override
public void close() throws IOException {
checkStarted();
if (!levels.empty())
throw new IOException("Called close before exiting all opened elements");
super.close();
}
@Override
public void end() throws IOException {
checkStarted();
if (!levels.empty())
throw new IOException("Called end() before exiting all opened elements");
flush();
}
@Override
public void exit() throws IOException {
checkStarted();
if (levels.empty()) {
throw new IOException("Called exit one too many times");
} else {
if (pendingClose) {
write("/>");
writePendingComment();
pendingClose = false;
} else {
if (levels.current().hasChildren())
writePretty();
write("");
if (levels.current().getNamespace() == null)
write(levels.current().getName());
else
write(getNSAbbreviation(levels.current().getNamespace())+levels.current().getName());
write('>');
}
levels.pop();
}
}
/* (non-Javadoc)
* @see org.eclipse.ohf.utilities.xml.IXMLWriter#open(java.lang.String)
*/
@Override
public void enter(String name) throws IOException {
enter(null, name);
}
/* (non-Javadoc)
* @see org.eclipse.ohf.utilities.xml.IXMLWriter#element(java.lang.String, java.lang.String, java.lang.String, boolean)
*/
@Override
public void element(String namespace, String name, String content, boolean onlyIfNotEmpty) throws IOException {
if (!onlyIfNotEmpty || content != null && !content.equals(""))
element(namespace, name, content);
}
/* (non-Javadoc)
* @see org.eclipse.ohf.utilities.xml.IXMLWriter#element(java.lang.String, java.lang.String, java.lang.String, java.lang.String)
*/
@Override
public void element(String namespace, String name, String content, String comment) throws IOException {
if (!XMLUtil.isNMToken(name))
throw new IOException("XML name "+name+" is not valid");
enter(namespace, name, comment);
text(content);
exit();
}
/* (non-Javadoc)
* @see org.eclipse.ohf.utilities.xml.IXMLWriter#element(java.lang.String, java.lang.String, java.lang.String)
*/
@Override
public void element(String namespace, String name, String content) throws IOException {
if (!XMLUtil.isNMToken(name))
throw new IOException("XML name "+name+" is not valid");
enter(namespace, name);
text(content);
exit();
}
/* (non-Javadoc)
* @see org.eclipse.ohf.utilities.xml.IXMLWriter#element(java.lang.String, java.lang.String, boolean)
*/
@Override
public void element(String name, String content, boolean onlyIfNotEmpty) throws IOException {
if (!onlyIfNotEmpty || content != null && !content.equals(""))
element(null, name, content);
}
/* (non-Javadoc)
* @see org.eclipse.ohf.utilities.xml.IXMLWriter#element(java.lang.String, java.lang.String)
*/
@Override
public void element(String name, String content) throws IOException {
element(null, name, content);
}
@Override
public void element(String name) throws IOException {
element(null, name, null);
}
/* (non-Javadoc)
* @see org.eclipse.ohf.utilities.xml.IXMLWriter#text(java.lang.String)
*/
@Override
public void text(String content) throws IOException {
text(content, false);
}
/* (non-Javadoc)
* @see org.eclipse.ohf.utilities.xml.IXMLWriter#text(java.lang.String, boolean)
*
* Replace escapeText()
*/
@Override
public void text(String content, boolean dontEscape) throws IOException {
checkInElement();
if (content != null) {
if (pendingClose) {
write(">");
writePendingComment();
pendingClose = false;
}
if (dontEscape)
write(content);
else
write(XMLUtil.escapeXML(content, charset, false));
}
}
/* (non-Javadoc)
* @see org.eclipse.ohf.utilities.xml.IXMLWriter#cData(java.lang.String)
*/
@Override
public void cData(String text) throws IOException {
text("");
}
/* (non-Javadoc)
* @see org.eclipse.ohf.utilities.xml.IXMLWriter#writeBytes(byte[])
*/
@Override
public void writeBytes(byte[] bytes) throws IOException {
checkInElement();
if (pendingClose) {
write(">");
writePendingComment();
pendingClose = false;
}
flush();
stream.write(bytes);
}
/* (non-Javadoc)
* @see org.eclipse.ohf.utilities.xml.IXMLWriter#isPretty()
*/
@Override
public boolean isPretty() throws IOException {
return (levels == null || levels.empty()) ? prettyBase : levels.current().isPretty();
}
/* (non-Javadoc)
* @see org.eclipse.ohf.utilities.xml.IXMLWriter#setPretty(boolean)
*/
@Override
public void setPretty(boolean pretty) throws IOException {
if (levels == null || levels.empty())
this.prettyBase = pretty;
else
levels.current().setPretty(pretty);
}
/* (non-Javadoc)
* @see org.eclipse.ohf.utilities.xml.IXMLWriter#startCommentBlock()
*/
@Override
public void startCommentBlock() throws IOException {
if (levels.inComment())
throw new IOException("cannot nest comments");
levels.current().setInComment(true);
if (isPretty())
writePretty();
write("");
if (isPretty())
writePretty();
levels.current().setInComment(false);
}
public boolean isSortAttributes() {
return sortAttributes;
}
public void setSortAttributes(boolean sortAttributes) {
this.sortAttributes = sortAttributes;
}
public boolean isPrettyHeader() {
return prettyHeader;
}
public void setPrettyHeader(boolean pretty) {
this.prettyHeader = pretty;
}
public int writePretty() throws IOException {
return writePretty(true);
}
public int writePretty(boolean eoln) throws IOException {
if (isPretty()) {
if (eoln)
write(lineType == LINE_UNIX ? "\n" : "\r\n");
for (int i = 0; i < levels.size() - 1; i++)
write(" ");
return (levels.size() - 1) * 2;
} else
return 0;
}
public int getLineType() {
return lineType;
}
public void setLineType(int lineType) {
this.lineType = lineType;
}
public boolean isXmlHeader() {
return xmlHeader;
}
public void setXmlHeader(boolean xmlHeader) {
this.xmlHeader = xmlHeader;
}
public String[] getSpecialAttributeNames() {
return specialAttributeNames;
}
public void setSpecialAttributeNames(String[] specialAttributeNames) {
this.specialAttributeNames = specialAttributeNames;
}
public int getAttributeLineWrap() {
return attributeLineWrap;
}
public void setAttributeLineWrap(int attributeLineWrap) {
this.attributeLineWrap = attributeLineWrap;
}
@Override
public void escapedText(String content) throws IOException {
text("");
int i = content.length();
if (isPretty())
while (i > 0 && (content.charAt(i-1) == '\r' || content.charAt(i-1) == '\n'))
i--;
write(content.substring(0, i));
}
public void processingInstruction(String value) throws IOException {
write(""+value+"?>");
if (isPrettyHeader())
write("\r\n");
}
@Override
public void link(String href) {
// ignore this
}
@Override
public void anchor(String name) {
// ignore this
}
@Override
public void decorate(ElementDecoration element) throws IOException {
// nothing...
}
@Override
public void setSchemaLocation(String ns, String loc) throws IOException {
namespace("http://www.w3.org/2001/XMLSchema-instance", "xsi");
attribute("http://www.w3.org/2001/XMLSchema-instance", "schemaLocation", ns+" "+loc);
}
@Override
public void externalLink(String ref) {
// ignore this
}
@Override
public boolean canElide() { return false; }
@Override
public void attributeElide() {
// ignore this
}
@Override
public void elide() throws IOException {
// ignore this
}
}