mirror of
https://github.com/esp8266/Arduino.git
synced 2025-08-12 20:49:16 +03:00
Importing Processing rev. 5503 (1.0.3).
This commit is contained in:
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());
|
||||
}
|
||||
|
||||
}
|
Reference in New Issue
Block a user