1
0
mirror of https://github.com/esp8266/Arduino.git synced 2025-06-17 22:23:10 +03:00

Importing Processing rev. 5503 (1.0.3).

This commit is contained in:
David A. Mellis
2009-05-31 15:53:33 +00:00
parent 40982627a3
commit 22ed6cdb73
767 changed files with 341874 additions and 0 deletions

View File

@ -0,0 +1,193 @@
/* CDATAReader.java NanoXML/Java
*
* $Revision: 1.3 $
* $Date: 2002/01/04 21:03:28 $
* $Name: RELEASE_2_2_1 $
*
* This file is part of NanoXML 2 for Java.
* Copyright (C) 2000-2002 Marc De Scheemaecker, All Rights Reserved.
*
* This software is provided 'as-is', without any express or implied warranty.
* In no event will the authors be held liable for any damages arising from the
* use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software in
* a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
*
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
*
* 3. This notice may not be removed or altered from any source distribution.
*/
package processing.xml;
import java.io.Reader;
import java.io.IOException;
/**
* This reader reads data from another reader until the end of a CDATA section
* (]]>) has been encountered.
*
* @author Marc De Scheemaecker
* @version $Name: RELEASE_2_2_1 $, $Revision: 1.3 $
*/
class CDATAReader
extends Reader
{
/**
* The encapsulated reader.
*/
private StdXMLReader reader;
/**
* Saved char.
*/
private char savedChar;
/**
* True if the end of the stream has been reached.
*/
private boolean atEndOfData;
/**
* Creates the reader.
*
* @param reader the encapsulated reader
*/
CDATAReader(StdXMLReader reader)
{
this.reader = reader;
this.savedChar = 0;
this.atEndOfData = false;
}
/**
* Cleans up the object when it's destroyed.
*/
protected void finalize()
throws Throwable
{
this.reader = null;
super.finalize();
}
/**
* Reads a block of data.
*
* @param buffer where to put the read data
* @param offset first position in buffer to put the data
* @param size maximum number of chars to read
*
* @return the number of chars read, or -1 if at EOF
*
* @throws java.io.IOException
* if an error occurred reading the data
*/
public int read(char[] buffer,
int offset,
int size)
throws IOException
{
int charsRead = 0;
if (this.atEndOfData) {
return -1;
}
if ((offset + size) > buffer.length) {
size = buffer.length - offset;
}
while (charsRead < size) {
char ch = this.savedChar;
if (ch == 0) {
ch = this.reader.read();
} else {
this.savedChar = 0;
}
if (ch == ']') {
char ch2 = this.reader.read();
if (ch2 == ']') {
char ch3 = this.reader.read();
if (ch3 == '>') {
this.atEndOfData = true;
break;
}
this.savedChar = ch2;
this.reader.unread(ch3);
} else {
this.reader.unread(ch2);
}
}
buffer[charsRead] = ch;
charsRead++;
}
if (charsRead == 0) {
charsRead = -1;
}
return charsRead;
}
/**
* Skips remaining data and closes the stream.
*
* @throws java.io.IOException
* if an error occurred reading the data
*/
public void close()
throws IOException
{
while (! this.atEndOfData) {
char ch = this.savedChar;
if (ch == 0) {
ch = this.reader.read();
} else {
this.savedChar = 0;
}
if (ch == ']') {
char ch2 = this.reader.read();
if (ch2 == ']') {
char ch3 = this.reader.read();
if (ch3 == '>') {
break;
}
this.savedChar = ch2;
this.reader.unread(ch3);
} else {
this.reader.unread(ch2);
}
}
}
this.atEndOfData = true;
}
}

View File

@ -0,0 +1,212 @@
/* ContentReader.java NanoXML/Java
*
* $Revision: 1.4 $
* $Date: 2002/01/04 21:03:28 $
* $Name: RELEASE_2_2_1 $
*
* This file is part of NanoXML 2 for Java.
* Copyright (C) 2000-2002 Marc De Scheemaecker, All Rights Reserved.
*
* This software is provided 'as-is', without any express or implied warranty.
* In no event will the authors be held liable for any damages arising from the
* use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software in
* a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
*
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
*
* 3. This notice may not be removed or altered from any source distribution.
*/
package processing.xml;
import java.io.Reader;
import java.io.IOException;
/**
* This reader reads data from another reader until a new element has
* been encountered.
*
* @author Marc De Scheemaecker
* @version $Name: RELEASE_2_2_1 $, $Revision: 1.4 $
*/
class ContentReader
extends Reader
{
/**
* The encapsulated reader.
*/
private StdXMLReader reader;
/**
* Buffer.
*/
private String buffer;
/**
* Pointer into the buffer.
*/
private int bufferIndex;
/**
* The entity resolver.
*/
private XMLEntityResolver resolver;
/**
* Creates the reader.
*
* @param reader the encapsulated reader
* @param resolver the entity resolver
* @param buffer data that has already been read from <code>reader</code>
*/
ContentReader(StdXMLReader reader,
XMLEntityResolver resolver,
String buffer)
{
this.reader = reader;
this.resolver = resolver;
this.buffer = buffer;
this.bufferIndex = 0;
}
/**
* Cleans up the object when it's destroyed.
*/
protected void finalize()
throws Throwable
{
this.reader = null;
this.resolver = null;
this.buffer = null;
super.finalize();
}
/**
* Reads a block of data.
*
* @param outputBuffer where to put the read data
* @param offset first position in buffer to put the data
* @param size maximum number of chars to read
*
* @return the number of chars read, or -1 if at EOF
*
* @throws java.io.IOException
* if an error occurred reading the data
*/
public int read(char[] outputBuffer,
int offset,
int size)
throws IOException
{
try {
int charsRead = 0;
int bufferLength = this.buffer.length();
if ((offset + size) > outputBuffer.length) {
size = outputBuffer.length - offset;
}
while (charsRead < size) {
String str = "";
char ch;
if (this.bufferIndex >= bufferLength) {
str = XMLUtil.read(this.reader, '&');
ch = str.charAt(0);
} else {
ch = this.buffer.charAt(this.bufferIndex);
this.bufferIndex++;
outputBuffer[charsRead] = ch;
charsRead++;
continue; // don't interprete chars in the buffer
}
if (ch == '<') {
this.reader.unread(ch);
break;
}
if ((ch == '&') && (str.length() > 1)) {
if (str.charAt(1) == '#') {
ch = XMLUtil.processCharLiteral(str);
} else {
XMLUtil.processEntity(str, this.reader, this.resolver);
continue;
}
}
outputBuffer[charsRead] = ch;
charsRead++;
}
if (charsRead == 0) {
charsRead = -1;
}
return charsRead;
} catch (XMLParseException e) {
throw new IOException(e.getMessage());
}
}
/**
* Skips remaining data and closes the stream.
*
* @throws java.io.IOException
* if an error occurred reading the data
*/
public void close()
throws IOException
{
try {
int bufferLength = this.buffer.length();
for (;;) {
String str = "";
char ch;
if (this.bufferIndex >= bufferLength) {
str = XMLUtil.read(this.reader, '&');
ch = str.charAt(0);
} else {
ch = this.buffer.charAt(this.bufferIndex);
this.bufferIndex++;
continue; // don't interprete chars in the buffer
}
if (ch == '<') {
this.reader.unread(ch);
break;
}
if ((ch == '&') && (str.length() > 1)) {
if (str.charAt(1) != '#') {
XMLUtil.processEntity(str, this.reader, this.resolver);
}
}
}
} catch (XMLParseException e) {
throw new IOException(e.getMessage());
}
}
}

View File

@ -0,0 +1,157 @@
/* PIReader.java NanoXML/Java
*
* $Revision: 1.3 $
* $Date: 2002/01/04 21:03:28 $
* $Name: RELEASE_2_2_1 $
*
* This file is part of NanoXML 2 for Java.
* Copyright (C) 2000-2002 Marc De Scheemaecker, All Rights Reserved.
*
* This software is provided 'as-is', without any express or implied warranty.
* In no event will the authors be held liable for any damages arising from the
* use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software in
* a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
*
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
*
* 3. This notice may not be removed or altered from any source distribution.
*/
package processing.xml;
import java.io.Reader;
import java.io.IOException;
/**
* This reader reads data from another reader until the end of a processing
* instruction (?&gt;) has been encountered.
*
* @author Marc De Scheemaecker
* @version $Name: RELEASE_2_2_1 $, $Revision: 1.3 $
*/
class PIReader
extends Reader
{
/**
* The encapsulated reader.
*/
private StdXMLReader reader;
/**
* True if the end of the stream has been reached.
*/
private boolean atEndOfData;
/**
* Creates the reader.
*
* @param reader the encapsulated reader
*/
PIReader(StdXMLReader reader)
{
this.reader = reader;
this.atEndOfData = false;
}
/**
* Cleans up the object when it's destroyed.
*/
protected void finalize()
throws Throwable
{
this.reader = null;
super.finalize();
}
/**
* Reads a block of data.
*
* @param buffer where to put the read data
* @param offset first position in buffer to put the data
* @param size maximum number of chars to read
*
* @return the number of chars read, or -1 if at EOF
*
* @throws java.io.IOException
* if an error occurred reading the data
*/
public int read(char[] buffer,
int offset,
int size)
throws IOException
{
if (this.atEndOfData) {
return -1;
}
int charsRead = 0;
if ((offset + size) > buffer.length) {
size = buffer.length - offset;
}
while (charsRead < size) {
char ch = this.reader.read();
if (ch == '?') {
char ch2 = this.reader.read();
if (ch2 == '>') {
this.atEndOfData = true;
break;
}
this.reader.unread(ch2);
}
buffer[charsRead] = ch;
charsRead++;
}
if (charsRead == 0) {
charsRead = -1;
}
return charsRead;
}
/**
* Skips remaining data and closes the stream.
*
* @throws java.io.IOException
* if an error occurred reading the data
*/
public void close()
throws IOException
{
while (! this.atEndOfData) {
char ch = this.reader.read();
if (ch == '?') {
char ch2 = this.reader.read();
if (ch2 == '>') {
this.atEndOfData = true;
}
}
}
}
}

View File

