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:
193
core/src/processing/xml/CDATAReader.java
Normal file
193
core/src/processing/xml/CDATAReader.java
Normal 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;
|
||||
}
|
||||
|
||||
}
|
212
core/src/processing/xml/ContentReader.java
Normal file
212
core/src/processing/xml/ContentReader.java
Normal 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());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
157
core/src/processing/xml/PIReader.java
Normal file
157
core/src/processing/xml/PIReader.java
Normal 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 (?>) 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
356
core/src/processing/xml/StdXMLBuilder.java
Normal file
356
core/src/processing/xml/StdXMLBuilder.java
Normal 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;
|
||||
}
|
||||
|
||||
}
|
684
core/src/processing/xml/StdXMLParser.java
Normal file
684
core/src/processing/xml/StdXMLParser.java
Normal 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 (<!...>).
|
||||
*
|
||||
* @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());
|
||||
}
|
||||
|
||||
}
|
626
core/src/processing/xml/StdXMLReader.java
Normal file
626
core/src/processing/xml/StdXMLReader.java
Normal 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 <?xml...?> 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;
|
||||
}
|
||||
|
||||
}
|
153
core/src/processing/xml/XMLAttribute.java
Normal file
153
core/src/processing/xml/XMLAttribute.java
Normal 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;
|
||||
}
|
||||
|
||||
}
|
1353
core/src/processing/xml/XMLElement.java
Normal file
1353
core/src/processing/xml/XMLElement.java
Normal file
File diff suppressed because it is too large
Load Diff
173
core/src/processing/xml/XMLEntityResolver.java
Normal file
173
core/src/processing/xml/XMLEntityResolver.java
Normal 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", "&");
|
||||
this.entities.put("quot", """);
|
||||
this.entities.put("apos", "'");
|
||||
this.entities.put("lt", "<");
|
||||
this.entities.put("gt", ">");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
286
core/src/processing/xml/XMLException.java
Normal file
286
core/src/processing/xml/XMLException.java
Normal 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;
|
||||
}
|
||||
|
||||
}
|
69
core/src/processing/xml/XMLParseException.java
Normal file
69
core/src/processing/xml/XMLParseException.java
Normal 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);
|
||||
}
|
||||
|
||||
}
|
758
core/src/processing/xml/XMLUtil.java
Normal file
758
core/src/processing/xml/XMLUtil.java
Normal 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 <!- 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 (& 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 (& or %) used to indicate
|
||||
* an entity
|
||||
*
|
||||
* @return the character, or an entity expression (like e.g. &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 (& 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);
|
||||
}
|
||||
|
||||
}
|
190
core/src/processing/xml/XMLValidationException.java
Normal file
190
core/src/processing/xml/XMLValidationException.java
Normal 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;
|
||||
}
|
||||
|
||||
}
|
631
core/src/processing/xml/XMLValidator.java
Normal file
631
core/src/processing/xml/XMLValidator.java
Normal 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 "validator".
|
||||
*/
|
||||
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
|
||||
}
|
||||
|
||||
}
|
307
core/src/processing/xml/XMLWriter.java
Normal file
307
core/src/processing/xml/XMLWriter.java
Normal 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("<");
|
||||
break;
|
||||
|
||||
case '>':
|
||||
this.writer.print(">");
|
||||
break;
|
||||
|
||||
case '&':
|
||||
this.writer.print("&");
|
||||
break;
|
||||
|
||||
case '\'':
|
||||
this.writer.print("'");
|
||||
break;
|
||||
|
||||
case '"':
|
||||
this.writer.print(""");
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
Reference in New Issue
Block a user