@ -0,0 +1,356 @@
/* StdXMLBuilder.java NanoXML/Java
*
* $Revision: 1.3 $
* $Date: 2002/01/04 21:03:28 $
* $Name: RELEASE_2_2_1 $
*
* This file is part of NanoXML 2 for Java.
* Copyright (C) 2000-2002 Marc De Scheemaecker, All Rights Reserved.
*
* This software is provided 'as-is', without any express or implied warranty.
* In no event will the authors be held liable for any damages arising from the
* use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software in
* a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
*
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
*
* 3. This notice may not be removed or altered from any source distribution.
*/
package processing.xml;
import java.io.IOException;
import java.io.Reader;
import java.util.Stack;
/**
* StdXMLBuilder is a concrete implementation of IXMLBuilder which creates a
* tree of IXMLElement from an XML data source.
*
* @see processing.xml.XMLElement
*
* @author Marc De Scheemaecker
* @version $Name: RELEASE_2_2_1 $, $Revision: 1.3 $
*/
public class StdXMLBuilder
{
/**
* This stack contains the current element and its parents.
*/
private Stack<XMLElement> stack;
/**
* The root element of the parsed XML tree.
*/
private XMLElement root;
private XMLElement parent;
/**
* Prototype element for creating the tree.
*/
//private XMLElement prototype;
/**
* Creates the builder.
*/
public StdXMLBuilder()
{
this.stack = null;
this.root = null;
//this(new XMLElement());
}
public StdXMLBuilder(XMLElement parent)
{
this.parent = parent;
}
/**
* Creates the builder.
*
* @param prototype the prototype to use when building the tree.
*/
// public StdXMLBuilder(XMLElement prototype)
// {
// this.stack = null;
// this.root = null;
// this.prototype = prototype;
// }
/**
* Cleans up the object when it's destroyed.
*/
protected void finalize()
throws Throwable
{
//this.prototype = null;
this.root = null;
this.stack.clear();
this.stack = null;
super.finalize();
}
/**
* This method is called before the parser starts processing its input.
*
* @param systemID the system ID of the XML data source.
* @param lineNr the line on which the parsing starts.
*/
public void startBuilding(String systemID,
int lineNr)
{
this.stack = new Stack<XMLElement>();
this.root = null;
}
/**
* This method is called when a processing instruction is encountered.
* PIs with target "xml" are handled by the parser.
*
* @param target the PI target.
* @param reader to read the data from the PI.
*/
public void newProcessingInstruction(String target,
Reader reader)
{
// nothing to do
}
/**
* This method is called when a new XML element is encountered.
*
* @see #endElement
*
* @param name the name of the element.
* @param nsPrefix the prefix used to identify the namespace. If no
* namespace has been specified, this parameter is null.
* @param nsURI the URI associated with the namespace. If no
* namespace has been specified, or no URI is
* associated with nsPrefix, this parameter is null.
* @param systemID the system ID of the XML data source.
* @param lineNr the line in the source where the element starts.
*/
public void startElement(String name,
String nsPrefix,
String nsURI,
String systemID,
int lineNr)
{
String fullName = name;
if (nsPrefix != null) {
fullName = nsPrefix + ':' + name;
}
//XMLElement elt = this.prototype.createElement(fullName, nsURI,
// systemID, lineNr);
// XMLElement elt = new XMLElement(fullName, nsURI, systemID, lineNr);
//
// if (this.stack.empty()) {
// this.root = elt;
// } else {
// XMLElement top = (XMLElement) this.stack.peek();
// top.addChild(elt);
// }
// stack.push(elt);
if (this.stack.empty()) {
//System.out.println("setting root");
parent.set(fullName, nsURI, systemID, lineNr);
stack.push(parent);
root = parent;
} else {
XMLElement top = (XMLElement) this.stack.peek();
//System.out.println("stack has " + top.getName());
XMLElement elt = new XMLElement(fullName, nsURI, systemID, lineNr);
top.addChild(elt);
stack.push(elt);
}
}
/**
* This method is called when the attributes of an XML element have been
* processed.
*
* @see #startElement
* @see #addAttribute
*
* @param name the name of the element.
* @param nsPrefix the prefix used to identify the namespace. If no
* namespace has been specified, this parameter is null.
* @param nsURI the URI associated with the namespace. If no
* namespace has been specified, or no URI is
* associated with nsPrefix, this parameter is null.
*/
public void elementAttributesProcessed(String name,
String nsPrefix,
String nsURI)
{
// nothing to do
}
/**
* This method is called when the end of an XML elemnt is encountered.
*
* @see #startElement
*
* @param name the name of the element.
* @param nsPrefix the prefix used to identify the namespace. If no
* namespace has been specified, this parameter is null.
* @param nsURI the URI associated with the namespace. If no
* namespace has been specified, or no URI is
* associated with nsPrefix, this parameter is null.
*/
public void endElement(String name,
String nsPrefix,
String nsURI)
{
XMLElement elt = (XMLElement) this.stack.pop();
if (elt.getChildCount() == 1) {
XMLElement child = elt.getChildAtIndex(0);
if (child.getLocalName() == null) {
elt.setContent(child.getContent());
elt.removeChildAtIndex(0);
}
}
}
/**
* This method is called when a new attribute of an XML element is
* encountered.
*
* @param key the key (name) of the attribute.
* @param nsPrefix the prefix used to identify the namespace. If no
* namespace has been specified, this parameter is null.
* @param nsURI the URI associated with the namespace. If no
* namespace has been specified, or no URI is
* associated with nsPrefix, this parameter is null.
* @param value the value of the attribute.
* @param type the type of the attribute. If no type is known,
* "CDATA" is returned.
*
* @throws java.lang.Exception
* If an exception occurred while processing the event.
*/
public void addAttribute(String key,
String nsPrefix,
String nsURI,
String value,
String type)
throws Exception
{
String fullName = key;
if (nsPrefix != null) {
fullName = nsPrefix + ':' + key;
}
XMLElement top = (XMLElement) this.stack.peek();
if (top.hasAttribute(fullName)) {
throw new XMLParseException(top.getSystemID(),
top.getLineNr(),
"Duplicate attribute: " + key);
}
if (nsPrefix != null) {
top.setAttribute(fullName, nsURI, value);
} else {
top.setAttribute(fullName, value);
}
}
/**
* This method is called when a PCDATA element is encountered. A Java
* reader is supplied from which you can read the data. The reader will
* only read the data of the element. You don't need to check for
* boundaries. If you don't read the full element, the rest of the data
* is skipped. You also don't have to care about entities; they are
* resolved by the parser.
*
* @param reader the Java reader from which you can retrieve the data.
* @param systemID the system ID of the XML data source.
* @param lineNr the line in the source where the element starts.
*/
public void addPCData(Reader reader,
String systemID,
int lineNr)
{
int bufSize = 2048;
int sizeRead = 0;
StringBuffer str = new StringBuffer(bufSize);
char[] buf = new char[bufSize];
for (;;) {
if (sizeRead >= bufSize) {
bufSize *= 2;
str.ensureCapacity(bufSize);
}
int size;
try {
size = reader.read(buf);
} catch (IOException e) {
break;
}
if (size < 0) {
break;
}
str.append(buf, 0, size);
sizeRead += size;
}
//XMLElement elt = this.prototype.createElement(null, systemID, lineNr);
XMLElement elt = new XMLElement(null, null, systemID, lineNr);
elt.setContent(str.toString());
if (! this.stack.empty()) {
XMLElement top = (XMLElement) this.stack.peek();
top.addChild(elt);
}
}
/**
* Returns the result of the building process. This method is called just
* before the <I>parse</I> method of StdXMLParser returns.
*
* @return the result of the building process.
*/
public Object getResult()
{
return this.root;
}
}

View File

@ -0,0 +1,684 @@
/* StdXMLParser.java NanoXML/Java
*
* $Revision: 1.5 $
* $Date: 2002/03/24 11:37:00 $
* $Name: RELEASE_2_2_1 $
*
* This file is part of NanoXML 2 for Java.
* Copyright (C) 2000-2002 Marc De Scheemaecker, All Rights Reserved.
*
* This software is provided 'as-is', without any express or implied warranty.
* In no event will the authors be held liable for any damages arising from the
* use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software in
* a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
*
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
*
* 3. This notice may not be removed or altered from any source distribution.
*/
package processing.xml;
import java.io.Reader;
import java.util.Enumeration;
import java.util.Properties;
import java.util.Vector;
/**
* StdXMLParser is the core parser of NanoXML.
*
* @author Marc De Scheemaecker
* @version $Name: RELEASE_2_2_1 $, $Revision: 1.5 $
*/
public class StdXMLParser {
/**
* The builder which creates the logical structure of the XML data.
*/
private StdXMLBuilder builder;
/**
* The reader from which the parser retrieves its data.
*/
private StdXMLReader reader;
/**
* The entity resolver.
*/
private XMLEntityResolver entityResolver;
/**
* The validator that will process entity references and validate the XML
* data.
*/
private XMLValidator validator;
/**
* Creates a new parser.
*/
public StdXMLParser()
{
this.builder = null;
this.validator = null;
this.reader = null;
this.entityResolver = new XMLEntityResolver();
}
/**
* Cleans up the object when it's destroyed.
*/
protected void finalize()
throws Throwable
{
this.builder = null;
this.reader = null;
this.entityResolver = null;
this.validator = null;
super.finalize();
}
/**
* Sets the builder which creates the logical structure of the XML data.
*
* @param builder the non-null builder
*/
public void setBuilder(StdXMLBuilder builder)
{
this.builder = builder;
}
/**
* Returns the builder which creates the logical structure of the XML data.
*
* @return the builder
*/
public StdXMLBuilder getBuilder()
{
return this.builder;
}
/**
* Sets the validator that validates the XML data.
*
* @param validator the non-null validator
*/
public void setValidator(XMLValidator validator)
{
this.validator = validator;
}
/**
* Returns the validator that validates the XML data.
*
* @return the validator
*/
public XMLValidator getValidator()
{
return this.validator;
}
/**
* Sets the entity resolver.
*
* @param resolver the non-null resolver
*/
public void setResolver(XMLEntityResolver resolver)
{
this.entityResolver = resolver;
}
/**
* Returns the entity resolver.
*
* @return the non-null resolver
*/
public XMLEntityResolver getResolver()
{
return this.entityResolver;
}
/**
* Sets the reader from which the parser retrieves its data.
*
* @param reader the reader
*/
public void setReader(StdXMLReader reader)
{
this.reader = reader;
}
/**
* Returns the reader from which the parser retrieves its data.
*
* @return the reader
*/
public StdXMLReader getReader()
{
return this.reader;
}
/**
* Parses the data and lets the builder create the logical data structure.
*
* @return the logical structure built by the builder
*
* @throws net.n3.nanoxml.XMLException
* if an error occurred reading or parsing the data
*/
public Object parse()
throws XMLException
{
try {
this.builder.startBuilding(this.reader.getSystemID(),
this.reader.getLineNr());
this.scanData();
return this.builder.getResult();
} catch (XMLException e) {
throw e;
} catch (Exception e) {
throw new XMLException(e);
}
}
/**
* Scans the XML data for elements.
*
* @throws java.lang.Exception
* if something went wrong
*/
protected void scanData() throws Exception {
while ((! this.reader.atEOF()) && (this.builder.getResult() == null)) {
String str = XMLUtil.read(this.reader, '&');
char ch = str.charAt(0);
if (ch == '&') {
XMLUtil.processEntity(str, this.reader, this.entityResolver);
continue;
}
switch (ch) {
case '<':
this.scanSomeTag(false, // don't allow CDATA
null, // no default namespace
new Properties());
break;
case ' ':
case '\t':
case '\r':
case '\n':
// skip whitespace
break;
default:
XMLUtil.errorInvalidInput(reader.getSystemID(),
reader.getLineNr(),
"`" + ch + "' (0x"
+ Integer.toHexString((int) ch)
+ ')');
}
}
}
/**
* Scans an XML tag.
*
* @param allowCDATA true if CDATA sections are allowed at this point
* @param defaultNamespace the default namespace URI (or null)
* @param namespaces list of defined namespaces
*
* @throws java.lang.Exception
* if something went wrong
*/
protected void scanSomeTag(boolean allowCDATA,
String defaultNamespace,
Properties namespaces)
throws Exception
{
String str = XMLUtil.read(this.reader, '&');
char ch = str.charAt(0);
if (ch == '&') {
XMLUtil.errorUnexpectedEntity(reader.getSystemID(),
reader.getLineNr(),
str);
}
switch (ch) {
case '?':
this.processPI();
break;
case '!':
this.processSpecialTag(allowCDATA);
break;
default:
this.reader.unread(ch);
this.processElement(defaultNamespace, namespaces);
}
}
/**
* Processes a "processing instruction".
*
* @throws java.lang.Exception
* if something went wrong
*/
protected void processPI()
throws Exception
{
XMLUtil.skipWhitespace(this.reader, null);
String target = XMLUtil.scanIdentifier(this.reader);
XMLUtil.skipWhitespace(this.reader, null);
Reader r = new PIReader(this.reader);
if (!target.equalsIgnoreCase("xml")) {
this.builder.newProcessingInstruction(target, r);
}
r.close();
}
/**
* Processes a tag that starts with a bang (&lt;!...&gt;).
*
* @param allowCDATA true if CDATA sections are allowed at this point
*
* @throws java.lang.Exception
* if something went wrong
*/
protected void processSpecialTag(boolean allowCDATA)
throws Exception
{
String str = XMLUtil.read(this.reader, '&');
char ch = str.charAt(0);
if (ch == '&') {
XMLUtil.errorUnexpectedEntity(reader.getSystemID(),
reader.getLineNr(),
str);
}
switch (ch) {
case '[':
if (allowCDATA) {
this.processCDATA();
} else {
XMLUtil.errorUnexpectedCDATA(reader.getSystemID(),
reader.getLineNr());
}
return;
case 'D':
this.processDocType();
return;
case '-':
XMLUtil.skipComment(this.reader);
return;
}
}
/**
* Processes a CDATA section.
*
* @throws java.lang.Exception
* if something went wrong
*/
protected void processCDATA() throws Exception {
if (! XMLUtil.checkLiteral(this.reader, "CDATA[")) {
XMLUtil.errorExpectedInput(reader.getSystemID(),
reader.getLineNr(),
"<![[CDATA[");
}
this.validator.PCDataAdded(this.reader.getSystemID(),
this.reader.getLineNr());
Reader r = new CDATAReader(this.reader);
this.builder.addPCData(r, this.reader.getSystemID(),
this.reader.getLineNr());
r.close();
}
/**
* Processes a document type declaration.
*
* @throws java.lang.Exception
* if an error occurred reading or parsing the data
*/
protected void processDocType() throws Exception {
if (! XMLUtil.checkLiteral(this.reader, "OCTYPE")) {
XMLUtil.errorExpectedInput(reader.getSystemID(),
reader.getLineNr(),
"<!DOCTYPE");
return;
}
XMLUtil.skipWhitespace(this.reader, null);
String systemID = null;
StringBuffer publicID = new StringBuffer();
/*String rootElement =*/ XMLUtil.scanIdentifier(this.reader);
//System.out.println("rootElement is " + rootElement);
XMLUtil.skipWhitespace(this.reader, null);
char ch = this.reader.read();
if (ch == 'P') {
systemID = XMLUtil.scanPublicID(publicID, reader);
XMLUtil.skipWhitespace(this.reader, null);
ch = this.reader.read();
} else if (ch == 'S') {
systemID = XMLUtil.scanSystemID(reader);
XMLUtil.skipWhitespace(this.reader, null);
ch = this.reader.read();
}
if (ch == '[') {
this.validator.parseDTD(publicID.toString(),
this.reader,
this.entityResolver,
false);
XMLUtil.skipWhitespace(this.reader, null);
ch = this.reader.read();
}
if (ch != '>') {
XMLUtil.errorExpectedInput(reader.getSystemID(),
reader.getLineNr(),
"`>'");
}
// TODO DTD checking is currently disabled, because it breaks
// applications that don't have access to a net connection
// (since it insists on going and checking out the DTD).
if (false) {
if (systemID != null) {
Reader r = this.reader.openStream(publicID.toString(), systemID);
this.reader.startNewStream(r);
this.reader.setSystemID(systemID);
this.reader.setPublicID(publicID.toString());
this.validator.parseDTD(publicID.toString(),
this.reader,
this.entityResolver,
true);
}
}
}
/**
* Processes a regular element.
*
* @param defaultNamespace the default namespace URI (or null)
* @param namespaces list of defined namespaces
*
* @throws java.lang.Exception
* if something went wrong
*/
protected void processElement(String defaultNamespace,
Properties namespaces)
throws Exception
{
String fullName = XMLUtil.scanIdentifier(this.reader);
String name = fullName;
XMLUtil.skipWhitespace(this.reader, null);
String prefix = null;
int colonIndex = name.indexOf(':');
if (colonIndex > 0) {
prefix = name.substring(0, colonIndex);
name = name.substring(colonIndex + 1);
}
Vector<String> attrNames = new Vector<String>();
Vector<String> attrValues = new Vector<String>();
Vector<String> attrTypes = new Vector<String>();
this.validator.elementStarted(fullName,
this.reader.getSystemID(),
this.reader.getLineNr());
char ch;
for (;;) {
ch = this.reader.read();
if ((ch == '/') || (ch == '>')) {
break;
}
this.reader.unread(ch);
this.processAttribute(attrNames, attrValues, attrTypes);
XMLUtil.skipWhitespace(this.reader, null);
}
Properties extraAttributes = new Properties();
this.validator.elementAttributesProcessed(fullName,
extraAttributes,
this.reader.getSystemID(),
this.reader.getLineNr());
Enumeration<?> en = extraAttributes.keys();
while (en.hasMoreElements()) {
String key = (String) en.nextElement();
String value = extraAttributes.getProperty(key);
attrNames.addElement(key);
attrValues.addElement(value);
attrTypes.addElement("CDATA");
}
for (int i = 0; i < attrNames.size(); i++) {
String key = (String) attrNames.elementAt(i);
String value = (String) attrValues.elementAt(i);
//String type = (String) attrTypes.elementAt(i);
if (key.equals("xmlns")) {
defaultNamespace = value;
} else if (key.startsWith("xmlns:")) {
namespaces.put(key.substring(6), value);
}
}
if (prefix == null) {
this.builder.startElement(name, prefix, defaultNamespace,
this.reader.getSystemID(),
this.reader.getLineNr());
} else {
this.builder.startElement(name, prefix,
namespaces.getProperty(prefix),
this.reader.getSystemID(),
this.reader.getLineNr());
}
for (int i = 0; i < attrNames.size(); i++) {
String key = (String) attrNames.elementAt(i);
if (key.startsWith("xmlns")) {
continue;
}
String value = (String) attrValues.elementAt(i);
String type = (String) attrTypes.elementAt(i);
colonIndex = key.indexOf(':');
if (colonIndex > 0) {
String attPrefix = key.substring(0, colonIndex);
key = key.substring(colonIndex + 1);
this.builder.addAttribute(key, attPrefix,
namespaces.getProperty(attPrefix),
value, type);
} else {
this.builder.addAttribute(key, null, null, value, type);
}
}
if (prefix == null) {
this.builder.elementAttributesProcessed(name, prefix,
defaultNamespace);
} else {
this.builder.elementAttributesProcessed(name, prefix,
namespaces
.getProperty(prefix));
}
if (ch == '/') {
if (this.reader.read() != '>') {
XMLUtil.errorExpectedInput(reader.getSystemID(),
reader.getLineNr(),
"`>'");
}
this.validator.elementEnded(name,
this.reader.getSystemID(),
this.reader.getLineNr());
if (prefix == null) {
this.builder.endElement(name, prefix, defaultNamespace);
} else {
this.builder.endElement(name, prefix,
namespaces.getProperty(prefix));
}
return;
}
StringBuffer buffer = new StringBuffer(16);
for (;;) {
buffer.setLength(0);
String str;
for (;;) {
XMLUtil.skipWhitespace(this.reader, buffer);
str = XMLUtil.read(this.reader, '&');
if ((str.charAt(0) == '&') && (str.charAt(1) != '#')) {
XMLUtil.processEntity(str, this.reader,
this.entityResolver);
} else {
break;
}
}
if (str.charAt(0) == '<') {
str = XMLUtil.read(this.reader, '\0');
if (str.charAt(0) == '/') {
XMLUtil.skipWhitespace(this.reader, null);
str = XMLUtil.scanIdentifier(this.reader);
if (! str.equals(fullName)) {
XMLUtil.errorWrongClosingTag(reader.getSystemID(),
reader.getLineNr(),
name, str);
}
XMLUtil.skipWhitespace(this.reader, null);
if (this.reader.read() != '>') {
XMLUtil.errorClosingTagNotEmpty(reader.getSystemID(),
reader.getLineNr());
}
this.validator.elementEnded(fullName,
this.reader.getSystemID(),
this.reader.getLineNr());
if (prefix == null) {
this.builder.endElement(name, prefix, defaultNamespace);
} else {
this.builder.endElement(name, prefix,
namespaces.getProperty(prefix));
}
break;
} else { // <[^/]
this.reader.unread(str.charAt(0));
this.scanSomeTag(true, //CDATA allowed
defaultNamespace,
(Properties) namespaces.clone());
}
} else { // [^<]
if (str.charAt(0) == '&') {
ch = XMLUtil.processCharLiteral(str);
buffer.append(ch);
} else {
reader.unread(str.charAt(0));
}
this.validator.PCDataAdded(this.reader.getSystemID(),
this.reader.getLineNr());
Reader r = new ContentReader(this.reader,
this.entityResolver,
buffer.toString());
this.builder.addPCData(r, this.reader.getSystemID(),
this.reader.getLineNr());
r.close();
}
}
}
/**
* Processes an attribute of an element.
*
* @param attrNames contains the names of the attributes.
* @param attrValues contains the values of the attributes.
* @param attrTypes contains the types of the attributes.
*
* @throws java.lang.Exception
* if something went wrong
*/
protected void processAttribute(Vector<String> attrNames,
Vector<String> attrValues,
Vector<String> attrTypes)
throws Exception
{
String key = XMLUtil.scanIdentifier(this.reader);
XMLUtil.skipWhitespace(this.reader, null);
if (! XMLUtil.read(this.reader, '&').equals("=")) {
XMLUtil.errorExpectedInput(reader.getSystemID(),
reader.getLineNr(),
"`='");
}
XMLUtil.skipWhitespace(this.reader, null);
String value = XMLUtil.scanString(this.reader, '&',
this.entityResolver);
attrNames.addElement(key);
attrValues.addElement(value);
attrTypes.addElement("CDATA");
this.validator.attributeAdded(key, value,
this.reader.getSystemID(),
this.reader.getLineNr());
}
}

View File

@ -0,0 +1,626 @@
/* StdXMLReader.java NanoXML/Java
*
* $Revision: 1.4 $
* $Date: 2002/01/04 21:03:28 $
* $Name: RELEASE_2_2_1 $
*
* This file is part of NanoXML 2 for Java.
* Copyright (C) 2000-2002 Marc De Scheemaecker, All Rights Reserved.
*
* This software is provided 'as-is', without any express or implied warranty.
* In no event will the authors be held liable for any damages arising from the
* use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software in
* a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
*
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
*
* 3. This notice may not be removed or altered from any source distribution.
*/
package processing.xml;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.IOException;
//import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.LineNumberReader;
import java.io.PushbackReader;
import java.io.PushbackInputStream;
import java.io.Reader;
import java.io.StringReader;
import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Stack;
/**
* StdXMLReader reads the data to be parsed.
*
* @author Marc De Scheemaecker
* @version $Name: RELEASE_2_2_1 $, $Revision: 1.4 $
*/
public class StdXMLReader
{
/**
* A stacked reader.
*
* @author Marc De Scheemaecker
* @version $Name: RELEASE_2_2_1 $, $Revision: 1.4 $
*/
private class StackedReader
{
PushbackReader pbReader;
LineNumberReader lineReader;
URL systemId;
String publicId;
}
/**
* The stack of readers.
*/
private Stack<StackedReader> readers;
/**
* The current push-back reader.
*/
private StackedReader currentReader;
/**
* Creates a new reader using a string as input.
*
* @param str the string containing the XML data
*/
public static StdXMLReader stringReader(String str)
{
return new StdXMLReader(new StringReader(str));
}
/**
* Creates a new reader using a file as input.
*
* @param filename the name of the file containing the XML data
*
* @throws java.io.FileNotFoundException
* if the file could not be found
* @throws java.io.IOException
* if an I/O error occurred
*/
public static StdXMLReader fileReader(String filename)
throws FileNotFoundException,
IOException
{
StdXMLReader r = new StdXMLReader(new FileInputStream(filename));
r.setSystemID(filename);
for (int i = 0; i < r.readers.size(); i++) {
StackedReader sr = (StackedReader) r.readers.elementAt(i);
sr.systemId = r.currentReader.systemId;
}
return r;
}
/**
* Initializes the reader from a system and public ID.
*
* @param publicID the public ID which may be null.
* @param systemID the non-null system ID.
*
* @throws MalformedURLException
* if the system ID does not contain a valid URL
* @throws FileNotFoundException
* if the system ID refers to a local file which does not exist
* @throws IOException
* if an error occurred opening the stream
*/
public StdXMLReader(String publicID,
String systemID)
throws MalformedURLException,
FileNotFoundException,
IOException
{
URL systemIDasURL = null;
try {
systemIDasURL = new URL(systemID);
} catch (MalformedURLException e) {
systemID = "file:" + systemID;
try {
systemIDasURL = new URL(systemID);
} catch (MalformedURLException e2) {
throw e;
}
}
this.currentReader = new StackedReader();
this.readers = new Stack<StackedReader>();
Reader reader = this.openStream(publicID, systemIDasURL.toString());
this.currentReader.lineReader = new LineNumberReader(reader);
this.currentReader.pbReader
= new PushbackReader(this.currentReader.lineReader, 2);
}
/**
* Initializes the XML reader.
*
* @param reader the input for the XML data.
*/
public StdXMLReader(Reader reader)
{
this.currentReader = new StackedReader();
this.readers = new Stack<StackedReader>();
this.currentReader.lineReader = new LineNumberReader(reader);
this.currentReader.pbReader
= new PushbackReader(this.currentReader.lineReader, 2);
this.currentReader.publicId = "";
try {
this.currentReader.systemId = new URL("file:.");
} catch (MalformedURLException e) {
// never happens
}
}
/**
* Cleans up the object when it's destroyed.
*/
protected void finalize()
throws Throwable
{
this.currentReader.lineReader = null;
this.currentReader.pbReader = null;
this.currentReader.systemId = null;
this.currentReader.publicId = null;
this.currentReader = null;
this.readers.clear();
super.finalize();
}
/**
* Scans the encoding from an &lt;?xml...?&gt; tag.
*
* @param str the first tag in the XML data.
*
* @return the encoding, or null if no encoding has been specified.
*/
protected String getEncoding(String str)
{
if (! str.startsWith("<?xml")) {
return null;
}
int index = 5;
while (index < str.length()) {
StringBuffer key = new StringBuffer();
while ((index < str.length()) && (str.charAt(index) <= ' ')) {
index++;
}
while ((index < str.length())
&& (str.charAt(index) >= 'a')
&& (str.charAt(index) <= 'z')) {
key.append(str.charAt(index));
index++;
}
while ((index < str.length()) && (str.charAt(index) <= ' ')) {
index++;
}
if ((index >= str.length()) || (str.charAt(index) != '=')) {
break;
}
while ((index < str.length()) && (str.charAt(index) != '\'')
&& (str.charAt(index) != '"')) {
index++;
}
if (index >= str.length()) {
break;
}
char delimiter = str.charAt(index);
index++;
int index2 = str.indexOf(delimiter, index);
if (index2 < 0) {
break;
}
if (key.toString().equals("encoding")) {
return str.substring(index, index2);
}
index = index2 + 1;
}
return null;
}
/**
* Converts a stream to a reader while detecting the encoding.
*
* @param stream the input for the XML data.
* @param charsRead buffer where to put characters that have been read
*
* @throws java.io.IOException
* if an I/O error occurred
*/
protected Reader stream2reader(InputStream stream,
StringBuffer charsRead)
throws IOException
{
PushbackInputStream pbstream = new PushbackInputStream(stream);
int b = pbstream.read();
switch (b) {
case 0x00:
case 0xFE:
case 0xFF:
pbstream.unread(b);
return new InputStreamReader(pbstream, "UTF-16");
case 0xEF:
for (int i = 0; i < 2; i++) {
pbstream.read();
}
return new InputStreamReader(pbstream, "UTF-8");
case 0x3C:
b = pbstream.read();
charsRead.append('<');
while ((b > 0) && (b != 0x3E)) {
charsRead.append((char) b);
b = pbstream.read();
}
if (b > 0) {
charsRead.append((char) b);
}
String encoding = this.getEncoding(charsRead.toString());
if (encoding == null) {
return new InputStreamReader(pbstream, "UTF-8");
}
charsRead.setLength(0);
try {
return new InputStreamReader(pbstream, encoding);
} catch (UnsupportedEncodingException e) {
return new InputStreamReader(pbstream, "UTF-8");
}
default:
charsRead.append((char) b);
return new InputStreamReader(pbstream, "UTF-8");
}
}
/**
* Initializes the XML reader.
*
* @param stream the input for the XML data.
*
* @throws java.io.IOException
* if an I/O error occurred
*/
public StdXMLReader(InputStream stream)
throws IOException
{
// unused?
//PushbackInputStream pbstream = new PushbackInputStream(stream);
StringBuffer charsRead = new StringBuffer();
Reader reader = this.stream2reader(stream, charsRead);
this.currentReader = new StackedReader();
this.readers = new Stack<StackedReader>();
this.currentReader.lineReader = new LineNumberReader(reader);
this.currentReader.pbReader
= new PushbackReader(this.currentReader.lineReader, 2);
this.currentReader.publicId = "";
try {
this.currentReader.systemId = new URL("file:.");
} catch (MalformedURLException e) {
// never happens
}
this.startNewStream(new StringReader(charsRead.toString()));
}
/**
* Reads a character.
*
* @return the character
*
* @throws java.io.IOException
* if no character could be read
*/
public char read()
throws IOException
{
int ch = this.currentReader.pbReader.read();
while (ch < 0) {
if (this.readers.empty()) {
throw new IOException("Unexpected EOF");
}
this.currentReader.pbReader.close();
this.currentReader = (StackedReader) this.readers.pop();
ch = this.currentReader.pbReader.read();
}
return (char) ch;
}
/**
* Returns true if the current stream has no more characters left to be
* read.
*
* @throws java.io.IOException
* if an I/O error occurred
*/
public boolean atEOFOfCurrentStream()
throws IOException
{
int ch = this.currentReader.pbReader.read();
if (ch < 0) {
return true;
} else {
this.currentReader.pbReader.unread(ch);
return false;
}
}
/**
* Returns true if there are no more characters left to be read.
*
* @throws java.io.IOException
* if an I/O error occurred
*/
public boolean atEOF()
throws IOException
{
int ch = this.currentReader.pbReader.read();
while (ch < 0) {
if (this.readers.empty()) {
return true;
}
this.currentReader.pbReader.close();
this.currentReader = (StackedReader) this.readers.pop();
ch = this.currentReader.pbReader.read();
}
this.currentReader.pbReader.unread(ch);
return false;
}
/**
* Pushes the last character read back to the stream.
*
* @param ch the character to push back.
*
* @throws java.io.IOException
* if an I/O error occurred
*/
public void unread(char ch)
throws IOException
{
this.currentReader.pbReader.unread(ch);
}
/**
* Opens a stream from a public and system ID.
*
* @param publicID the public ID, which may be null
* @param systemID the system ID, which is never null
*
* @throws java.net.MalformedURLException
* if the system ID does not contain a valid URL
* @throws java.io.FileNotFoundException
* if the system ID refers to a local file which does not exist
* @throws java.io.IOException
* if an error occurred opening the stream
*/
public Reader openStream(String publicID,
String systemID)
throws MalformedURLException,
FileNotFoundException,
IOException
{
URL url = new URL(this.currentReader.systemId, systemID);
if (url.getRef() != null) {
String ref = url.getRef();
if (url.getFile().length() > 0) {
url = new URL(url.getProtocol(), url.getHost(), url.getPort(),
url.getFile());
url = new URL("jar:" + url + '!' + ref);
} else {
url = StdXMLReader.class.getResource(ref);
}
}
this.currentReader.publicId = publicID;
this.currentReader.systemId = url;
StringBuffer charsRead = new StringBuffer();
Reader reader = this.stream2reader(url.openStream(), charsRead);
if (charsRead.length() == 0) {
return reader;
}
String charsReadStr = charsRead.toString();
PushbackReader pbreader = new PushbackReader(reader,
charsReadStr.length());
for (int i = charsReadStr.length() - 1; i >= 0; i--) {
pbreader.unread(charsReadStr.charAt(i));
}
return pbreader;
}
/**
* Starts a new stream from a Java reader. The new stream is used
* temporary to read data from. If that stream is exhausted, control
* returns to the parent stream.
*
* @param reader the non-null reader to read the new data from
*/
public void startNewStream(Reader reader)
{
this.startNewStream(reader, false);
}
/**
* Starts a new stream from a Java reader. The new stream is used
* temporary to read data from. If that stream is exhausted, control
* returns to the parent stream.
*
* @param reader the non-null reader to read the new data from
* @param isInternalEntity true if the reader is produced by resolving
* an internal entity
*/
public void startNewStream(Reader reader,
boolean isInternalEntity)
{
StackedReader oldReader = this.currentReader;
this.readers.push(this.currentReader);
this.currentReader = new StackedReader();
if (isInternalEntity) {
this.currentReader.lineReader = null;
this.currentReader.pbReader = new PushbackReader(reader, 2);
} else {
this.currentReader.lineReader = new LineNumberReader(reader);
this.currentReader.pbReader
= new PushbackReader(this.currentReader.lineReader, 2);
}
this.currentReader.systemId = oldReader.systemId;
this.currentReader.publicId = oldReader.publicId;
}
/**
* Returns the current "level" of the stream on the stack of streams.
*/
public int getStreamLevel()
{
return this.readers.size();
}
/**
* Returns the line number of the data in the current stream.
*/
public int getLineNr()
{
if (this.currentReader.lineReader == null) {
StackedReader sr = (StackedReader) this.readers.peek();
if (sr.lineReader == null) {
return 0;
} else {
return sr.lineReader.getLineNumber() + 1;
}
}
return this.currentReader.lineReader.getLineNumber() + 1;
}
/**
* Sets the system ID of the current stream.
*
* @param systemID the system ID
*
* @throws java.net.MalformedURLException
* if the system ID does not contain a valid URL
*/
public void setSystemID(String systemID)
throws MalformedURLException
{
this.currentReader.systemId = new URL(this.currentReader.systemId,
systemID);
}
/**
* Sets the public ID of the current stream.
*
* @param publicID the public ID
*/
public void setPublicID(String publicID)
{
this.currentReader.publicId = publicID;
}
/**
* Returns the current system ID.
*/
public String getSystemID()
{
return this.currentReader.systemId.toString();
}
/**
* Returns the current public ID.
*/
public String getPublicID()
{
return this.currentReader.publicId;
}
}

View File

@ -0,0 +1,153 @@
/* XMLAttribute.java NanoXML/Java
*
* $Revision: 1.4 $
* $Date: 2002/01/04 21:03:29 $
* $Name: RELEASE_2_2_1 $
*
* This file is part of NanoXML 2 for Java.
* Copyright (C) 2000-2002 Marc De Scheemaecker, All Rights Reserved.
*
* This software is provided 'as-is', without any express or implied warranty.
* In no event will the authors be held liable for any damages arising from the
* use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software in
* a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
*
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
*
* 3. This notice may not be removed or altered from any source distribution.
*/
package processing.xml;
/**
* An attribute in an XML element. This is an internal class.
*
* @see net.n3.nanoxml.XMLElement
*
* @author Marc De Scheemaecker
* @version $Name: RELEASE_2_2_1 $, $Revision: 1.4 $
*/
class XMLAttribute
{
/**
* The full name of the attribute.
*/
private String fullName;
/**
* The short name of the attribute.
*/
private String name;
/**
* The namespace URI of the attribute.
*/
private String namespace;
/**
* The value of the attribute.
*/
private String value;
/**
* The type of the attribute.
*/
private String type;
/**
* Creates a new attribute.
*
* @param fullName the non-null full name
* @param name the non-null short name
* @param namespace the namespace URI, which may be null
* @param value the value of the attribute
* @param type the type of the attribute
*/
XMLAttribute(String fullName,
String name,
String namespace,
String value,
String type)
{
this.fullName = fullName;
this.name = name;
this.namespace = namespace;
this.value = value;
this.type = type;
}
/**
* Returns the full name of the attribute.
*/
String getFullName()
{
return this.fullName;
}
/**
* Returns the short name of the attribute.
*/
String getName()
{
return this.name;
}
/**
* Returns the namespace of the attribute.
*/
String getNamespace()
{
return this.namespace;
}
/**
* Returns the value of the attribute.
*/
String getValue()
{
return this.value;
}
/**
* Sets the value of the attribute.
*
* @param value the new value.
*/
void setValue(String value)
{
this.value = value;
}
/**
* Returns the type of the attribute.
*
* @param type the new type.
*/
String getType()
{
return this.type;
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,173 @@
/* XMLEntityResolver.java NanoXML/Java
*
* $Revision: 1.4 $
* $Date: 2002/01/04 21:03:29 $
* $Name: RELEASE_2_2_1 $
*
* This file is part of NanoXML 2 for Java.
* Copyright (C) 2000-2002 Marc De Scheemaecker, All Rights Reserved.
*
* This software is provided 'as-is', without any express or implied warranty.
* In no event will the authors be held liable for any damages arising from the
* use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software in
* a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
*
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
*
* 3. This notice may not be removed or altered from any source distribution.
*/
package processing.xml;
import java.util.Hashtable;
import java.io.Reader;
import java.io.StringReader;
/**
* An XMLEntityResolver resolves entities.
*
* @author Marc De Scheemaecker
* @version $Name: RELEASE_2_2_1 $, $Revision: 1.4 $
*/
public class XMLEntityResolver
{
/**
* The entities.
*/
private Hashtable<String, Object> entities;
/**
* Initializes the resolver.
*/
public XMLEntityResolver()
{
this.entities = new Hashtable<String, Object>();
this.entities.put("amp", "&#38;");
this.entities.put("quot", "&#34;");
this.entities.put("apos", "&#39;");
this.entities.put("lt", "&#60;");
this.entities.put("gt", "&#62;");
}
/**
* Cleans up the object when it's destroyed.
*/
protected void finalize()
throws Throwable
{
this.entities.clear();
this.entities = null;
super.finalize();
}
/**
* Adds an internal entity.
*
* @param name the name of the entity.
* @param value the value of the entity.
*/
public void addInternalEntity(String name,
String value)
{
if (! this.entities.containsKey(name)) {
this.entities.put(name, value);
}
}
/**
* Adds an external entity.
*
* @param name the name of the entity.
* @param publicID the public ID of the entity, which may be null.
* @param systemID the system ID of the entity.
*/
public void addExternalEntity(String name,
String publicID,
String systemID)
{
if (! this.entities.containsKey(name)) {
this.entities.put(name, new String[] { publicID, systemID } );
}
}
/**
* Returns a Java reader containing the value of an entity.
*
* @param xmlReader the current XML reader
* @param name the name of the entity.
*
* @return the reader, or null if the entity could not be resolved.
*/
public Reader getEntity(StdXMLReader xmlReader,
String name)
throws XMLParseException
{
Object obj = this.entities.get(name);
if (obj == null) {
return null;
} else if (obj instanceof java.lang.String) {
return new StringReader((String)obj);
} else {
String[] id = (String[]) obj;
return this.openExternalEntity(xmlReader, id[0], id[1]);
}
}
/**
* Returns true if an entity is external.
*
* @param name the name of the entity.
*/
public boolean isExternalEntity(String name)
{
Object obj = this.entities.get(name);
return ! (obj instanceof java.lang.String);
}
/**
* Opens an external entity.
*
* @param xmlReader the current XML reader
* @param publicID the public ID, which may be null
* @param systemID the system ID
*
* @return the reader, or null if the reader could not be created/opened
*/
protected Reader openExternalEntity(StdXMLReader xmlReader,
String publicID,
String systemID)
throws XMLParseException
{
String parentSystemID = xmlReader.getSystemID();
try {
return xmlReader.openStream(publicID, systemID);
} catch (Exception e) {
throw new XMLParseException(parentSystemID,
xmlReader.getLineNr(),
"Could not open external entity "
+ "at system ID: " + systemID);
}
}
}

View File

@ -0,0 +1,286 @@
/* XMLException.java NanoXML/Java
*
* $Revision: 1.4 $
* $Date: 2002/01/04 21:03:29 $
* $Name: RELEASE_2_2_1 $
*
* This file is part of NanoXML 2 for Java.
* Copyright (C) 2000-2002 Marc De Scheemaecker, All Rights Reserved.
*
* This software is provided 'as-is', without any express or implied warranty.
* In no event will the authors be held liable for any damages arising from the
* use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software in
* a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
*
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
*
* 3. This notice may not be removed or altered from any source distribution.
*/
package processing.xml;
import java.io.PrintStream;
import java.io.PrintWriter;
/**
* An XMLException is thrown when an exception occurred while processing the
* XML data.
*
* @author Marc De Scheemaecker
* @version $Name: RELEASE_2_2_1 $, $Revision: 1.4 $
*/
public class XMLException
extends Exception
{
/**
* The message of the exception.
*/
private String msg;
/**
* The system ID of the XML data where the exception occurred.
*/
private String systemID;
/**
* The line number in the XML data where the exception occurred.
*/
private int lineNr;
/**
* Encapsulated exception.
*/
private Exception encapsulatedException;
/**
* Creates a new exception.
*
* @param msg the message of the exception.
*/
public XMLException(String msg)
{
this(null, -1, null, msg, false);
}
/**
* Creates a new exception.
*
* @param e the encapsulated exception.
*/
public XMLException(Exception e)
{
this(null, -1, e, "Nested Exception", false);
}
/**
* Creates a new exception.
*
* @param systemID the system ID of the XML data where the exception
* occurred
* @param lineNr the line number in the XML data where the exception
* occurred.
* @param e the encapsulated exception.
*/
public XMLException(String systemID,
int lineNr,
Exception e)
{
this(systemID, lineNr, e, "Nested Exception", true);
}
/**
* Creates a new exception.
*
* @param systemID the system ID of the XML data where the exception
* occurred
* @param lineNr the line number in the XML data where the exception
* occurred.
* @param msg the message of the exception.
*/
public XMLException(String systemID,
int lineNr,
String msg)
{
this(systemID, lineNr, null, msg, true);
}
/**
* Creates a new exception.
*
* @param systemID the system ID from where the data came
* @param lineNr the line number in the XML data where the exception
* occurred.
* @param e the encapsulated exception.
* @param msg the message of the exception.
* @param reportParams true if the systemID, lineNr and e params need to be
* appended to the message
*/
public XMLException(String systemID,
int lineNr,
Exception e,
String msg,
boolean reportParams)
{
super(XMLException.buildMessage(systemID, lineNr, e, msg,
reportParams));
this.systemID = systemID;
this.lineNr = lineNr;
this.encapsulatedException = e;
this.msg = XMLException.buildMessage(systemID, lineNr, e, msg,
reportParams);
}
/**
* Builds the exception message
*
* @param systemID the system ID from where the data came
* @param lineNr the line number in the XML data where the exception
* occurred.
* @param e the encapsulated exception.
* @param msg the message of the exception.
* @param reportParams true if the systemID, lineNr and e params need to be
* appended to the message
*/
private static String buildMessage(String systemID,
int lineNr,
Exception e,
String msg,
boolean reportParams)
{
String str = msg;
if (reportParams) {
if (systemID != null) {
str += ", SystemID='" + systemID + "'";
}
if (lineNr >= 0) {
str += ", Line=" + lineNr;
}
if (e != null) {
str += ", Exception: " + e;
}
}
return str;
}
/**
* Cleans up the object when it's destroyed.
*/
protected void finalize()
throws Throwable
{
this.systemID = null;
this.encapsulatedException = null;
super.finalize();
}
/**
* Returns the system ID of the XML data where the exception occurred.
* If there is no system ID known, null is returned.
*/
public String getSystemID()
{
return this.systemID;
}
/**
* Returns the line number in the XML data where the exception occurred.
* If there is no line number known, -1 is returned.
*/
public int getLineNr()
{
return this.lineNr;
}
/**
* Returns the encapsulated exception, or null if no exception is
* encapsulated.
*/
public Exception getException()
{
return this.encapsulatedException;
}
/**
* Dumps the exception stack to a print writer.
*
* @param writer the print writer
*/
public void printStackTrace(PrintWriter writer)
{
super.printStackTrace(writer);
if (this.encapsulatedException != null) {
writer.println("*** Nested Exception:");
this.encapsulatedException.printStackTrace(writer);
}
}
/**
* Dumps the exception stack to an output stream.
*
* @param stream the output stream
*/
public void printStackTrace(PrintStream stream)
{
super.printStackTrace(stream);
if (this.encapsulatedException != null) {
stream.println("*** Nested Exception:");
this.encapsulatedException.printStackTrace(stream);
}
}
/**
* Dumps the exception stack to System.err.
*/
public void printStackTrace()
{
super.printStackTrace();
if (this.encapsulatedException != null) {
System.err.println("*** Nested Exception:");
this.encapsulatedException.printStackTrace();
}
}
/**
* Returns a string representation of the exception.
*/
public String toString()
{
return this.msg;
}
}

View File

@ -0,0 +1,69 @@
/* XMLParseException.java NanoXML/Java
*
* $Revision: 1.3 $
* $Date: 2002/01/04 21:03:29 $
* $Name: RELEASE_2_2_1 $
*
* This file is part of NanoXML 2 for Java.
* Copyright (C) 2000-2002 Marc De Scheemaecker, All Rights Reserved.
*
* This software is provided 'as-is', without any express or implied warranty.
* In no event will the authors be held liable for any damages arising from the
* use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software in
* a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
*
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
*
* 3. This notice may not be removed or altered from any source distribution.
*/
package processing.xml;
/**
* An XMLParseException is thrown when the XML passed to the XML parser is not
* well-formed.
*
* @author Marc De Scheemaecker
* @version $Name: RELEASE_2_2_1 $, $Revision: 1.3 $
*/
public class XMLParseException
extends XMLException
{
/**
* Creates a new exception.
*
* @param msg the message of the exception.
*/
public XMLParseException(String msg)
{
super(msg);
}
/**
* Creates a new exception.
*
* @param systemID the system ID from where the data came
* @param lineNr the line number in the XML data where the exception
* occurred.
* @param msg the message of the exception.
*/
public XMLParseException(String systemID,
int lineNr,
String msg)
{
super(systemID, lineNr, null, msg, true);
}
}

View File

@ -0,0 +1,758 @@
/* XMLUtil.java NanoXML/Java
*
* $Revision: 1.5 $
* $Date: 2002/02/03 21:19:38 $
* $Name: RELEASE_2_2_1 $
*
* This file is part of NanoXML 2 for Java.
* Copyright (C) 2000-2002 Marc De Scheemaecker, All Rights Reserved.
*
* This software is provided 'as-is', without any express or implied warranty.
* In no event will the authors be held liable for any damages arising from the
* use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software in
* a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
*
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
*
* 3. This notice may not be removed or altered from any source distribution.
*/
package processing.xml;
import java.io.IOException;
import java.io.Reader;
/**
* Utility methods for NanoXML.
*
* @author Marc De Scheemaecker
* @version $Name: RELEASE_2_2_1 $, $Revision: 1.5 $
*/
class XMLUtil
{
/**
* Skips the remainder of a comment.
* It is assumed that &lt;!- is already read.
*
* @param reader the reader
*
* @throws java.io.IOException
* if an error occurred reading the data
*/
static void skipComment(StdXMLReader reader)
throws IOException,
XMLParseException
{
if (reader.read() != '-') {
XMLUtil.errorExpectedInput(reader.getSystemID(),
reader.getLineNr(),
"<!--");
}
int dashesRead = 0;
for (;;) {
char ch = reader.read();
switch (ch) {
case '-':
dashesRead++;
break;
case '>':
if (dashesRead == 2) {
return;
}
dashesRead = 0;
break;
default:
dashesRead = 0;
}
}
}
/**
* Skips the remainder of the current XML tag.
*
* @param reader the reader
*
* @throws java.io.IOException
* if an error occurred reading the data
*/
static void skipTag(StdXMLReader reader)
throws IOException,
XMLParseException
{
int level = 1;
while (level > 0) {
char ch = reader.read();
switch (ch) {
case '<':
++level;
break;
case '>':
--level;
break;
}
}
}
/**
* Scans a public ID.
*
* @param publicID will contain the public ID
* @param reader the reader
*
* @return the system ID
*
* @throws java.io.IOException
* if an error occurred reading the data
*/
static String scanPublicID(StringBuffer publicID,
StdXMLReader reader)
throws IOException,
XMLParseException
{
if (! XMLUtil.checkLiteral(reader, "UBLIC")) {
return null;
}
XMLUtil.skipWhitespace(reader, null);
publicID.append(XMLUtil.scanString(reader, '\0', null));
XMLUtil.skipWhitespace(reader, null);
return XMLUtil.scanString(reader, '\0', null);
}
/**
* Scans a system ID.
*
* @param reader the reader
*
* @return the system ID
*
* @throws java.io.IOException
* if an error occurred reading the data
*/
static String scanSystemID(StdXMLReader reader)
throws IOException,
XMLParseException
{
if (! XMLUtil.checkLiteral(reader, "YSTEM")) {
return null;
}
XMLUtil.skipWhitespace(reader, null);
return XMLUtil.scanString(reader, '\0', null);
}
/**
* Retrieves an identifier from the data.
*
* @param reader the reader
*
* @throws java.io.IOException
* if an error occurred reading the data
*/
static String scanIdentifier(StdXMLReader reader)
throws IOException,
XMLParseException
{
StringBuffer result = new StringBuffer();
for (;;) {
char ch = reader.read();
if ((ch == '_') || (ch == ':') || (ch == '-') || (ch == '.')
|| ((ch >= 'a') && (ch <= 'z'))
|| ((ch >= 'A') && (ch <= 'Z'))
|| ((ch >= '0') && (ch <= '9')) || (ch > '\u007E')) {
result.append(ch);
} else {
reader.unread(ch);
break;
}
}
return result.toString();
}
/**
* Retrieves a delimited string from the data.
*
* @param reader the reader
* @param entityChar the escape character (&amp; or %)
* @param entityResolver the entity resolver
*
* @throws java.io.IOException
* if an error occurred reading the data
*/
static String scanString(StdXMLReader reader,
char entityChar,
XMLEntityResolver entityResolver)
throws IOException,
XMLParseException
{
StringBuffer result = new StringBuffer();
int startingLevel = reader.getStreamLevel();
char delim = reader.read();
if ((delim != '\'') && (delim != '"')) {
XMLUtil.errorExpectedInput(reader.getSystemID(),
reader.getLineNr(),
"delimited string");
}
for (;;) {
String str = XMLUtil.read(reader, entityChar);
char ch = str.charAt(0);
if (ch == entityChar) {
if (str.charAt(1) == '#') {
result.append(XMLUtil.processCharLiteral(str));
} else {
XMLUtil.processEntity(str, reader, entityResolver);
}
} else if (ch == '&') {
reader.unread(ch);
str = XMLUtil.read(reader, '&');
if (str.charAt(1) == '#') {
result.append(XMLUtil.processCharLiteral(str));
} else {
result.append(str);
}
} else if (reader.getStreamLevel() == startingLevel) {
if (ch == delim) {
break;
} else if ((ch == 9) || (ch == 10) || (ch == 13)) {
result.append(' ');
} else {
result.append(ch);
}
} else {
result.append(ch);
}
}
return result.toString();
}
/**
* Processes an entity.
*
* @param entity the entity
* @param reader the reader
* @param entityResolver the entity resolver
*
* @throws java.io.IOException
* if an error occurred reading the data
*/
static void processEntity(String entity,
StdXMLReader reader,
XMLEntityResolver entityResolver)
throws IOException,
XMLParseException
{
entity = entity.substring(1, entity.length() - 1);
Reader entityReader = entityResolver.getEntity(reader, entity);
if (entityReader == null) {
XMLUtil.errorInvalidEntity(reader.getSystemID(),
reader.getLineNr(),
entity);
}
boolean externalEntity = entityResolver.isExternalEntity(entity);
reader.startNewStream(entityReader, !externalEntity);
}
/**
* Processes a character literal.
*
* @param entity the entity
*
* @throws java.io.IOException
* if an error occurred reading the data
*/
static char processCharLiteral(String entity)
throws IOException,
XMLParseException
{
if (entity.charAt(2) == 'x') {
entity = entity.substring(3, entity.length() - 1);
return (char) Integer.parseInt(entity, 16);
} else {
entity = entity.substring(2, entity.length() - 1);
return (char) Integer.parseInt(entity, 10);
}
}
/**
* Skips whitespace from the reader.
*
* @param reader the reader
* @param buffer where to put the whitespace; null if the
* whitespace does not have to be stored.
*
* @throws java.io.IOException
* if an error occurred reading the data
*/
static void skipWhitespace(StdXMLReader reader,
StringBuffer buffer)
throws IOException
{
char ch;
if (buffer == null) {
do {
ch = reader.read();
} while ((ch == ' ') || (ch == '\t') || (ch == '\n'));
} else {
for (;;) {
ch = reader.read();
if ((ch != ' ') && (ch != '\t') && (ch != '\n')) {
break;
}
if (ch == '\n') {
buffer.append('\n');
} else {
buffer.append(' ');
}
}
}
reader.unread(ch);
}
/**
* Reads a character from the reader.
*
* @param reader the reader
* @param entityChar the escape character (&amp; or %) used to indicate
* an entity
*
* @return the character, or an entity expression (like e.g. &amp;lt;)
*
* @throws java.io.IOException
* if an error occurred reading the data
*/
static String read(StdXMLReader reader,
char entityChar) throws IOException, XMLParseException {
char ch = reader.read();
StringBuffer buf = new StringBuffer();
buf.append(ch);
if (ch == entityChar) {
while (ch != ';') {
ch = reader.read();
buf.append(ch);
}
}
return buf.toString();
}
/**
* Reads a character from the reader disallowing entities.
*
* @param reader the reader
* @param entityChar the escape character (&amp; or %) used to indicate
* an entity
*/
static char readChar(StdXMLReader reader,
char entityChar) throws IOException, XMLParseException {
String str = XMLUtil.read(reader, entityChar);
char ch = str.charAt(0);
if (ch == entityChar) {
XMLUtil.errorUnexpectedEntity(reader.getSystemID(),
reader.getLineNr(),
str);
}
return ch;
}
/**
* Returns true if the data starts with <I>literal</I>.
* Enough chars are read to determine this result.
*
* @param reader the reader
* @param literal the literal to check
*
* @throws java.io.IOException
* if an error occurred reading the data
*/
static boolean checkLiteral(StdXMLReader reader,
String literal)
throws IOException,
XMLParseException
{
for (int i = 0; i < literal.length(); i++) {
if (reader.read() != literal.charAt(i)) {
return false;
}
}
return true;
}
/**
* Throws an XMLParseException to indicate that an expected string is not
* encountered.
*
* @param systemID the system ID of the data source
* @param lineNr the line number in the data source
* @param expectedString the string that is expected
*/
static void errorExpectedInput(String systemID,
int lineNr,
String expectedString)
throws XMLParseException
{
throw new XMLParseException(systemID, lineNr,
"Expected: " + expectedString);
}
/**
* Throws an XMLParseException to indicate that an entity could not be
* resolved.
*
* @param systemID the system ID of the data source
* @param lineNr the line number in the data source
* @param entity the name of the entity
*/
static void errorInvalidEntity(String systemID,
int lineNr,
String entity)
throws XMLParseException
{
throw new XMLParseException(systemID, lineNr,
"Invalid entity: `&" + entity + ";'");
}
/**
* Throws an XMLParseException to indicate that an entity reference is
* unexpected at this point.
*
* @param systemID the system ID of the data source
* @param lineNr the line number in the data source
* @param entity the name of the entity
*/
static void errorUnexpectedEntity(String systemID,
int lineNr,
String entity)
throws XMLParseException
{
throw new XMLParseException(systemID, lineNr,
"No entity reference is expected here ("
+ entity + ")");
}
/**
* Throws an XMLParseException to indicate that a CDATA section is
* unexpected at this point.
*
* @param systemID the system ID of the data source
* @param lineNr the line number in the data source
*/
static void errorUnexpectedCDATA(String systemID,
int lineNr)
throws XMLParseException
{
throw new XMLParseException(systemID, lineNr,
"No CDATA section is expected here");
}
/**
* Throws an XMLParseException to indicate that a string is not expected
* at this point.
*
* @param systemID the system ID of the data source
* @param lineNr the line number in the data source
* @param unexpectedString the string that is unexpected
*/
static void errorInvalidInput(String systemID,
int lineNr,
String unexpectedString)
throws XMLParseException
{
throw new XMLParseException(systemID, lineNr,
"Invalid input: " + unexpectedString);
}
/**
* Throws an XMLParseException to indicate that the closing tag of an
* element does not match the opening tag.
*
* @param systemID the system ID of the data source
* @param lineNr the line number in the data source
* @param expectedName the name of the opening tag
* @param wrongName the name of the closing tag
*/
static void errorWrongClosingTag(String systemID,
int lineNr,
String expectedName,
String wrongName)
throws XMLParseException
{
throw new XMLParseException(systemID, lineNr,
"Closing tag does not match opening tag: `"
+ wrongName + "' != `" + expectedName
+ "'");
}
/**
* Throws an XMLParseException to indicate that extra data is encountered
* in a closing tag.
*
* @param systemID the system ID of the data source
* @param lineNr the line number in the data source
*/
static void errorClosingTagNotEmpty(String systemID,
int lineNr)
throws XMLParseException
{
throw new XMLParseException(systemID, lineNr,
"Closing tag must be empty");
}
/**
* Throws an XMLValidationException to indicate that an element is missing.
*
* @param systemID the system ID of the data source
* @param lineNr the line number in the data source
* @param parentElementName the name of the parent element
* @param missingElementName the name of the missing element
*/
static void errorMissingElement(String systemID,
int lineNr,
String parentElementName,
String missingElementName)
throws XMLValidationException
{
throw new XMLValidationException(
XMLValidationException.MISSING_ELEMENT,
systemID, lineNr,
missingElementName,
/*attributeName*/ null,
/*attributeValue*/ null,
"Element " + parentElementName
+ " expects to have a " + missingElementName);
}
/**
* Throws an XMLValidationException to indicate that an element is
* unexpected.
*
* @param systemID the system ID of the data source
* @param lineNr the line number in the data source
* @param parentElementName the name of the parent element
* @param unexpectedElementName the name of the unexpected element
*/
static void errorUnexpectedElement(String systemID,
int lineNr,
String parentElementName,
String unexpectedElementName)
throws XMLValidationException
{
throw new XMLValidationException(
XMLValidationException.UNEXPECTED_ELEMENT,
systemID, lineNr,
unexpectedElementName,
/*attributeName*/ null,
/*attributeValue*/ null,
"Unexpected " + unexpectedElementName + " in a "
+ parentElementName);
}
/**
* Throws an XMLValidationException to indicate that an attribute is
* missing.
*
* @param systemID the system ID of the data source
* @param lineNr the line number in the data source
* @param elementName the name of the element
* @param attributeName the name of the missing attribute
*/
static void errorMissingAttribute(String systemID,
int lineNr,
String elementName,
String attributeName)
throws XMLValidationException
{
throw new XMLValidationException(
XMLValidationException.MISSING_ATTRIBUTE,
systemID, lineNr,
elementName,
attributeName,
/*attributeValue*/ null,
"Element " + elementName + " expects an attribute named "
+ attributeName);
}
/**
* Throws an XMLValidationException to indicate that an attribute is
* unexpected.
*
* @param systemID the system ID of the data source
* @param lineNr the line number in the data source
* @param elementName the name of the element
* @param attributeName the name of the unexpected attribute
*/
static void errorUnexpectedAttribute(String systemID,
int lineNr,
String elementName,
String attributeName)
throws XMLValidationException
{
throw new XMLValidationException(
XMLValidationException.UNEXPECTED_ATTRIBUTE,
systemID, lineNr,
elementName,
attributeName,
/*attributeValue*/ null,
"Element " + elementName + " did not expect an attribute "
+ "named " + attributeName);
}
/**
* Throws an XMLValidationException to indicate that an attribute has an
* invalid value.
*
* @param systemID the system ID of the data source
* @param lineNr the line number in the data source
* @param elementName the name of the element
* @param attributeName the name of the attribute
* @param attributeValue the value of that attribute
*/
static void errorInvalidAttributeValue(String systemID,
int lineNr,
String elementName,
String attributeName,
String attributeValue)
throws XMLValidationException
{
throw new XMLValidationException(
XMLValidationException.ATTRIBUTE_WITH_INVALID_VALUE,
systemID, lineNr,
elementName,
attributeName,
attributeValue,
"Invalid value for attribute " + attributeName);
}
/**
* Throws an XMLValidationException to indicate that a #PCDATA element was
* missing.
*
* @param systemID the system ID of the data source
* @param lineNr the line number in the data source
* @param parentElementName the name of the parent element
*/
static void errorMissingPCData(String systemID,
int lineNr,
String parentElementName)
throws XMLValidationException
{
throw new XMLValidationException(
XMLValidationException.MISSING_PCDATA,
systemID, lineNr,
/*elementName*/ null,
/*attributeName*/ null,
/*attributeValue*/ null,
"Missing #PCDATA in element " + parentElementName);
}
/**
* Throws an XMLValidationException to indicate that a #PCDATA element was
* unexpected.
*
* @param systemID the system ID of the data source
* @param lineNr the line number in the data source
* @param parentElementName the name of the parent element
*/
static void errorUnexpectedPCData(String systemID,
int lineNr,
String parentElementName)
throws XMLValidationException
{
throw new XMLValidationException(
XMLValidationException.UNEXPECTED_PCDATA,
systemID, lineNr,
/*elementName*/ null,
/*attributeName*/ null,
/*attributeValue*/ null,
"Unexpected #PCDATA in element " + parentElementName);
}
/**
* Throws an XMLValidationException.
*
* @param systemID the system ID of the data source
* @param lineNr the line number in the data source
* @param message the error message
* @param elementName the name of the element
* @param attributeName the name of the attribute
* @param attributeValue the value of that attribute
*/
static void validationError(String systemID,
int lineNr,
String message,
String elementName,
String attributeName,
String attributeValue)
throws XMLValidationException
{
throw new XMLValidationException(XMLValidationException.MISC_ERROR,
systemID, lineNr,
elementName,
attributeName,
attributeValue,
message);
}
}

View File

@ -0,0 +1,190 @@
/* XMLValidationException.java NanoXML/Java
*
* $Revision: 1.3 $
* $Date: 2002/01/04 21:03:29 $
* $Name: RELEASE_2_2_1 $
*
* This file is part of NanoXML 2 for Java.
* Copyright (C) 2000-2002 Marc De Scheemaecker, All Rights Reserved.
*
* This software is provided 'as-is', without any express or implied warranty.
* In no event will the authors be held liable for any damages arising from the
* use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software in
* a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
*
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
*
* 3. This notice may not be removed or altered from any source distribution.
*/
package processing.xml;
/**
* An XMLValidationException is thrown when the XML passed to the XML parser is
* well-formed but not valid.
*
* @author Marc De Scheemaecker
* @version $Name: RELEASE_2_2_1 $, $Revision: 1.3 $
*/
public class XMLValidationException
extends XMLException
{
/**
* An element was missing.
*/
public static final int MISSING_ELEMENT = 1;
/**
* An unexpected element was encountered.
*/
public static final int UNEXPECTED_ELEMENT = 2;
/**
* An attribute was missing.
*/
public static final int MISSING_ATTRIBUTE = 3;
/**
* An unexpected attribute was encountered.
*/
public static final int UNEXPECTED_ATTRIBUTE = 4;
/**
* An attribute has an invalid value.
*/
public static final int ATTRIBUTE_WITH_INVALID_VALUE = 5;
/**
* A PCDATA element was missing.
*/
public static final int MISSING_PCDATA = 6;
/**
* An unexpected PCDATA element was encountered.
*/
public static final int UNEXPECTED_PCDATA = 7;
/**
* Another error than those specified in this class was encountered.
*/
public static final int MISC_ERROR = 0;
/**
* Which error occurred.
*/
//private int errorType;
/**
* The name of the element where the exception occurred.
*/
private String elementName;
/**
* The name of the attribute where the exception occurred.
*/
private String attributeName;
/**
* The value of the attribute where the exception occurred.
*/
private String attributeValue;
/**
* Creates a new exception.
*
* @param errorType the type of validity error
* @param systemID the system ID from where the data came
* @param lineNr the line number in the XML data where the
* exception occurred.
* @param elementName the name of the offending element
* @param attributeName the name of the offending attribute
* @param attributeValue the value of the offending attribute
* @param msg the message of the exception.
*/
public XMLValidationException(int errorType,
String systemID,
int lineNr,
String elementName,
String attributeName,
String attributeValue,
String msg)
{
super(systemID, lineNr, null,
msg + ((elementName == null) ? "" : (", element=" + elementName))
+ ((attributeName == null) ? ""
: (", attribute=" + attributeName))
+ ((attributeValue == null) ? ""
: (", value='" + attributeValue + "'")),
false);
this.elementName = elementName;
this.attributeName = attributeName;
this.attributeValue = attributeValue;
}
/**
* Cleans up the object when it's destroyed.
*/
protected void finalize()
throws Throwable
{
this.elementName = null;
this.attributeName = null;
this.attributeValue = null;
super.finalize();
}
/**
* Returns the name of the element in which the validation is violated.
* If there is no current element, null is returned.
*/
public String getElementName()
{
return this.elementName;
}
/**
* Returns the name of the attribute in which the validation is violated.
* If there is no current attribute, null is returned.
*/
public String getAttributeName()
{
return this.attributeName;
}
/**
* Returns the value of the attribute in which the validation is violated.
* If there is no current attribute, null is returned.
*/
public String getAttributeValue()
{
return this.attributeValue;
}
}

View File

@ -0,0 +1,631 @@
/* NonValidator.java NanoXML/Java
*
* $Revision: 1.4 $
* $Date: 2002/02/03 21:19:38 $
* $Name: RELEASE_2_2_1 $
*
* This file is part of NanoXML 2 for Java.
* Copyright (C) 2000-2002 Marc De Scheemaecker, All Rights Reserved.
*
* This software is provided 'as-is', without any express or implied warranty.
* In no event will the authors be held liable for any damages arising from the
* use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software in
* a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
*
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
*
* 3. This notice may not be removed or altered from any source distribution.
*/
package processing.xml;
import java.io.Reader;
import java.io.StringReader;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Properties;
import java.util.Stack;
/**
* XMLValidator implementation based on NonValidator (which implemented
* IXMLValidator in the original NanoXML).
* This implementation processes the DTD and handles entity definitions.
* It does not do any validation itself.
*
* @author Marc De Scheemaecker
* @author processing.org
*/
public class XMLValidator
{
/**
* The parameter entity resolver.
*/
protected XMLEntityResolver parameterEntityResolver;
/**
* Contains the default values for attributes for the different element
* types.
*/
protected Hashtable<String, Properties> attributeDefaultValues;
/**
* The stack of elements to be processed.
*/
protected Stack<Properties> currentElements;
/**
* Creates the &quot;validator&quot;.
*/
public XMLValidator()
{
this.attributeDefaultValues = new Hashtable<String, Properties>();
this.currentElements = new Stack<Properties>();
this.parameterEntityResolver = new XMLEntityResolver();
}
/**
* Cleans up the object when it's destroyed.
*/
protected void finalize()
throws Throwable
{
this.parameterEntityResolver = null;
this.attributeDefaultValues.clear();
this.attributeDefaultValues = null;
this.currentElements.clear();
this.currentElements = null;
super.finalize();
}
/**
* Sets the parameter entity resolver.
*
* @param resolver the entity resolver.
*/
public void setParameterEntityResolver(XMLEntityResolver resolver)
{
this.parameterEntityResolver = resolver;
}
/**
* Returns the parameter entity resolver.
*
* @return the entity resolver.
*/
public XMLEntityResolver getParameterEntityResolver()
{
return this.parameterEntityResolver;
}
/**
* Parses the DTD. The validator object is responsible for reading the
* full DTD.
*
* @param publicID the public ID, which may be null.
* @param reader the reader to read the DTD from.
* @param entityResolver the entity resolver.
* @param external true if the DTD is external.
*
* @throws java.lang.Exception
* If something went wrong.
*/
public void parseDTD(String publicID,
StdXMLReader reader,
XMLEntityResolver entityResolver,
boolean external)
throws Exception
{
XMLUtil.skipWhitespace(reader, null);
int origLevel = reader.getStreamLevel();
for (;;) {
String str = XMLUtil.read(reader, '%');
char ch = str.charAt(0);
if (ch == '%') {
XMLUtil.processEntity(str, reader,
this.parameterEntityResolver);
continue;
} else if (ch == '<') {
this.processElement(reader, entityResolver);
} else if (ch == ']') {
return; // end internal DTD
} else {
XMLUtil.errorInvalidInput(reader.getSystemID(),
reader.getLineNr(),
str);
}
do {
ch = reader.read();
if (external && (reader.getStreamLevel() < origLevel)) {
reader.unread(ch);
return; // end external DTD
}
} while ((ch == ' ') || (ch == '\t') || (ch == '\n')
|| (ch == '\r'));
reader.unread(ch);
}
}
/**
* Processes an element in the DTD.
*
* @param reader the reader to read data from.
* @param entityResolver the entity resolver.
*
* @throws java.lang.Exception
* If something went wrong.
*/
protected void processElement(StdXMLReader reader,
XMLEntityResolver entityResolver)
throws Exception
{
String str = XMLUtil.read(reader, '%');
char ch = str.charAt(0);
if (ch != '!') {
XMLUtil.skipTag(reader);
return;
}
str = XMLUtil.read(reader, '%');
ch = str.charAt(0);
switch (ch) {
case '-':
XMLUtil.skipComment(reader);
break;
case '[':
this.processConditionalSection(reader, entityResolver);
break;
case 'E':
this.processEntity(reader, entityResolver);
break;
case 'A':
this.processAttList(reader, entityResolver);
break;
default:
XMLUtil.skipTag(reader);
}
}
/**
* Processes a conditional section.
*
* @param reader the reader to read data from.
* @param entityResolver the entity resolver.
*
* @throws java.lang.Exception
* If something went wrong.
*/
protected void processConditionalSection(StdXMLReader reader,
XMLEntityResolver entityResolver)
throws Exception
{
XMLUtil.skipWhitespace(reader, null);
String str = XMLUtil.read(reader, '%');
char ch = str.charAt(0);
if (ch != 'I') {
XMLUtil.skipTag(reader);
return;
}
str = XMLUtil.read(reader, '%');
ch = str.charAt(0);
switch (ch) {
case 'G':
this.processIgnoreSection(reader, entityResolver);
return;
case 'N':
break;
default:
XMLUtil.skipTag(reader);
return;
}
if (! XMLUtil.checkLiteral(reader, "CLUDE")) {
XMLUtil.skipTag(reader);
return;
}
XMLUtil.skipWhitespace(reader, null);
str = XMLUtil.read(reader, '%');
ch = str.charAt(0);
if (ch != '[') {
XMLUtil.skipTag(reader);
return;
}
Reader subreader = new CDATAReader(reader);
StringBuffer buf = new StringBuffer(1024);
for (;;) {
int ch2 = subreader.read();
if (ch2 < 0) {
break;
}
buf.append((char) ch2);
}
subreader.close();
reader.startNewStream(new StringReader(buf.toString()));
}
/**
* Processes an ignore section.
*
* @param reader the reader to read data from.
* @param entityResolver the entity resolver.
*
* @throws java.lang.Exception
* If something went wrong.
*/
protected void processIgnoreSection(StdXMLReader reader,
XMLEntityResolver entityResolver)
throws Exception
{
if (! XMLUtil.checkLiteral(reader, "NORE")) {
XMLUtil.skipTag(reader);
return;
}
XMLUtil.skipWhitespace(reader, null);
String str = XMLUtil.read(reader, '%');
char ch = str.charAt(0);
if (ch != '[') {
XMLUtil.skipTag(reader);
return;
}
Reader subreader = new CDATAReader(reader);
subreader.close();
}
/**
* Processes an ATTLIST element.
*
* @param reader the reader to read data from.
* @param entityResolver the entity resolver.
*
* @throws java.lang.Exception
* If something went wrong.
*/
protected void processAttList(StdXMLReader reader,
XMLEntityResolver entityResolver)
throws Exception
{
if (! XMLUtil.checkLiteral(reader, "TTLIST")) {
XMLUtil.skipTag(reader);
return;
}
XMLUtil.skipWhitespace(reader, null);
String str = XMLUtil.read(reader, '%');
char ch = str.charAt(0);
while (ch == '%') {
XMLUtil.processEntity(str, reader,
this.parameterEntityResolver);
str = XMLUtil.read(reader, '%');
ch = str.charAt(0);
}
reader.unread(ch);
String elementName = XMLUtil.scanIdentifier(reader);
XMLUtil.skipWhitespace(reader, null);
str = XMLUtil.read(reader, '%');
ch = str.charAt(0);
while (ch == '%') {
XMLUtil.processEntity(str, reader,
this.parameterEntityResolver);
str = XMLUtil.read(reader, '%');
ch = str.charAt(0);
}
Properties props = new Properties();
while (ch != '>') {
reader.unread(ch);
String attName = XMLUtil.scanIdentifier(reader);
XMLUtil.skipWhitespace(reader, null);
str = XMLUtil.read(reader, '%');
ch = str.charAt(0);
while (ch == '%') {
XMLUtil.processEntity(str, reader,
this.parameterEntityResolver);
str = XMLUtil.read(reader, '%');
ch = str.charAt(0);
}
if (ch == '(') {
while (ch != ')') {
str = XMLUtil.read(reader, '%');
ch = str.charAt(0);
while (ch == '%') {
XMLUtil.processEntity(str, reader,
this.parameterEntityResolver);
str = XMLUtil.read(reader, '%');
ch = str.charAt(0);
}
}
} else {
reader.unread(ch);
XMLUtil.scanIdentifier(reader);
}
XMLUtil.skipWhitespace(reader, null);
str = XMLUtil.read(reader, '%');
ch = str.charAt(0);
while (ch == '%') {
XMLUtil.processEntity(str, reader,
this.parameterEntityResolver);
str = XMLUtil.read(reader, '%');
ch = str.charAt(0);
}
if (ch == '#') {
str = XMLUtil.scanIdentifier(reader);
XMLUtil.skipWhitespace(reader, null);
if (! str.equals("FIXED")) {
XMLUtil.skipWhitespace(reader, null);
str = XMLUtil.read(reader, '%');
ch = str.charAt(0);
while (ch == '%') {
XMLUtil.processEntity(str, reader,
this.parameterEntityResolver);
str = XMLUtil.read(reader, '%');
ch = str.charAt(0);
}
continue;
}
} else {
reader.unread(ch);
}
String value = XMLUtil.scanString(reader, '%',
this.parameterEntityResolver);
props.put(attName, value);
XMLUtil.skipWhitespace(reader, null);
str = XMLUtil.read(reader, '%');
ch = str.charAt(0);
while (ch == '%') {
XMLUtil.processEntity(str, reader,
this.parameterEntityResolver);
str = XMLUtil.read(reader, '%');
ch = str.charAt(0);
}
}
if (! props.isEmpty()) {
this.attributeDefaultValues.put(elementName, props);
}
}
/**
* Processes an ENTITY element.
*
* @param reader the reader to read data from.
* @param entityResolver the entity resolver.
*
* @throws java.lang.Exception
* If something went wrong.
*/
protected void processEntity(StdXMLReader reader,
XMLEntityResolver entityResolver)
throws Exception
{
if (! XMLUtil.checkLiteral(reader, "NTITY")) {
XMLUtil.skipTag(reader);
return;
}
XMLUtil.skipWhitespace(reader, null);
char ch = XMLUtil.readChar(reader, '\0');
if (ch == '%') {
XMLUtil.skipWhitespace(reader, null);
entityResolver = this.parameterEntityResolver;
} else {
reader.unread(ch);
}
String key = XMLUtil.scanIdentifier(reader);
XMLUtil.skipWhitespace(reader, null);
ch = XMLUtil.readChar(reader, '%');
String systemID = null;
String publicID = null;
switch (ch) {
case 'P':
if (! XMLUtil.checkLiteral(reader, "UBLIC")) {
XMLUtil.skipTag(reader);
return;
}
XMLUtil.skipWhitespace(reader, null);
publicID = XMLUtil.scanString(reader, '%',
this.parameterEntityResolver);
XMLUtil.skipWhitespace(reader, null);
systemID = XMLUtil.scanString(reader, '%',
this.parameterEntityResolver);
XMLUtil.skipWhitespace(reader, null);
XMLUtil.readChar(reader, '%');
break;
case 'S':
if (! XMLUtil.checkLiteral(reader, "YSTEM")) {
XMLUtil.skipTag(reader);
return;
}
XMLUtil.skipWhitespace(reader, null);
systemID = XMLUtil.scanString(reader, '%',
this.parameterEntityResolver);
XMLUtil.skipWhitespace(reader, null);
XMLUtil.readChar(reader, '%');
break;
case '"':
case '\'':
reader.unread(ch);
String value = XMLUtil.scanString(reader, '%',
this.parameterEntityResolver);
entityResolver.addInternalEntity(key, value);
XMLUtil.skipWhitespace(reader, null);
XMLUtil.readChar(reader, '%');
break;
default:
XMLUtil.skipTag(reader);
}
if (systemID != null) {
entityResolver.addExternalEntity(key, publicID, systemID);
}
}
/**
* Indicates that an element has been started.
*
* @param name the name of the element.
* @param systemId the system ID of the XML data of the element.
* @param lineNr the line number in the XML data of the element.
*/
public void elementStarted(String name,
String systemId,
int lineNr)
{
Properties attribs
= (Properties) this.attributeDefaultValues.get(name);
if (attribs == null) {
attribs = new Properties();
} else {
attribs = (Properties) attribs.clone();
}
this.currentElements.push(attribs);
}
/**
* Indicates that the current element has ended.
*
* @param name the name of the element.
* @param systemId the system ID of the XML data of the element.
* @param lineNr the line number in the XML data of the element.
*/
public void elementEnded(String name,
String systemId,
int lineNr)
{
// nothing to do
}
/**
* This method is called when the attributes of an XML element have been
* processed.
* If there are attributes with a default value which have not been
* specified yet, they have to be put into <I>extraAttributes</I>.
*
* @param name the name of the element.
* @param extraAttributes where to put extra attributes.
* @param systemId the system ID of the XML data of the element.
* @param lineNr the line number in the XML data of the element.
*/
public void elementAttributesProcessed(String name,
Properties extraAttributes,
String systemId,
int lineNr)
{
Properties props = (Properties) this.currentElements.pop();
Enumeration<?> en = props.keys();
while (en.hasMoreElements()) {
String key = (String) en.nextElement();
extraAttributes.put(key, props.get(key));
}
}
/**
* Indicates that an attribute has been added to the current element.
*
* @param key the name of the attribute.
* @param value the value of the attribute.
* @param systemId the system ID of the XML data of the element.
* @param lineNr the line number in the XML data of the element.
*/
public void attributeAdded(String key,
String value,
String systemId,
int lineNr)
{
Properties props = (Properties) this.currentElements.peek();
if (props.containsKey(key)) {
props.remove(key);
}
}
/**
* Indicates that a new #PCDATA element has been encountered.
*
* @param systemId the system ID of the XML data of the element.
* @param lineNr the line number in the XML data of the element.
*/
public void PCDataAdded(String systemId,
int lineNr)
{
// nothing to do
}
}

View File

@ -0,0 +1,307 @@
/* XMLWriter.java NanoXML/Java
*
* $Revision: 1.4 $
* $Date: 2002/03/24 11:37:51 $
* $Name: RELEASE_2_2_1 $
*
* This file is part of NanoXML 2 for Java.
* Copyright (C) 2000-2002 Marc De Scheemaecker, All Rights Reserved.
*
* This software is provided 'as-is', without any express or implied warranty.
* In no event will the authors be held liable for any damages arising from the
* use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software in
* a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
*
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
*
* 3. This notice may not be removed or altered from any source distribution.
*/
package processing.xml;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.Writer;
import java.util.Enumeration;
import java.util.Vector;
/**
* An XMLWriter writes XML data to a stream.
*
* @author Marc De Scheemaecker
*/
public class XMLWriter
{
/**
* Where to write the output to.
*/
private PrintWriter writer;
/**
* Creates a new XML writer.
*
* @param writer where to write the output to.
*/
public XMLWriter(Writer writer)
{
if (writer instanceof PrintWriter) {
this.writer = (PrintWriter) writer;
} else {
this.writer = new PrintWriter(writer);
}
}
/**
* Creates a new XML writer.
*
* @param stream where to write the output to.
*/
public XMLWriter(OutputStream stream)
{
this.writer = new PrintWriter(stream);
}
/**
* Cleans up the object when it's destroyed.
*/
protected void finalize()
throws Throwable
{
this.writer = null;
super.finalize();
}
/**
* Writes an XML element.
*
* @param xml the non-null XML element to write.
*/
public void write(XMLElement xml)
throws IOException
{
this.write(xml, false, 0, true);
}
/**
* Writes an XML element.
*
* @param xml the non-null XML element to write.
* @param prettyPrint if spaces need to be inserted to make the output more
* readable
*/
public void write(XMLElement xml,
boolean prettyPrint)
throws IOException
{
this.write(xml, prettyPrint, 0, true);
}
/**
* Writes an XML element.
*
* @param xml the non-null XML element to write.
* @param prettyPrint if spaces need to be inserted to make the output more
* readable
* @param indent how many spaces to indent the element.
*/
public void write(XMLElement xml,
boolean prettyPrint,
int indent)
throws IOException
{
this.write(xml, prettyPrint, indent, true);
}
/**
* Writes an XML element.
*
* @param xml the non-null XML element to write.
* @param prettyPrint if spaces need to be inserted to make the output more
* readable
* @param indent how many spaces to indent the element.
*/
public void write(XMLElement xml,
boolean prettyPrint,
int indent,
boolean collapseEmptyElements)
throws IOException
{
if (prettyPrint) {
for (int i = 0; i < indent; i++) {
this.writer.print(' ');
}
}
if (xml.getLocalName() == null) {
if (xml.getContent() != null) {
if (prettyPrint) {
this.writeEncoded(xml.getContent().trim());
writer.println();
} else {
this.writeEncoded(xml.getContent());
}
}
} else {
this.writer.print('<');
this.writer.print(xml.getName());
Vector<String> nsprefixes = new Vector<String>();
if (xml.getNamespace() != null) {
if (xml.getLocalName().equals(xml.getName())) {
this.writer.print(" xmlns=\"" + xml.getNamespace() + '"');
} else {
String prefix = xml.getName();
prefix = prefix.substring(0, prefix.indexOf(':'));
nsprefixes.addElement(prefix);
this.writer.print(" xmlns:" + prefix);
this.writer.print("=\"" + xml.getNamespace() + "\"");
}
}
Enumeration<?> en = xml.enumerateAttributeNames();
while (en.hasMoreElements()) {
String key = (String) en.nextElement();
int index = key.indexOf(':');
if (index >= 0) {
String namespace = xml.getAttributeNamespace(key);
if (namespace != null) {
String prefix = key.substring(0, index);
if (! nsprefixes.contains(prefix)) {
this.writer.print(" xmlns:" + prefix);
this.writer.print("=\"" + namespace + '"');
nsprefixes.addElement(prefix);
}
}
}
}
en = xml.enumerateAttributeNames();
while (en.hasMoreElements()) {
String key = (String) en.nextElement();
String value = xml.getAttribute(key, null);
this.writer.print(" " + key + "=\"");
this.writeEncoded(value);
this.writer.print('"');
}
if ((xml.getContent() != null)
&& (xml.getContent().length() > 0)) {
writer.print('>');
this.writeEncoded(xml.getContent());
writer.print("</" + xml.getName() + '>');
if (prettyPrint) {
writer.println();
}
} else if (xml.hasChildren() || (! collapseEmptyElements)) {
writer.print('>');
if (prettyPrint) {
writer.println();
}
en = xml.enumerateChildren();
while (en.hasMoreElements()) {
XMLElement child = (XMLElement) en.nextElement();
this.write(child, prettyPrint, indent + 4,
collapseEmptyElements);
}
if (prettyPrint) {
for (int i = 0; i < indent; i++) {
this.writer.print(' ');
}
}
this.writer.print("</" + xml.getName() + ">");
if (prettyPrint) {
writer.println();
}
} else {
this.writer.print("/>");
if (prettyPrint) {
writer.println();
}
}
}
this.writer.flush();
}
/**
* Writes a string encoding reserved characters.
*
* @param str the string to write.
*/
private void writeEncoded(String str)
{
for (int i = 0; i < str.length(); i++) {
char c = str.charAt(i);
switch (c) {
case 0x0A:
this.writer.print(c);
break;
case '<':
this.writer.print("&lt;");
break;
case '>':
this.writer.print("&gt;");
break;
case '&':
this.writer.print("&amp;");
break;
case '\'':
this.writer.print("&apos;");
break;
case '"':
this.writer.print("&quot;");
break;
default:
if ((c < ' ') || (c > 0x7E)) {
this.writer.print("&#x");
this.writer.print(Integer.toString(c, 16));
this.writer.print(';');
} else {
this.writer.print(c);
}
}
}
}
}