From 2d8cf20d0d5ca6b1fbdefc22229d4b7cf1497ede Mon Sep 17 00:00:00 2001
From: mark
Date: Tue, 17 Jan 2006 18:09:40 +0000
Subject: Imported GNU Classpath 0.20 * Makefile.am
(AM_CPPFLAGS): Add classpath/include. *
java/nio/charset/spi/CharsetProvider.java: New override file. *
java/security/Security.java: Likewise. * sources.am: Regenerated.
* Makefile.in: Likewise.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@109831 138bc75d-0d04-0410-961f-82ee72b054a4
---
.../gnu/xml/aelfred2/ContentHandler2.java | 65 -
libjava/classpath/gnu/xml/aelfred2/SAXDriver.java | 15 -
libjava/classpath/gnu/xml/aelfred2/XmlParser.java | 3 -
libjava/classpath/gnu/xml/dom/Consumer.java | 16 -
libjava/classpath/gnu/xml/dom/DomDocument.java | 25 +
libjava/classpath/gnu/xml/dom/DomElement.java | 33 +
libjava/classpath/gnu/xml/dom/DomNamedNodeMap.java | 2 +-
libjava/classpath/gnu/xml/dom/DomNode.java | 215 +-
libjava/classpath/gnu/xml/dom/ls/DomLSParser.java | 1 +
libjava/classpath/gnu/xml/dom/ls/SAXEventSink.java | 182 +-
.../classpath/gnu/xml/pipeline/DomConsumer.java | 17 +-
.../classpath/gnu/xml/pipeline/EventFilter.java | 15 +-
.../classpath/gnu/xml/stream/BufferedReader.java | 198 +
libjava/classpath/gnu/xml/stream/CRLFReader.java | 180 +
libjava/classpath/gnu/xml/stream/SAXParser.java | 966 ++++
.../classpath/gnu/xml/stream/SAXParserFactory.java | 104 +
.../classpath/gnu/xml/stream/UnicodeReader.java | 201 +
.../classpath/gnu/xml/stream/XIncludeFilter.java | 932 ++++
.../gnu/xml/stream/XMLInputFactoryImpl.java | 75 +-
libjava/classpath/gnu/xml/stream/XMLParser.java | 5266 ++++++++++++++++++++
.../gnu/xml/stream/XMLStreamWriterImpl.java | 2 +
.../classpath/gnu/xml/transform/AttributeNode.java | 54 +-
libjava/classpath/gnu/xml/transform/Bindings.java | 22 +
.../xml/transform/ElementAvailableFunction.java | 19 +-
.../classpath/gnu/xml/transform/ElementNode.java | 157 +-
.../xml/transform/FunctionAvailableFunction.java | 28 +-
.../classpath/gnu/xml/transform/LiteralNode.java | 64 +-
.../classpath/gnu/xml/transform/MessageNode.java | 23 +-
.../gnu/xml/transform/NamespaceProxy.java | 77 +
.../gnu/xml/transform/StreamSerializer.java | 474 +-
.../gnu/xml/transform/StrippingInstruction.java | 73 +
.../classpath/gnu/xml/transform/Stylesheet.java | 375 +-
.../gnu/xml/transform/TransformerFactoryImpl.java | 49 +-
.../gnu/xml/transform/TransformerImpl.java | 240 +-
.../classpath/gnu/xml/transform/ValueOfNode.java | 56 +-
libjava/classpath/gnu/xml/xpath/Expr.java | 45 +-
.../classpath/gnu/xml/xpath/LocalNameFunction.java | 6 +-
libjava/classpath/gnu/xml/xpath/NameFunction.java | 6 +-
libjava/classpath/gnu/xml/xpath/NameTest.java | 39 +-
libjava/classpath/gnu/xml/xpath/NamespaceTest.java | 26 +-
.../gnu/xml/xpath/NamespaceUriFunction.java | 6 +-
libjava/classpath/gnu/xml/xpath/NodeTypeTest.java | 20 +-
libjava/classpath/gnu/xml/xpath/Selector.java | 157 +-
.../classpath/gnu/xml/xpath/SubstringFunction.java | 21 +-
44 files changed, 9264 insertions(+), 1286 deletions(-)
delete mode 100644 libjava/classpath/gnu/xml/aelfred2/ContentHandler2.java
create mode 100644 libjava/classpath/gnu/xml/stream/BufferedReader.java
create mode 100644 libjava/classpath/gnu/xml/stream/CRLFReader.java
create mode 100644 libjava/classpath/gnu/xml/stream/SAXParser.java
create mode 100644 libjava/classpath/gnu/xml/stream/SAXParserFactory.java
create mode 100644 libjava/classpath/gnu/xml/stream/UnicodeReader.java
create mode 100644 libjava/classpath/gnu/xml/stream/XIncludeFilter.java
create mode 100644 libjava/classpath/gnu/xml/stream/XMLParser.java
create mode 100644 libjava/classpath/gnu/xml/transform/NamespaceProxy.java
create mode 100644 libjava/classpath/gnu/xml/transform/StrippingInstruction.java
(limited to 'libjava/classpath/gnu/xml')
diff --git a/libjava/classpath/gnu/xml/aelfred2/ContentHandler2.java b/libjava/classpath/gnu/xml/aelfred2/ContentHandler2.java
deleted file mode 100644
index 15161383592..00000000000
--- a/libjava/classpath/gnu/xml/aelfred2/ContentHandler2.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/* ContentHandler2.java --
- Copyright (C) 2004 Free Software Foundation, Inc.
-
-This file is part of GNU Classpath.
-
-GNU Classpath is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Classpath is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Classpath; see the file COPYING. If not, write to the
-Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
-02110-1301 USA.
-
-Linking this library statically or dynamically with other modules is
-making a combined work based on this library. Thus, the terms and
-conditions of the GNU General Public License cover the whole
-combination.
-
-As a special exception, the copyright holders of this library give you
-permission to link this library with independent modules to produce an
-executable, regardless of the license terms of these independent
-modules, and to copy and distribute the resulting executable under
-terms of your choice, provided that you also meet, for each linked
-independent module, the terms and conditions of the license of that
-module. An independent module is a module which is not derived from
-or based on this library. If you modify this library, you may extend
-this exception to your version of the library, but you are not
-obligated to do so. If you do not wish to do so, delete this
-exception statement from your version. */
-
-package gnu.xml.aelfred2;
-
-import org.xml.sax.ContentHandler;
-import org.xml.sax.SAXException;
-
-/**
- * Extension to the SAX ContentHandler interface to report parsing events
- * and parameters required by DOM Level 3 but not supported by SAX.
- *
- * @author Chris Burdess
- */
-public interface ContentHandler2
- extends ContentHandler
-{
-
- /**
- * Reports the XML declaration.
- * @param version the value of the version attribute in the XML
- * declaration
- * @param encoding the encoding specified in the XML declaration, if any
- * @param standalone the standalone attribute from the XML declaration
- * @param inputEncoding the encoding of the XML input
- */
- void xmlDecl(String version, String encoding, boolean standalone,
- String inputEncoding)
- throws SAXException;
-
-}
diff --git a/libjava/classpath/gnu/xml/aelfred2/SAXDriver.java b/libjava/classpath/gnu/xml/aelfred2/SAXDriver.java
index 6864ff65971..e7c4d5a3f64 100644
--- a/libjava/classpath/gnu/xml/aelfred2/SAXDriver.java
+++ b/libjava/classpath/gnu/xml/aelfred2/SAXDriver.java
@@ -655,21 +655,6 @@ final public class SAXDriver
attributesList.clear();
}
- void xmlDecl(String version,
- String encoding,
- boolean standalone,
- String inputEncoding)
- throws SAXException
- {
- if (contentHandler instanceof ContentHandler2)
- {
- ((ContentHandler2) contentHandler).xmlDecl(version,
- encoding,
- standalone,
- inputEncoding);
- }
- }
-
void skippedEntity(String name)
throws SAXException
{
diff --git a/libjava/classpath/gnu/xml/aelfred2/XmlParser.java b/libjava/classpath/gnu/xml/aelfred2/XmlParser.java
index f2abb889666..ab2ed16f946 100644
--- a/libjava/classpath/gnu/xml/aelfred2/XmlParser.java
+++ b/libjava/classpath/gnu/xml/aelfred2/XmlParser.java
@@ -841,9 +841,6 @@ final class XmlParser
{
inputEncoding = encodingName;
}
- handler.xmlDecl(version, encodingName, docIsStandalone,
- inputEncoding);
-
return encodingName;
}
diff --git a/libjava/classpath/gnu/xml/dom/Consumer.java b/libjava/classpath/gnu/xml/dom/Consumer.java
index f99e221e998..026e2754ef9 100644
--- a/libjava/classpath/gnu/xml/dom/Consumer.java
+++ b/libjava/classpath/gnu/xml/dom/Consumer.java
@@ -301,22 +301,6 @@ public class Consumer extends DomConsumer
doc.setBuilding(true);
}
- /**
- * Required by DOM Level 3 to report document parameters
- */
- public void xmlDecl(String version,
- String encoding,
- boolean standalone,
- String inputEncoding)
- throws SAXException
- {
- super.xmlDecl(version, encoding, standalone, inputEncoding);
-
- DomDocument doc = (DomDocument) getDocument();
- doc.setXmlEncoding(encoding);
- doc.setInputEncoding(inputEncoding);
- }
-
public void endDocument ()
throws SAXException
{
diff --git a/libjava/classpath/gnu/xml/dom/DomDocument.java b/libjava/classpath/gnu/xml/dom/DomDocument.java
index 29b8dc72e53..900d03ac3dc 100644
--- a/libjava/classpath/gnu/xml/dom/DomDocument.java
+++ b/libjava/classpath/gnu/xml/dom/DomDocument.java
@@ -1313,6 +1313,31 @@ public class DomDocument
return config;
}
+ public boolean isEqualNode(Node arg)
+ {
+ if (!super.isEqualNode(arg))
+ return false;
+ Document d = (Document) arg;
+ String dversion = d.getXmlVersion();
+ if (dversion == null || !dversion.equals(version))
+ return false;
+ boolean dstandalone = d.getXmlStandalone();
+ if (dstandalone != standalone)
+ return false;
+ String dencoding = d.getXmlEncoding();
+ if (dencoding == null || dencoding.equalsIgnoreCase("UTF-8"))
+ {
+ if (encoding != null && !encoding.equalsIgnoreCase("UTF-8"))
+ return false;
+ }
+ else
+ {
+ if (!dencoding.equals(encoding))
+ return false;
+ }
+ return true;
+ }
+
public void normalizeDocument()
{
boolean save = building;
diff --git a/libjava/classpath/gnu/xml/dom/DomElement.java b/libjava/classpath/gnu/xml/dom/DomElement.java
index 34509f647bc..f55b084cc94 100644
--- a/libjava/classpath/gnu/xml/dom/DomElement.java
+++ b/libjava/classpath/gnu/xml/dom/DomElement.java
@@ -519,5 +519,38 @@ public class DomElement
Attr attr = (Attr) attrs.getNamedItemNS(namespaceURI, localName);
setIdAttributeNode(attr, isId);
}
+
+ public boolean isEqualNode(Node arg)
+ {
+ if (!super.isEqualNode(arg))
+ return false;
+ getAttributes();
+ NamedNodeMap argAttrs = arg.getAttributes();
+ int len = argAttrs.getLength();
+ if (argAttrs == null || (len != attributes.length))
+ return false;
+ for (int i = 0; i < len; i++)
+ {
+ Node argCtx = argAttrs.item(i);
+ // Don't compare namespace nodes
+ if (XMLConstants.XMLNS_ATTRIBUTE_NS_URI
+ .equals(argCtx.getNamespaceURI()))
+ continue;
+ // Find corresponding attribute node
+ DomNode ctx = attributes.first;
+ for (; ctx != null; ctx = ctx.next)
+ {
+ if (XMLConstants.XMLNS_ATTRIBUTE_NS_URI
+ .equals(ctx.getNamespaceURI()))
+ continue;
+ if (!ctx.isEqualNode(argCtx))
+ continue;
+ break;
+ }
+ if (ctx == null)
+ return false; // not found
+ }
+ return true;
+ }
}
diff --git a/libjava/classpath/gnu/xml/dom/DomNamedNodeMap.java b/libjava/classpath/gnu/xml/dom/DomNamedNodeMap.java
index 6f224029ac3..e3f08e4b4b7 100644
--- a/libjava/classpath/gnu/xml/dom/DomNamedNodeMap.java
+++ b/libjava/classpath/gnu/xml/dom/DomNamedNodeMap.java
@@ -319,7 +319,7 @@ public class DomNamedNodeMap
if (ns)
{
String tln = ctx.getLocalName();
- if (tln.equals(name))
+ if (name != null && name.equals(tln))
{
String tu = ctx.getNamespaceURI();
if ((tu == null && uri == null) ||
diff --git a/libjava/classpath/gnu/xml/dom/DomNode.java b/libjava/classpath/gnu/xml/dom/DomNode.java
index 3f29fb1283d..93f7c6f64f3 100644
--- a/libjava/classpath/gnu/xml/dom/DomNode.java
+++ b/libjava/classpath/gnu/xml/dom/DomNode.java
@@ -38,6 +38,7 @@ exception statement from your version. */
package gnu.xml.dom;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
@@ -149,7 +150,7 @@ public abstract class DomNode
boolean readonly;
// event registrations
- private ListenerRecord[] listeners;
+ private HashSet listeners;
private int nListeners;
// DOM Level 3 userData dictionary.
@@ -167,19 +168,6 @@ public abstract class DomNode
*/
public void compact()
{
- if (listeners != null && listeners.length != nListeners)
- {
- if (nListeners == 0)
- {
- listeners = null;
- }
- else
- {
- ListenerRecord[] l = new ListenerRecord[nListeners];
- System.arraycopy(listeners, 0, l, 0, nListeners);
- listeners = l;
- }
- }
}
/**
@@ -201,6 +189,7 @@ public abstract class DomNode
}
}
this.owner = owner;
+ this.listeners = new HashSet();
}
@@ -372,6 +361,16 @@ public abstract class DomNode
return;
}
break;
+ case DOCUMENT_TYPE_NODE:
+ if (!owner.building)
+ break;
+ switch (childNodeType)
+ {
+ case COMMENT_NODE:
+ case PROCESSING_INSTRUCTION_NODE:
+ return;
+ }
+ break;
}
if (owner.checkingWellformedness)
{
@@ -960,12 +959,6 @@ public abstract class DomNode
*/
public void trimToSize()
{
- if (listeners != null && listeners.length != nListeners)
- {
- ListenerRecord[] newKids = new ListenerRecord[length];
- System.arraycopy(listeners, 0, newKids, 0, nListeners);
- listeners = newKids;
- }
}
/**
@@ -1175,7 +1168,7 @@ public abstract class DomNode
node.next = null;
node.readonly = false;
- node.listeners = null;
+ node.listeners = new HashSet();
node.nListeners = 0;
return node;
@@ -1264,16 +1257,17 @@ public abstract class DomNode
elementName = name;
matchAnyURI = "*".equals(uri);
matchAnyName = "*".equals(name);
-
+
DomNode.this.addEventListener("DOMNodeInserted", this, true);
DomNode.this.addEventListener("DOMNodeRemoved", this, true);
}
void detach()
{
- current.detach();
+ if (current != null)
+ current.detach();
current = null;
-
+
DomNode.this.removeEventListener("DOMNodeInserted", this, true);
DomNode.this.removeEventListener("DOMNodeRemoved", this, true);
}
@@ -1336,6 +1330,8 @@ public abstract class DomNode
return;
}
+ if (current != null)
+ current.detach();
current = null;
}
@@ -1354,6 +1350,7 @@ public abstract class DomNode
lastIndex--;
}
Node ret = current.previousNode ();
+ current.detach();
current = null;
return ret;
}
@@ -1361,9 +1358,11 @@ public abstract class DomNode
// somewhere after last node
while (++lastIndex != index)
current.nextNode ();
- Node ret = current.nextNode ();
- current = null;
- return ret;
+
+ Node ret = current.nextNode ();
+ current.detach();
+ current = null;
+ return ret;
}
public int getLength()
@@ -1375,7 +1374,7 @@ public abstract class DomNode
{
retval++;
}
- current = null;
+ iter.detach();
return retval;
}
@@ -1403,13 +1402,18 @@ public abstract class DomNode
this.useCapture = useCapture;
}
- boolean equals(ListenerRecord rec)
+ public boolean equals(Object o)
{
+ ListenerRecord rec = (ListenerRecord)o;
return listener == rec.listener
&& useCapture == rec.useCapture
&& type == rec.type;
}
+ public int hashCode()
+ {
+ return listener.hashCode() ^ type.hashCode();
+ }
}
/**
@@ -1464,30 +1468,12 @@ public abstract class DomNode
EventListener listener,
boolean useCapture)
{
- if (listeners == null)
- {
- listeners = new ListenerRecord[1];
- }
- else if (nListeners == listeners.length)
- {
- ListenerRecord[] newListeners =
- new ListenerRecord[listeners.length + NKIDS_DELTA];
- System.arraycopy(listeners, 0, newListeners, 0, nListeners);
- listeners = newListeners;
- }
-
// prune duplicates
ListenerRecord record;
record = new ListenerRecord(type, listener, useCapture);
- for (int i = 0; i < nListeners; i++)
- {
- if (record.equals(listeners[i]))
- {
- return;
- }
- }
- listeners [nListeners++] = record;
+ listeners.add(record);
+ nListeners = listeners.size();
}
// XXX this exception should be discarded from DOM
@@ -1672,11 +1658,14 @@ public abstract class DomNode
ListenerRecord[] notificationSet)
{
int count = 0;
+ Iterator iter;
+
+ iter = current.listeners.iterator();
// do any of this set of listeners get notified?
- for (int i = 0; i < current.nListeners; i++)
+ while (iter.hasNext())
{
- ListenerRecord rec = current.listeners[i];
+ ListenerRecord rec = (ListenerRecord)iter.next();
if (rec.useCapture != capture)
{
@@ -1697,6 +1686,7 @@ public abstract class DomNode
}
notificationSet[count++] = rec;
}
+ iter = null;
// Notify just those listeners
e.currentNode = current;
@@ -1704,18 +1694,21 @@ public abstract class DomNode
{
try
{
+ iter = current.listeners.iterator();
// Late in the DOM CR process (3rd or 4th CR?) the
// removeEventListener spec became asymmetric with respect
// to addEventListener ... effect is now immediate.
- for (int j = 0; j < current.nListeners; j++)
+ while (iter.hasNext())
{
- if (current.listeners[j].equals(notificationSet[i]))
+ ListenerRecord rec = (ListenerRecord)iter.next();
+
+ if (rec.equals(notificationSet[i]))
{
notificationSet[i].listener.handleEvent(e);
break;
}
}
-
+ iter = null;
}
catch (Exception x)
{
@@ -1733,36 +1726,8 @@ public abstract class DomNode
EventListener listener,
boolean useCapture)
{
- for (int i = 0; i < nListeners; i++)
- {
- if (listeners[i].listener != listener)
- {
- continue;
- }
- if (listeners[i].useCapture != useCapture)
- {
- continue;
- }
- if (!listeners[i].type.equals(type))
- {
- continue;
- }
-
- if (nListeners == 1)
- {
- listeners = null;
- nListeners = 0;
- }
- else
- {
- for (int j = i + 1; j < nListeners; j++)
- {
- listeners[i++] = listeners[j++];
- }
- listeners[--nListeners] = null;
- }
- break;
- }
+ listeners.remove(new ListenerRecord(type, listener, useCapture));
+ nListeners = listeners.size();
// no exceptions reported
}
@@ -1779,10 +1744,15 @@ public abstract class DomNode
readonly = false;
for (DomNode ctx = first; ctx != null; ctx = ctx.next)
{
+ boolean saved2 = ctx.readonly;
+ ctx.readonly = false;
switch (ctx.nodeType)
{
case TEXT_NODE:
- while (ctx.next != null && ctx.next.nodeType == TEXT_NODE)
+ case CDATA_SECTION_NODE:
+ while (ctx.next != null &&
+ (ctx.next.nodeType == TEXT_NODE ||
+ ctx.next.nodeType == CDATA_SECTION_NODE))
{
Text text = (Text) ctx;
text.appendData(ctx.next.getNodeValue());
@@ -1794,7 +1764,11 @@ public abstract class DomNode
int len = attrs.getLength();
for (int i = 0; i < len; i++)
{
- attrs.item(i).normalize();
+ DomNode attr = (DomNode) attrs.item(i);
+ boolean saved3 = attr.readonly;
+ attr.readonly = false;
+ attr.normalize();
+ attr.readonly = saved3;
}
// Fall through
case DOCUMENT_NODE:
@@ -1804,6 +1778,7 @@ public abstract class DomNode
ctx.normalize();
break;
}
+ ctx.readonly = saved2;
}
readonly = saved;
}
@@ -2017,39 +1992,56 @@ public abstract class DomNode
public boolean isEqualNode(Node arg)
{
if (this == arg)
- {
- return true;
- }
+ return true;
if (arg == null)
+ return false;
+ if (nodeType != arg.getNodeType())
+ return false;
+ switch (nodeType)
{
- return false;
- }
- if (nodeType != arg.getNodeType() ||
- !equal(getNodeName(), arg.getNodeName()) ||
- !equal(getLocalName(), arg.getLocalName()) ||
- !equal(getNamespaceURI(), arg.getNamespaceURI()) ||
- !equal(getPrefix(), arg.getPrefix()) ||
- !equal(getNodeValue(), arg.getNodeValue()))
- {
- return false;
+ case ELEMENT_NODE:
+ case ATTRIBUTE_NODE:
+ if (!equal(getLocalName(), arg.getLocalName()) ||
+ !equal(getNamespaceURI(), arg.getNamespaceURI()))
+ return false;
+ break;
+ case PROCESSING_INSTRUCTION_NODE:
+ if (!equal(getNodeName(), arg.getNodeName()) ||
+ !equal(getNodeValue(), arg.getNodeValue()))
+ return false;
+ break;
+ case COMMENT_NODE:
+ case TEXT_NODE:
+ case CDATA_SECTION_NODE:
+ if (!equal(getNodeValue(), arg.getNodeValue()))
+ return false;
+ break;
}
// Children
Node argCtx = arg.getFirstChild();
getFirstChild(); // because of DomAttr lazy children
- for (DomNode ctx = first; ctx != null; ctx = ctx.next)
+ DomNode ctx = first;
+ for (; ctx != null && argCtx != null; ctx = ctx.next)
{
- if (!ctx.isEqualNode(argCtx))
+ if (nodeType == DOCUMENT_NODE)
{
- return false;
+ // Ignore whitespace outside document element
+ while (ctx != null && ctx.nodeType == TEXT_NODE)
+ ctx = ctx.next;
+ while (argCtx != null && ctx.getNodeType() == TEXT_NODE)
+ argCtx = argCtx.getNextSibling();
+ if (ctx == null && argCtx != null)
+ return false;
+ else if (argCtx == null && ctx != null)
+ return false;
}
+ if (!ctx.isEqualNode(argCtx))
+ return false;
argCtx = argCtx.getNextSibling();
}
- if (argCtx != null)
- {
- return false;
- }
+ if (ctx != null || argCtx != null)
+ return false;
- // TODO Attr NamedNodeMap
// TODO DocumentType
return true;
}
@@ -2185,5 +2177,14 @@ public abstract class DomNode
}
}
+ public void list(java.io.PrintStream out, int indent)
+ {
+ for (int i = 0; i < indent; i++)
+ out.print(" ");
+ out.println(toString());
+ for (DomNode ctx = first; ctx != null; ctx = ctx.next)
+ ctx.list(out, indent + 1);
+ }
+
}
diff --git a/libjava/classpath/gnu/xml/dom/ls/DomLSParser.java b/libjava/classpath/gnu/xml/dom/ls/DomLSParser.java
index eb7c1c49f3a..7ac4cc749fc 100644
--- a/libjava/classpath/gnu/xml/dom/ls/DomLSParser.java
+++ b/libjava/classpath/gnu/xml/dom/ls/DomLSParser.java
@@ -260,6 +260,7 @@ public class DomLSParser
eventSink.coalescing = coalescing;
// get and configure reader
XMLReader reader = getXMLReader();
+ eventSink.reader = reader;
try
{
reader.setContentHandler(eventSink);
diff --git a/libjava/classpath/gnu/xml/dom/ls/SAXEventSink.java b/libjava/classpath/gnu/xml/dom/ls/SAXEventSink.java
index a850460b1e2..aad5ac76e70 100644
--- a/libjava/classpath/gnu/xml/dom/ls/SAXEventSink.java
+++ b/libjava/classpath/gnu/xml/dom/ls/SAXEventSink.java
@@ -37,6 +37,7 @@ exception statement from your version. */
package gnu.xml.dom.ls;
+import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
@@ -45,20 +46,26 @@ import org.w3c.dom.Attr;
import org.w3c.dom.DocumentType;
import org.w3c.dom.Element;
import org.w3c.dom.Entity;
+import org.w3c.dom.EntityReference;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.Text;
import org.xml.sax.Attributes;
+import org.xml.sax.ContentHandler;
import org.xml.sax.DTDHandler;
import org.xml.sax.Locator;
import org.xml.sax.SAXException;
+import org.xml.sax.SAXNotRecognizedException;
+import org.xml.sax.SAXNotSupportedException;
+import org.xml.sax.XMLReader;
import org.xml.sax.ext.Attributes2;
import org.xml.sax.ext.DeclHandler;
import org.xml.sax.ext.LexicalHandler;
-import gnu.xml.aelfred2.ContentHandler2;
+import org.xml.sax.ext.Locator2;
import gnu.xml.dom.DomAttr;
import gnu.xml.dom.DomDocument;
import gnu.xml.dom.DomDoctype;
+import gnu.xml.dom.DomNode;
/**
* A SAX content and lexical handler used to construct a DOM document.
@@ -66,17 +73,28 @@ import gnu.xml.dom.DomDoctype;
* @author Chris Burdess
*/
class SAXEventSink
- implements ContentHandler2, LexicalHandler, DTDHandler, DeclHandler
+ implements ContentHandler, LexicalHandler, DTDHandler, DeclHandler
{
private static final String XMLNS_URI = XMLConstants.XMLNS_ATTRIBUTE_NS_URI;
private static final String XMLNS_PREFIX = XMLConstants.XMLNS_ATTRIBUTE;
+ private static final HashSet PREDEFINED_ENTITIES = new HashSet();
+ static
+ {
+ PREDEFINED_ENTITIES.add("amp");
+ PREDEFINED_ENTITIES.add("lt");
+ PREDEFINED_ENTITIES.add("gt");
+ PREDEFINED_ENTITIES.add("quot");
+ PREDEFINED_ENTITIES.add("apos");
+ }
boolean namespaceAware;
boolean ignoreWhitespace;
boolean expandEntityReferences;
boolean ignoreComments;
boolean coalescing;
+
+ XMLReader reader; // reference back to the parser to get features
DomDocument doc; // document being constructed
Node ctx; // current context (parent node)
@@ -110,20 +128,42 @@ class SAXEventSink
doc.setStrictErrorChecking(false);
doc.setBuilding(true);
ctx = doc;
- }
- public void xmlDecl(String version, String encoding, boolean standalone,
- String inputEncoding)
- throws SAXException
- {
- if (interrupted)
+ final String FEATURES = "http://xml.org/sax/features/";
+ final String PROPERTIES = "http://xml.org/sax/properties/";
+ final String GNU_PROPERTIES = "http://gnu.org/sax/properties/";
+
+ boolean standalone = reader.getFeature(FEATURES + "is-standalone");
+ doc.setXmlStandalone(standalone);
+ try
+ {
+ String version = (String) reader.getProperty(PROPERTIES +
+ "document-xml-version");
+ doc.setXmlVersion(version);
+ }
+ catch (SAXNotRecognizedException e)
+ {
+ }
+ catch (SAXNotSupportedException e)
+ {
+ }
+ if (locator != null && locator instanceof Locator2)
+ {
+ String encoding = ((Locator2) locator).getEncoding();
+ doc.setInputEncoding(encoding);
+ }
+ try
+ {
+ String encoding = (String) reader.getProperty(GNU_PROPERTIES +
+ "document-xml-encoding");
+ doc.setXmlEncoding(encoding);
+ }
+ catch (SAXNotRecognizedException e)
+ {
+ }
+ catch (SAXNotSupportedException e)
{
- return;
}
- doc.setXmlVersion(version);
- doc.setXmlEncoding(encoding);
- doc.setXmlStandalone(standalone);
- doc.setInputEncoding(inputEncoding);
}
public void endDocument()
@@ -265,7 +305,7 @@ class SAXEventSink
public void characters(char[] c, int off, int len)
throws SAXException
{
- if (interrupted)
+ if (interrupted || len < 1)
{
return;
}
@@ -301,11 +341,8 @@ class SAXEventSink
{
return;
}
- if (!inDTD)
- {
- Node pi = createProcessingInstruction(target, data);
- ctx.appendChild(pi);
- }
+ Node pi = createProcessingInstruction(target, data);
+ ctx.appendChild(pi);
}
protected Node createProcessingInstruction(String target, String data)
@@ -354,6 +391,8 @@ class SAXEventSink
public void startEntity(String name)
throws SAXException
{
+ if (interrupted)
+ return;
DocumentType doctype = doc.getDoctype();
if (doctype == null)
{
@@ -361,19 +400,9 @@ class SAXEventSink
"reference to entity in undeclared doctype");
}
if ("[dtd]".equals(name) || name.charAt(0) == '%')
- {
- // Ignore DTD and parameter entities
- ctx = doctype;
- return;
- }
- if ("lt".equals(name) ||
- "gt".equals(name) ||
- "amp".equals(name) ||
- "apos".equals(name) ||
- "quot".equals(name))
- {
- return;
- }
+ return;
+ if (PREDEFINED_ENTITIES.contains(name))
+ return;
// Get entity
NamedNodeMap entities = doctype.getEntities();
Entity entity = (Entity) entities.getNamedItem(name);
@@ -382,59 +411,47 @@ class SAXEventSink
throw new SAXException("SAX parser error: " +
"reference to undeclared entity: " + name);
}
- pushEntity(entity);
+ EntityReference ref = doc.createEntityReference(name);
+ // DomDocument populates with the entity replacement text, remove this
+ Node child = ref.getFirstChild();
+ while (child != null)
+ {
+ Node nextChild = child.getNextSibling();
+ ref.removeChild(child);
+ child = nextChild;
+ }
+ ctx.appendChild(ref);
+ ctx = ref;
}
public void endEntity(String name)
throws SAXException
{
+ if (interrupted)
+ return;
if ("[dtd]".equals(name) || name.charAt(0) == '%')
- {
- // Ignore DTD and parameter entities
- return;
- }
- if ("lt".equals(name) ||
- "gt".equals(name) ||
- "amp".equals(name) ||
- "apos".equals(name) ||
- "quot".equals(name))
- {
- return;
- }
- // Get entity
- Entity entity = popEntity();
- // TODO resolve external entities to ensure that entity has content
+ return;
+ if (PREDEFINED_ENTITIES.contains(name))
+ return;
+ // Get entity reference
+ EntityReference ref = (EntityReference) ctx;
+ if (!ref.getNodeName().equals(name))
+ throw new SAXException("expecting end of "+ref.getNodeName()+" entity");
+ ctx = ctx.getParentNode();
+ if (ref instanceof DomNode)
+ ((DomNode) ref).makeReadonly();
if (expandEntityReferences)
{
- // Get entity content
- for (Node child = entity.getFirstChild(); child != null;
- child = child.getNextSibling())
+ // Move entity content from reference node onto context
+ Node child = ref.getFirstChild();
+ while (child != null)
{
+ Node nextChild = child.getNextSibling();
ctx.appendChild(child);
+ child = nextChild;
}
+ ctx.removeChild(ref);
}
- else
- {
- Node entityReference = doc.createEntityReference(name);
- ctx.appendChild(entityReference);
- }
- }
-
- void pushEntity(Node entity)
- {
- if (entityCtx == null)
- {
- entityCtx = new LinkedList();
- }
- entityCtx.addLast(ctx);
- ctx = entity;
- }
-
- Entity popEntity()
- {
- Entity ret = (Entity) ctx;
- ctx = (Node) entityCtx.removeLast();
- return ret;
}
public void startCDATA()
@@ -456,11 +473,8 @@ class SAXEventSink
{
return;
}
- if (!inDTD)
- {
- Node comment = createComment(c, off, len);
- ctx.appendChild(comment);
- }
+ Node comment = createComment(c, off, len);
+ ctx.appendChild(comment);
}
protected Node createComment(char[] c, int off, int len)
@@ -477,6 +491,8 @@ class SAXEventSink
{
return;
}
+ if (!inDTD)
+ throw new SAXException("notation decl outside DTD");
DomDoctype doctype = (DomDoctype) ctx;
doctype.declareNotation(name, publicId, systemId);
}
@@ -489,6 +505,8 @@ class SAXEventSink
{
return;
}
+ if (!inDTD)
+ throw new SAXException("unparsed entity decl outside DTD");
DomDoctype doctype = (DomDoctype) ctx;
Entity entity = doctype.declareEntity(name, publicId, systemId,
notationName);
@@ -503,6 +521,8 @@ class SAXEventSink
{
return;
}
+ if (!inDTD)
+ throw new SAXException("element decl outside DTD");
// Ignore fake element declarations generated by ValidationConsumer.
// If an element is not really declared in the DTD it will not be
// declared in the document model.
@@ -522,6 +542,8 @@ class SAXEventSink
{
return;
}
+ if (!inDTD)
+ throw new SAXException("attribute decl outside DTD");
DomDoctype doctype = (DomDoctype) ctx;
doctype.attributeDecl(eName, aName, type, mode, value);
}
@@ -533,6 +555,8 @@ class SAXEventSink
{
return;
}
+ if (!inDTD)
+ throw new SAXException("internal entity decl outside DTD");
DomDoctype doctype = (DomDoctype) ctx;
Entity entity = doctype.declareEntity(name, null, null, null);
if (entity != null)
@@ -549,6 +573,8 @@ class SAXEventSink
{
return;
}
+ if (!inDTD)
+ throw new SAXException("external entity decl outside DTD");
DomDoctype doctype = (DomDoctype) ctx;
Entity entity = doctype.declareEntity(name, publicId, systemId, null);
}
diff --git a/libjava/classpath/gnu/xml/pipeline/DomConsumer.java b/libjava/classpath/gnu/xml/pipeline/DomConsumer.java
index 389e02bb387..bdbf9281880 100644
--- a/libjava/classpath/gnu/xml/pipeline/DomConsumer.java
+++ b/libjava/classpath/gnu/xml/pipeline/DomConsumer.java
@@ -37,7 +37,6 @@ exception statement from your version. */
package gnu.xml.pipeline;
-import gnu.xml.aelfred2.ContentHandler2;
import gnu.xml.util.DomParser;
import org.xml.sax.Attributes;
@@ -330,7 +329,7 @@ public class DomConsumer implements EventConsumer
* accepted illegal input data).
*/
public static class Handler
- implements ContentHandler2, LexicalHandler,
+ implements ContentHandler, LexicalHandler,
DTDHandler, DeclHandler
{
protected DomConsumer consumer;
@@ -430,20 +429,6 @@ public class DomConsumer implements EventConsumer
top = document;
}
- // ContentHandler2
- public void xmlDecl(String version,
- String encoding,
- boolean standalone,
- String inputEncoding)
- throws SAXException
- {
- if (document != null)
- {
- document.setXmlVersion(version);
- document.setXmlStandalone(standalone);
- }
- }
-
// SAX1
public void endDocument ()
throws SAXException
diff --git a/libjava/classpath/gnu/xml/pipeline/EventFilter.java b/libjava/classpath/gnu/xml/pipeline/EventFilter.java
index 6600271718a..a14fb340f12 100644
--- a/libjava/classpath/gnu/xml/pipeline/EventFilter.java
+++ b/libjava/classpath/gnu/xml/pipeline/EventFilter.java
@@ -44,8 +44,6 @@ import org.xml.sax.*;
import org.xml.sax.ext.*;
import org.xml.sax.helpers.XMLFilterImpl;
-import gnu.xml.aelfred2.ContentHandler2;
-
/**
* A customizable event consumer, used to assemble various kinds of filters
* using SAX handlers and an optional second consumer. It can be constructed
@@ -138,7 +136,7 @@ import gnu.xml.aelfred2.ContentHandler2;
* @author David Brownell
*/
public class EventFilter
- implements EventConsumer, ContentHandler2, DTDHandler,
+ implements EventConsumer, ContentHandler, DTDHandler,
LexicalHandler, DeclHandler
{
// SAX handlers
@@ -600,17 +598,6 @@ public class EventFilter
docNext.startDocument ();
}
- public void xmlDecl(String version, String encoding, boolean standalone,
- String inputEncoding)
- throws SAXException
- {
- if (docNext != null && docNext instanceof ContentHandler2)
- {
- ((ContentHandler2) docNext).xmlDecl(version, encoding, standalone,
- inputEncoding);
- }
- }
-
/** SAX2: passes this callback to the next consumer, if any */
public void skippedEntity (String name) throws SAXException
{
diff --git a/libjava/classpath/gnu/xml/stream/BufferedReader.java b/libjava/classpath/gnu/xml/stream/BufferedReader.java
new file mode 100644
index 00000000000..f8287e823fd
--- /dev/null
+++ b/libjava/classpath/gnu/xml/stream/BufferedReader.java
@@ -0,0 +1,198 @@
+/* BufferedReader.java --
+ Copyright (C) 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.xml.stream;
+
+import java.io.IOException;
+import java.io.Reader;
+
+/**
+ * A mark-capable buffered reader.
+ *
+ * @author Chris Burdess
+ */
+class BufferedReader
+ extends Reader
+{
+
+ static final int DEFAULT_BUFFER_SIZE = 4096;
+
+ final Reader in;
+ char[] buf;
+ int pos, count, markpos, marklimit, bufferSize;
+
+ BufferedReader(Reader in)
+ {
+ this(in, DEFAULT_BUFFER_SIZE);
+ }
+
+ BufferedReader(Reader in, int bufferSize)
+ {
+ if (bufferSize < 1)
+ throw new IllegalArgumentException();
+ this.in = in;
+ this.bufferSize = bufferSize;
+ buf = new char[bufferSize];
+ pos = count = bufferSize;
+ }
+
+ public void close()
+ throws IOException
+ {
+ buf = null;
+ pos = count = 0;
+ markpos = -1;
+ in.close();
+ }
+
+ public void mark(int readlimit)
+ throws IOException
+ {
+ marklimit = readlimit;
+ markpos = pos;
+ }
+
+ public boolean markSupported()
+ {
+ return true;
+ }
+
+ public int read()
+ throws IOException
+ {
+ if (pos >= count && !refill())
+ return -1;
+ return (int) buf[pos++];
+ }
+
+ public int read(char[] b)
+ throws IOException
+ {
+ return read(b, 0, b.length);
+ }
+
+ public int read(char[] b, int off, int len)
+ throws IOException
+ {
+ if (off < 0 || len < 0 || b.length - off < len)
+ throw new IndexOutOfBoundsException();
+
+ if (len == 0)
+ return 0;
+
+ if (pos >= count && !refill())
+ return -1;
+
+ int ret = Math.min(count - pos, len);
+ System.arraycopy(buf, pos, b, off, ret);
+ pos += ret;
+ off += ret;
+ len -= ret;
+
+ while (len > 0 && refill())
+ {
+ int remain = Math.min(count - pos, len);
+ System.arraycopy(buf, pos, b, off, remain);
+ pos += remain;
+ off += remain;
+ len -= remain;
+ ret += remain;
+ }
+
+ return ret;
+ }
+
+ public void reset()
+ throws IOException
+ {
+ if (markpos == -1)
+ throw new IOException(buf == null ? "Stream closed." : "Invalid mark.");
+ pos = markpos;
+ }
+
+ public long skip(long n)
+ throws IOException
+ {
+ if (buf == null)
+ throw new IOException("Stream closed.");
+ final long origN = n;
+ while (n > 0L)
+ {
+ if (pos >= count && !refill())
+ break;
+ int numread = (int) Math.min((long) (count - pos), n);
+ pos += numread;
+ n -= numread;
+ }
+ return origN - n;
+ }
+
+ private boolean refill()
+ throws IOException
+ {
+ if (buf == null)
+ throw new IOException("Stream closed.");
+
+ int markcount = count - markpos;
+ if (markpos == -1 || markcount >= marklimit)
+ {
+ markpos = -1;
+ pos = count = 0;
+ }
+ else
+ {
+ char[] newbuf = buf;
+ if (markpos < bufferSize)
+ {
+ newbuf = new char[count - markpos + bufferSize];
+ }
+ System.arraycopy(buf, markpos, newbuf, 0, markcount);
+ buf = newbuf;
+ count = markcount;
+ pos -= markpos;
+ markpos = 0;
+ }
+
+ int numread = in.read(buf, count, bufferSize);
+ if (numread <= 0)
+ return false;
+
+ count += numread;
+ return true;
+ }
+
+}
diff --git a/libjava/classpath/gnu/xml/stream/CRLFReader.java b/libjava/classpath/gnu/xml/stream/CRLFReader.java
new file mode 100644
index 00000000000..1d214ce52c1
--- /dev/null
+++ b/libjava/classpath/gnu/xml/stream/CRLFReader.java
@@ -0,0 +1,180 @@
+/* CRLFReader.java --
+ Copyright (C) 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.xml.stream;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.Reader;
+
+/**
+ * Filtered reader that normalizes CRLF pairs into LFs.
+ *
+ * @author Chris Burdess
+ */
+class CRLFReader
+ extends Reader
+{
+
+ /**
+ * The CR octet.
+ */
+ public static final int CR = 13;
+
+ /**
+ * The LF octet.
+ */
+ public static final int LF = 10;
+
+ private boolean doReset;
+
+ protected Reader in;
+
+ /**
+ * Constructor.
+ */
+ protected CRLFReader(Reader in)
+ {
+ if (!in.markSupported())
+ in = new BufferedReader(in);
+ this.in = in;
+ }
+
+ public int read()
+ throws IOException
+ {
+ int c = in.read();
+ if (c == 13) // CR
+ {
+ in.mark(1);
+ int d = in.read();
+ if (d == 10) // LF
+ c = d;
+ else
+ in.reset();
+ }
+ return c;
+ }
+
+ public int read(char[] b)
+ throws IOException
+ {
+ return read(b, 0, b.length);
+ }
+
+ public int read(char[] b, int off, int len)
+ throws IOException
+ {
+ in.mark(len + 1);
+ int l = in.read(b, off, len);
+ if (l > 0)
+ {
+ int i = indexOfCRLF(b, off, l);
+ if (doReset)
+ {
+ in.reset();
+ if (i != -1)
+ {
+ l = in.read(b, off, (i + 1) - off); // read to CR
+ in.read(); // skip LF
+ b[i] = '\n'; // fix CR as LF
+ }
+ else
+ l = in.read(b, off, len); // CR(s) but no LF
+ }
+ }
+ return l;
+ }
+
+ public boolean markSupported()
+ {
+ return in.markSupported();
+ }
+
+ public void mark(int limit)
+ throws IOException
+ {
+ in.mark(limit);
+ }
+
+ public void reset()
+ throws IOException
+ {
+ in.reset();
+ }
+
+ public long skip(long n)
+ throws IOException
+ {
+ return in.skip(n);
+ }
+
+ public void close()
+ throws IOException
+ {
+ in.close();
+ }
+
+ private int indexOfCRLF(char[] b, int off, int len)
+ throws IOException
+ {
+ doReset = false;
+ int lm1 = len - 1;
+ for (int i = off; i < len; i++)
+ {
+ if (b[i] == '\r') // CR
+ {
+ int d;
+ if (i == lm1)
+ {
+ d = in.read();
+ doReset = true;
+ }
+ else
+ d = b[i + 1];
+ if (d == '\n') // LF
+ {
+ doReset = true;
+ return i;
+ }
+ }
+ }
+ return -1;
+ }
+
+}
+
diff --git a/libjava/classpath/gnu/xml/stream/SAXParser.java b/libjava/classpath/gnu/xml/stream/SAXParser.java
new file mode 100644
index 00000000000..54c8b36244b
--- /dev/null
+++ b/libjava/classpath/gnu/xml/stream/SAXParser.java
@@ -0,0 +1,966 @@
+/* SAXParser.java --
+ Copyright (C) 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.xml.stream;
+
+import java.io.InputStream;
+import java.io.IOException;
+import java.io.Reader;
+import java.net.URL;
+import java.util.Iterator;
+import java.util.Map;
+import javax.xml.XMLConstants;
+import javax.xml.namespace.QName;
+import javax.xml.stream.Location;
+import javax.xml.stream.XMLEventReader;
+import javax.xml.stream.XMLReporter;
+import javax.xml.stream.XMLResolver;
+import javax.xml.stream.XMLStreamConstants;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+
+import org.xml.sax.ContentHandler;
+import org.xml.sax.DTDHandler;
+import org.xml.sax.EntityResolver;
+import org.xml.sax.ErrorHandler;
+import org.xml.sax.InputSource;
+import org.xml.sax.Parser;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXNotRecognizedException;
+import org.xml.sax.SAXNotSupportedException;
+import org.xml.sax.SAXParseException;
+import org.xml.sax.XMLReader;
+import org.xml.sax.ext.Attributes2;
+import org.xml.sax.ext.DeclHandler;
+import org.xml.sax.ext.EntityResolver2;
+import org.xml.sax.ext.LexicalHandler;
+import org.xml.sax.ext.Locator2;
+
+/**
+ * JAXP SAX parser using an underlying StAX parser.
+ * This parser supports the following additional SAX features and
+ * properties:
+ *
+ * Features
+ * http://gnu.org/sax/features/xml-base
+ * read/write
+ * Indicates or sets whether XML Base processing is enabled
+ * Properties
+ * http://gnu.org/sax/properties/base-uri
+ * read-only String
+ * Returns the base URI of the current event
+ * http://gnu.org/sax/properties/document-xml-encoding
+ * read-only String
+ * Returns the encoding specified in the XML declaration
+ *
+ *
+ * @author Chris Burdess
+ */
+public class SAXParser
+ extends javax.xml.parsers.SAXParser
+ implements XMLReader, Attributes2, Locator2, XMLReporter,
+ XMLParser.XMLResolver2
+{
+
+ ContentHandler contentHandler;
+ DeclHandler declHandler;
+ DTDHandler dtdHandler;
+ EntityResolver entityResolver;
+ ErrorHandler errorHandler;
+ LexicalHandler lexicalHandler;
+
+ boolean validating = false;
+ boolean namespaceAware = true;
+ boolean xIncludeAware = false;
+ boolean stringInterning = true;
+ boolean coalescing = true;
+ boolean replaceERefs = true;
+ boolean externalEntities = true;
+ boolean supportDTD = true;
+ boolean baseAware = true;
+
+ XMLParser parser;
+ XMLStreamReader reader;
+ String encoding;
+ String xmlVersion;
+ boolean xmlStandalone;
+ String xmlEncoding;
+ String baseURI;
+
+ public SAXParser()
+ {
+ }
+
+ SAXParser(boolean validating, boolean namespaceAware, boolean xIncludeAware)
+ {
+ this.validating = validating;
+ this.namespaceAware = namespaceAware;
+ this.xIncludeAware = xIncludeAware;
+ }
+
+ // -- SAXParser --
+
+ public Parser getParser()
+ throws SAXException
+ {
+ return null;
+ }
+
+ public XMLReader getXMLReader()
+ throws SAXException
+ {
+ return this;
+ }
+
+ public boolean isNamespaceAware()
+ {
+ return namespaceAware;
+ }
+
+ public boolean isValidating()
+ {
+ return validating;
+ }
+
+ public void setProperty(String name, Object value)
+ throws SAXNotRecognizedException, SAXNotSupportedException
+ {
+ if (parser != null)
+ throw new IllegalStateException("parsing in progress");
+ final String FEATURES = "http://xml.org/sax/features/";
+ final String PROPERTIES = "http://xml.org/sax/properties/";
+ final String GNU_FEATURES = "http://gnu.org/sax/features/";
+ if ((FEATURES + "namespaces").equals(name))
+ namespaceAware = Boolean.TRUE.equals(value);
+ else if ((FEATURES + "namespace-prefixes").equals(name))
+ {
+ // NOOP
+ }
+ else if ((FEATURES + "string-interning").equals(name))
+ stringInterning = Boolean.TRUE.equals(value);
+ else if ((FEATURES + "use-attributes2").equals(name))
+ {
+ // NOOP
+ }
+ else if ((FEATURES + "validation").equals(name))
+ validating = Boolean.TRUE.equals(value);
+ else if ((FEATURES + "external-general-entities").equals(name))
+ externalEntities = Boolean.TRUE.equals(value);
+ else if ((FEATURES + "external-parameter-entities").equals(name))
+ externalEntities = Boolean.TRUE.equals(value);
+ else if ((PROPERTIES + "declaration-handler").equals(name))
+ declHandler = (DeclHandler) value;
+ else if ((PROPERTIES + "lexical-handler").equals(name))
+ lexicalHandler = (LexicalHandler) value;
+ else if ((GNU_FEATURES + "xml-base").equals(name))
+ baseAware = Boolean.TRUE.equals(value);
+ else
+ throw new SAXNotSupportedException(name);
+ }
+
+ public Object getProperty(String name)
+ throws SAXNotRecognizedException, SAXNotSupportedException
+ {
+ final String FEATURES = "http://xml.org/sax/features/";
+ final String PROPERTIES = "http://xml.org/sax/properties/";
+ final String GNU_FEATURES = "http://gnu.org/sax/features/";
+ final String GNU_PROPERTIES = "http://gnu.org/sax/properties/";
+ if ((GNU_FEATURES + "base-uri").equals(name))
+ return baseURI;
+ if ((FEATURES + "is-standalone").equals(name))
+ return xmlStandalone ? Boolean.TRUE : Boolean.FALSE;
+ if ((FEATURES + "namespaces").equals(name))
+ return namespaceAware ? Boolean.TRUE : Boolean.FALSE;
+ if ((FEATURES + "namespace-prefixes").equals(name))
+ return Boolean.TRUE;
+ if ((FEATURES + "string-interning").equals(name))
+ return stringInterning ? Boolean.TRUE : Boolean.FALSE;
+ if ((FEATURES + "use-attributes2").equals(name))
+ return Boolean.TRUE;
+ if ((FEATURES + "use-locator2").equals(name))
+ return Boolean.TRUE;
+ if ((FEATURES + "use-entity-resolver2").equals(name))
+ return Boolean.FALSE;
+ if ((FEATURES + "validation").equals(name))
+ return validating ? Boolean.TRUE : Boolean.FALSE;
+ if ((FEATURES + "external-general-entities").equals(name))
+ return externalEntities ? Boolean.TRUE : Boolean.FALSE;
+ if ((FEATURES + "external-parameter-entities").equals(name))
+ return externalEntities ? Boolean.TRUE : Boolean.FALSE;
+ if ((FEATURES + "xml-1.1").equals(name))
+ return Boolean.TRUE;
+ if ((PROPERTIES + "declaration-handler").equals(name))
+ return declHandler;
+ if ((PROPERTIES + "document-xml-version").equals(name))
+ return xmlVersion;
+ if ((PROPERTIES + "lexical-handler").equals(name))
+ return lexicalHandler;
+ if ((GNU_FEATURES + "xml-base").equals(name))
+ return baseAware ? Boolean.TRUE : Boolean.FALSE;
+ if ((GNU_PROPERTIES + "document-xml-encoding").equals(name))
+ return xmlEncoding;
+ throw new SAXNotSupportedException(name);
+ }
+
+ public boolean isXIncludeAware()
+ {
+ return xIncludeAware;
+ }
+
+ public void reset()
+ {
+ parser = null;
+ encoding = null;
+ xmlVersion = null;
+ xmlStandalone = false;
+ }
+
+ // -- XMLReader --
+
+ public boolean getFeature(String name)
+ throws SAXNotRecognizedException, SAXNotSupportedException
+ {
+ Object ret = getProperty(name);
+ if (ret instanceof Boolean)
+ return ((Boolean) ret).booleanValue();
+ throw new SAXNotSupportedException(name);
+ }
+
+ public void setFeature(String name, boolean value)
+ throws SAXNotRecognizedException, SAXNotSupportedException
+ {
+ setProperty(name, value ? Boolean.TRUE : Boolean.FALSE);
+ }
+
+ public void setEntityResolver(EntityResolver resolver)
+ {
+ entityResolver = resolver;
+ }
+
+ public EntityResolver getEntityResolver()
+ {
+ return entityResolver;
+ }
+
+ public void setDTDHandler(DTDHandler handler)
+ {
+ dtdHandler = handler;
+ }
+
+ public DTDHandler getDTDHandler()
+ {
+ return dtdHandler;
+ }
+
+ public void setContentHandler(ContentHandler handler)
+ {
+ contentHandler = handler;
+ }
+
+ public ContentHandler getContentHandler()
+ {
+ return contentHandler;
+ }
+
+ public void setErrorHandler(ErrorHandler handler)
+ {
+ errorHandler = handler;
+ }
+
+ public ErrorHandler getErrorHandler()
+ {
+ return errorHandler;
+ }
+
+ public synchronized void parse(InputSource input)
+ throws IOException, SAXException
+ {
+ reset();
+ String systemId = input.getSystemId();
+ InputStream in = input.getByteStream();
+ boolean opened = false;
+ if (in != null)
+ parser = new XMLParser(in, systemId,
+ validating,
+ namespaceAware,
+ coalescing,
+ replaceERefs,
+ externalEntities,
+ supportDTD,
+ baseAware,
+ stringInterning,
+ this,
+ this);
+ else
+ {
+ Reader r = input.getCharacterStream();
+ if (r != null)
+ parser = new XMLParser(r, systemId,
+ validating,
+ namespaceAware,
+ coalescing,
+ replaceERefs,
+ externalEntities,
+ supportDTD,
+ baseAware,
+ stringInterning,
+ this,
+ this);
+ }
+ if (parser == null)
+ {
+ if (systemId == null)
+ throw new SAXException("No stream or system ID specified");
+ systemId = XMLParser.absolutize(null, systemId);
+ in = new URL(systemId).openStream();
+ opened = true;
+ parser = new XMLParser(in, systemId,
+ validating,
+ namespaceAware,
+ coalescing,
+ replaceERefs,
+ externalEntities,
+ supportDTD,
+ baseAware,
+ stringInterning,
+ this,
+ this);
+ }
+ reader = parser;
+ baseURI = systemId;
+
+ if (xIncludeAware)
+ reader = new XIncludeFilter(parser, systemId, namespaceAware,
+ validating, true);
+
+ if (contentHandler != null)
+ contentHandler.setDocumentLocator(this);
+ boolean startDocumentDone = false;
+ try
+ {
+ while (parser.hasNext())
+ {
+ int event = parser.next();
+ if (baseAware)
+ baseURI = parser.getXMLBase();
+ switch (event)
+ {
+ case XMLStreamConstants.CHARACTERS:
+ if (contentHandler != null)
+ {
+ char[] b = reader.getTextCharacters();
+ contentHandler.characters(b, 0, b.length);
+ }
+ break;
+ case XMLStreamConstants.SPACE:
+ if (contentHandler != null)
+ {
+ char[] b = reader.getTextCharacters();
+ if (isIgnorableWhitespace(parser, b, false))
+ contentHandler.ignorableWhitespace(b, 0, b.length);
+ else
+ contentHandler.characters(b, 0, b.length);
+ }
+ break;
+ case XMLStreamConstants.CDATA:
+ if (lexicalHandler != null)
+ lexicalHandler.startCDATA();
+ if (contentHandler != null)
+ {
+ char[] b = reader.getTextCharacters();
+ if (isIgnorableWhitespace(parser, b, true))
+ contentHandler.ignorableWhitespace(b, 0, b.length);
+ else
+ contentHandler.characters(b, 0, b.length);
+ }
+ if (lexicalHandler != null)
+ lexicalHandler.endCDATA();
+ break;
+ case XMLStreamConstants.START_ELEMENT:
+ if (contentHandler != null)
+ {
+ QName name = reader.getName();
+ String uri = name.getNamespaceURI();
+ String localName = name.getLocalPart();
+ String prefix = name.getPrefix();
+ String qName = localName;
+ if (!"".equals(prefix))
+ qName = prefix + ":" + localName;
+ if (!namespaceAware)
+ {
+ uri = "";
+ localName = "";
+ }
+ else
+ {
+ int nc = reader.getNamespaceCount();
+ for (int i = 0; i < nc; i++)
+ {
+ String nsuri = reader.getNamespaceURI(i);
+ String nsprefix = reader.getNamespacePrefix(i);
+ if ("xml".equals(nsprefix))
+ continue;
+ contentHandler.startPrefixMapping(nsprefix, nsuri);
+ }
+ }
+ contentHandler.startElement(uri, localName, qName, this);
+ }
+ break;
+ case XMLStreamConstants.END_ELEMENT:
+ if (contentHandler != null)
+ {
+ QName name = reader.getName();
+ String uri = name.getNamespaceURI();
+ String localName = name.getLocalPart();
+ String prefix = name.getPrefix();
+ String qName = localName;
+ if (!"".equals(prefix))
+ qName = prefix + ":" + localName;
+ if (!namespaceAware)
+ {
+ uri = "";
+ localName = "";
+ }
+ contentHandler.endElement(uri, localName, qName);
+ if (namespaceAware)
+ {
+ int nc = reader.getNamespaceCount();
+ for (int i = 0; i < nc; i++)
+ {
+ String nsprefix = reader.getNamespacePrefix(i);
+ if ("xml".equals(nsprefix))
+ continue;
+ contentHandler.endPrefixMapping(nsprefix);
+ }
+ }
+ }
+ break;
+ case XMLStreamConstants.COMMENT:
+ if (lexicalHandler != null)
+ {
+ char[] b = reader.getTextCharacters();
+ lexicalHandler.comment(b, 0, b.length);
+ }
+ break;
+ case XMLStreamConstants.PROCESSING_INSTRUCTION:
+ if (contentHandler != null)
+ {
+ String target = reader.getPITarget();
+ String data = reader.getPIData();
+ if (data == null)
+ data = "";
+ contentHandler.processingInstruction(target, data);
+ }
+ break;
+ case XMLStreamConstants.START_ENTITY:
+ if (lexicalHandler != null)
+ {
+ String name = reader.getText();
+ lexicalHandler.startEntity(name);
+ }
+ break;
+ case XMLStreamConstants.END_ENTITY:
+ if (lexicalHandler != null)
+ {
+ String name = reader.getText();
+ lexicalHandler.endEntity(name);
+ }
+ break;
+ case XMLStreamConstants.START_DOCUMENT:
+ encoding = reader.getEncoding();
+ xmlVersion = reader.getVersion();
+ xmlStandalone = reader.isStandalone();
+ xmlEncoding = reader.getCharacterEncodingScheme();
+ if (contentHandler != null)
+ contentHandler.startDocument();
+ startDocumentDone = true;
+ break;
+ case XMLStreamConstants.END_DOCUMENT:
+ if (contentHandler != null)
+ contentHandler.endDocument();
+ break;
+ case XMLStreamConstants.DTD:
+ XMLParser.Doctype doctype = parser.doctype;
+ if (lexicalHandler != null)
+ {
+ String rootName = doctype.rootName;
+ String publicId = doctype.publicId;
+ String systemId2 = doctype.systemId;
+ lexicalHandler.startDTD(rootName, publicId, systemId2);
+ }
+ for (Iterator i = doctype.entryIterator(); i.hasNext(); )
+ {
+ String entry = (String) i.next();
+ char c = entry.charAt(0);
+ String name = entry.substring(1);
+ if ('E' == c)
+ {
+ // Element decl
+ if (declHandler != null)
+ {
+ XMLParser.ContentModel model =
+ doctype.getElementModel(name);
+ declHandler.elementDecl(name, model.text);
+ }
+ }
+ else if ('A' == c)
+ {
+ // Attlist decl
+ if (declHandler != null)
+ {
+ for (Iterator j = doctype.attlistIterator(name);
+ j.hasNext(); )
+ {
+ Map.Entry att = (Map.Entry) j.next();
+ String aname = (String) att.getKey();
+ XMLParser.AttributeDecl decl =
+ (XMLParser.AttributeDecl) att.getValue();
+ String type = decl.type;
+ String value = decl.value;
+ String mode = null;
+ switch (decl.valueType)
+ {
+ case XMLParser.ATTRIBUTE_DEFAULT_FIXED:
+ mode = "#FIXED";
+ break;
+ case XMLParser.ATTRIBUTE_DEFAULT_REQUIRED:
+ mode = "#REQUIRED";
+ break;
+ case XMLParser.ATTRIBUTE_DEFAULT_IMPLIED:
+ mode = "#IMPLIED";
+ break;
+ }
+ declHandler.attributeDecl(name, aname,
+ type, mode, value);
+ }
+ }
+ }
+ else if ('e' == c)
+ {
+ // Entity decl
+ Object entity = doctype.getEntity(name);
+ if (entity instanceof String)
+ {
+ if (declHandler != null)
+ declHandler.internalEntityDecl(name,
+ (String) entity);
+ }
+ else
+ {
+ XMLParser.ExternalIds ids =
+ (XMLParser.ExternalIds) entity;
+ if (ids.notationName != null)
+ {
+ if (dtdHandler != null)
+ {
+ String pub = ids.publicId;
+ String url = ids.systemId;
+ String not = ids.notationName;
+ dtdHandler.unparsedEntityDecl(name,
+ pub,
+ url,
+ not);
+ }
+ }
+ else
+ {
+ if (declHandler != null)
+ {
+ String pub = ids.publicId;
+ String url = ids.systemId;
+ declHandler.externalEntityDecl(name,
+ pub,
+ url);
+ }
+ }
+ }
+ }
+ else if ('n' == c)
+ {
+ // Notation decl
+ if (dtdHandler != null)
+ {
+ XMLParser.ExternalIds ids =
+ doctype.getNotation(name);
+ String pub = ids.publicId;
+ String url = ids.systemId;
+ dtdHandler.notationDecl(name, pub, url);
+ }
+ }
+ else if ('c' == c)
+ {
+ // Comment
+ if (lexicalHandler != null)
+ {
+ String comment = doctype.getComment(name);
+ char[] b = comment.toCharArray();
+ lexicalHandler.comment(b, 0, b.length);
+ }
+ }
+ else if ('p' == c)
+ {
+ // Processing instruction
+ if (contentHandler != null)
+ {
+ String[] pi = doctype.getPI(name);
+ String target = pi[0];
+ String data = pi[1];
+ if (data == null)
+ data = "";
+ contentHandler.processingInstruction(target, data);
+ }
+ }
+ }
+ if (lexicalHandler != null)
+ lexicalHandler.endDTD();
+ }
+ }
+ }
+ catch (XMLStreamException e)
+ {
+ if (!startDocumentDone && contentHandler != null)
+ contentHandler.startDocument();
+ SAXParseException e2 = new SAXParseException(e.getMessage(), this);
+ e2.initCause(e);
+ if (errorHandler != null)
+ errorHandler.fatalError(e2);
+ if (contentHandler != null)
+ contentHandler.endDocument();
+ throw e2;
+ }
+ finally
+ {
+ if (opened)
+ in.close();
+ reset();
+ }
+ }
+
+ /**
+ * Indicates whether the specified characters are ignorable whitespace.
+ */
+ private boolean isIgnorableWhitespace(XMLParser reader, char[] b,
+ boolean testCharacters)
+ throws XMLStreamException
+ {
+ XMLParser.Doctype doctype = reader.doctype;
+ if (doctype == null)
+ return false;
+ String currentElement = reader.getCurrentElement();
+ // check for xml:space
+ int ac = reader.getAttributeCount();
+ for (int i = 0; i < ac; i++)
+ {
+ QName aname = reader.getAttributeQName(i);
+ if ("space".equals(aname.getLocalPart()) &&
+ XMLConstants.XML_NS_URI.equals(aname.getNamespaceURI()))
+ {
+ if ("preserve".equals(reader.getAttributeValue(i)))
+ return false;
+ }
+ }
+ XMLParser.ContentModel model = doctype.getElementModel(currentElement);
+ if (model == null || model.type != XMLParser.ContentModel.ELEMENT)
+ return false;
+ if (model.external && xmlStandalone)
+ return false;
+ boolean white = true;
+ if (testCharacters)
+ {
+ for (int i = 0; i < b.length; i++)
+ {
+ if (b[i] != ' ' && b[i] != '\t' && b[i] != '\n' && b[i] != '\r')
+ {
+ white = false;
+ break;
+ }
+ }
+ }
+ return white;
+ }
+
+ public void parse(String systemId)
+ throws IOException, SAXException
+ {
+ parse(new InputSource(systemId));
+ }
+
+ // -- Attributes2 --
+
+ public int getIndex(String qName)
+ {
+ int len = reader.getAttributeCount();
+ for (int i = 0; i < len; i++)
+ {
+ QName q = reader.getAttributeQName(i);
+ String localName = q.getLocalPart();
+ String prefix = q.getPrefix();
+ String qn = ("".equals(prefix)) ? localName : prefix + ":" + localName;
+ if (qName.equals(qn))
+ return i;
+ }
+ return -1;
+ }
+
+ public int getIndex(String uri, String localName)
+ {
+ int len = reader.getAttributeCount();
+ for (int i = 0; i < len; i++)
+ {
+ QName q = reader.getAttributeQName(i);
+ String ln = q.getLocalPart();
+ String u = q.getNamespaceURI();
+ if (u == null && uri != null)
+ continue;
+ if (u != null && !u.equals(uri))
+ continue;
+ if (ln.equals(localName))
+ return i;
+ }
+ return -1;
+ }
+
+ public int getLength()
+ {
+ return reader.getAttributeCount();
+ }
+
+ public String getLocalName(int index)
+ {
+ return reader.getAttributeName(index);
+ }
+
+ public String getQName(int index)
+ {
+ QName q = reader.getAttributeQName(index);
+ String localName = q.getLocalPart();
+ String prefix = q.getPrefix();
+ return ("".equals(prefix)) ? localName : prefix + ":" + localName;
+ }
+
+ public String getType(int index)
+ {
+ String ret = reader.getAttributeType(index);
+ // SAX doesn't permit ENUMERATION?
+ return ("ENUMERATION".equals(ret)) ? "NMTOKEN" : ret;
+ }
+
+ public String getType(String qName)
+ {
+ int index = getIndex(qName);
+ return (index == -1) ? null : getType(index);
+ }
+
+ public String getType(String uri, String localName)
+ {
+ int index = getIndex(uri, localName);
+ return (index == -1) ? null : getType(index);
+ }
+
+ public String getURI(int index)
+ {
+ String ret = reader.getAttributeNamespace(index);
+ return (ret == null) ? "" : ret;
+ }
+
+ public String getValue(int index)
+ {
+ return reader.getAttributeValue(index);
+ }
+
+ public String getValue(String qName)
+ {
+ int index = getIndex(qName);
+ return (index == -1) ? null : getValue(index);
+ }
+
+ public String getValue(String uri, String localName)
+ {
+ int index = getIndex(uri, localName);
+ return (index == -1) ? null : getValue(index);
+ }
+
+ public boolean isDeclared(int index)
+ {
+ return parser.isAttributeDeclared(index);
+ }
+
+ public boolean isDeclared(String qName)
+ {
+ int index = getIndex(qName);
+ return (index == -1) ? false : isDeclared(index);
+ }
+
+ public boolean isDeclared(String uri, String localName)
+ {
+ int index = getIndex(uri, localName);
+ return (index == -1) ? false : isDeclared(index);
+ }
+
+ public boolean isSpecified(int index)
+ {
+ return reader.isAttributeSpecified(index);
+ }
+
+ public boolean isSpecified(String qName)
+ {
+ int index = getIndex(qName);
+ return (index == -1) ? false : isSpecified(index);
+ }
+
+ public boolean isSpecified(String uri, String localName)
+ {
+ int index = getIndex(uri, localName);
+ return (index == -1) ? false : isSpecified(index);
+ }
+
+ // -- Locator2 --
+
+ public int getColumnNumber()
+ {
+ Location l = reader.getLocation();
+ return l.getColumnNumber();
+ }
+
+ public int getLineNumber()
+ {
+ Location l = reader.getLocation();
+ return l.getLineNumber();
+ }
+
+ public String getPublicId()
+ {
+ return null;
+ }
+
+ public String getSystemId()
+ {
+ Location l = reader.getLocation();
+ return l.getLocationURI();
+ }
+
+ public String getEncoding()
+ {
+ return encoding;
+ }
+
+ public String getXMLVersion()
+ {
+ return xmlVersion;
+ }
+
+ // -- XMLResolver --
+
+ public InputStream resolve(String uri)
+ throws XMLStreamException
+ {
+ return resolve(null, uri);
+ }
+
+ public InputStream resolve(String publicId, String systemId)
+ throws XMLStreamException
+ {
+ if (entityResolver != null)
+ {
+ try
+ {
+ InputSource input =
+ entityResolver.resolveEntity(publicId, systemId);
+ if (input != null)
+ return input.getByteStream();
+ }
+ catch (SAXException e)
+ {
+ XMLStreamException e2 = new XMLStreamException(e.getMessage());
+ e2.initCause(e);
+ throw e2;
+ }
+ catch (IOException e)
+ {
+ XMLStreamException e2 = new XMLStreamException(e.getMessage());
+ e2.initCause(e);
+ throw e2;
+ }
+ }
+ return null;
+ }
+
+ public XMLEventReader resolveAsXMLEventReader(String uri)
+ throws XMLStreamException
+ {
+ // unused
+ return null;
+ }
+
+ public XMLStreamReader resolveAsXMLStreamReader(String uri)
+ throws XMLStreamException
+ {
+ // unused
+ return null;
+ }
+
+ // -- XMLReporter --
+
+ public void report(String message, String errorType,
+ Object relatedInformation, Location location)
+ throws XMLStreamException
+ {
+ if (errorHandler != null)
+ {
+ try
+ {
+ errorHandler.warning(new SAXParseException(message, this));
+ }
+ catch (SAXException e)
+ {
+ XMLStreamException e2 = new XMLStreamException(e.getMessage());
+ e2.initCause(e);
+ throw e2;
+ }
+ }
+ }
+
+ public static void main(String[] args)
+ throws Exception
+ {
+ SAXParser parser = new SAXParser();
+ InputSource input = new InputSource(args[0]);
+ parser.parse(input, new org.xml.sax.helpers.DefaultHandler());
+
+ }
+
+}
diff --git a/libjava/classpath/gnu/xml/stream/SAXParserFactory.java b/libjava/classpath/gnu/xml/stream/SAXParserFactory.java
new file mode 100644
index 00000000000..a2ccea1e694
--- /dev/null
+++ b/libjava/classpath/gnu/xml/stream/SAXParserFactory.java
@@ -0,0 +1,104 @@
+/* SAXParserFactory.java --
+ Copyright (C) 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.xml.stream;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+import javax.xml.parsers.ParserConfigurationException;
+
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXNotRecognizedException;
+import org.xml.sax.SAXNotSupportedException;
+
+/**
+ * SAX parser factory providing a SAX compatibility layer on top of StAX.
+ *
+ * @author Chris Burdess
+ */
+public class SAXParserFactory
+ extends javax.xml.parsers.SAXParserFactory
+{
+
+ static final Set FEATURE_NAMES = new HashSet();
+ static
+ {
+ FEATURE_NAMES.add("http://xml.org/sax/features/namespaces");
+ FEATURE_NAMES.add("http://xml.org/sax/features/string-interning");
+ FEATURE_NAMES.add("http://xml.org/sax/features/validation");
+ }
+
+ Map features = new HashMap();
+
+ public javax.xml.parsers.SAXParser newSAXParser()
+ throws ParserConfigurationException, SAXException
+ {
+ boolean validating = isValidating();
+ boolean namespaceAware = isNamespaceAware();
+ boolean xIncludeAware = isXIncludeAware();
+ SAXParser ret = new SAXParser(validating, namespaceAware, xIncludeAware);
+ for (Iterator i = features.entrySet().iterator(); i.hasNext(); )
+ {
+ Map.Entry entry = (Map.Entry) i.next();
+ String name = (String) entry.getKey();
+ Boolean value = (Boolean) entry.getValue();
+ ret.setFeature(name, value.booleanValue());
+ }
+ return ret;
+ }
+
+ public void setFeature(String name, boolean value)
+ throws ParserConfigurationException, SAXNotRecognizedException, SAXNotSupportedException
+ {
+ if (!FEATURE_NAMES.contains(name))
+ throw new SAXNotSupportedException(name);
+ features.put(name, value ? Boolean.TRUE : Boolean.FALSE);
+ }
+
+ public boolean getFeature(String name)
+ throws ParserConfigurationException, SAXNotRecognizedException, SAXNotSupportedException
+ {
+ if (!FEATURE_NAMES.contains(name))
+ throw new SAXNotSupportedException(name);
+ Boolean value = (Boolean) features.get(name);
+ return (value == null) ? false : value.booleanValue();
+ }
+
+}
diff --git a/libjava/classpath/gnu/xml/stream/UnicodeReader.java b/libjava/classpath/gnu/xml/stream/UnicodeReader.java
new file mode 100644
index 00000000000..c38516c30f8
--- /dev/null
+++ b/libjava/classpath/gnu/xml/stream/UnicodeReader.java
@@ -0,0 +1,201 @@
+/* UnicodeReader.java --
+ Copyright (C) 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.xml.stream;
+
+import java.io.IOException;
+import java.io.Reader;
+
+/**
+ * A reader that converts UTF-16 characters to Unicode code points.
+ *
+ * @author Chris Burdess
+ */
+class UnicodeReader
+{
+
+ final Reader in;
+
+ UnicodeReader(Reader in)
+ {
+ this.in = in;
+ }
+
+ public void mark(int limit)
+ throws IOException
+ {
+ in.mark(limit * 2);
+ }
+
+ public void reset()
+ throws IOException
+ {
+ in.reset();
+ }
+
+ public int read()
+ throws IOException
+ {
+ int ret = in.read();
+ if (ret == -1)
+ return ret;
+ if (ret >= 0xd800 && ret < 0xdc00)
+ {
+ // Unicode surrogate?
+ int low = in.read();
+ if (low >= 0xdc00 && low < 0xe000)
+ ret = Character.toCodePoint((char) ret, (char) low);
+ else
+ throw new IOException("unpaired surrogate: U+" +
+ Integer.toHexString(ret));
+ }
+ else if (ret >= 0xdc00 && ret < 0xe000)
+ throw new IOException("unpaired surrogate: U+" +
+ Integer.toHexString(ret));
+ return ret;
+ }
+
+ public int read(int[] buf, int off, int len)
+ throws IOException
+ {
+ if (len == 0)
+ return 0;
+ char[] b2 = new char[len];
+ int ret = in.read(b2, 0, len);
+ if (ret <= 0)
+ return ret;
+ int l = ret - 1;
+ int i = 0, j = off;
+ for (; i < l; i++)
+ {
+ char c = b2[i];
+ if (c >= 0xd800 && c < 0xdc00)
+ {
+ // Unicode surrogate?
+ char d = b2[i + 1];
+ if (d >= 0xdc00 && d < 0xe000)
+ {
+ buf[j++] = Character.toCodePoint(c, d);
+ i++;
+ continue;
+ }
+ else
+ throw new IOException("unpaired surrogate: U+" +
+ Integer.toHexString(c));
+ }
+ else if (c >= 0xdc00 && c < 0xe000)
+ throw new IOException("unpaired surrogate: U+" +
+ Integer.toHexString(c));
+ buf[j++] = (int) c;
+ }
+ if (i == l)
+ {
+ // last char
+ char c = b2[l];
+ if (c >= 0xd800 && c < 0xdc00)
+ {
+ int low = in.read();
+ if (low >= 0xdc00 && low < 0xe000)
+ {
+ buf[j++] = Character.toCodePoint(c, (char) low);
+ return j;
+ }
+ else
+ throw new IOException("unpaired surrogate: U+" +
+ Integer.toHexString(c));
+ }
+ else if (c >= 0xdc00 && c < 0xe000)
+ throw new IOException("unpaired surrogate: U+" +
+ Integer.toHexString(c));
+ buf[j++] = (int) c;
+ }
+ return j;
+ }
+
+ public void close()
+ throws IOException
+ {
+ in.close();
+ }
+
+ public static int[] toCodePointArray(String text)
+ throws IOException
+ {
+ char[] b2 = text.toCharArray();
+ int[] buf = new int[b2.length];
+ if (b2.length > 0)
+ {
+ int l = b2.length - 1;
+ int i = 0, j = 0;
+ for (; i < l; i++)
+ {
+ char c = b2[i];
+ if (c >= 0xd800 && c < 0xdc00)
+ {
+ // Unicode surrogate?
+ char d = b2[i + 1];
+ if (d >= 0xdc00 && d < 0xe000)
+ {
+ buf[j++] = Character.toCodePoint(c, d);
+ i++;
+ continue;
+ }
+ else
+ throw new IOException("unpaired surrogate: U+" +
+ Integer.toHexString(c));
+ }
+ else if (c >= 0xdc00 && c < 0xe000)
+ throw new IOException("unpaired surrogate: U+" +
+ Integer.toHexString(c));
+ buf[j++] = (int) c;
+ }
+ if (i == l)
+ {
+ // last char
+ buf[j++] = (int) b2[l];
+ if (j < buf.length)
+ {
+ int[] buf2 = new int[j];
+ System.arraycopy(buf, 0, buf2, 0, j);
+ buf = buf2;
+ }
+ }
+ }
+ return buf;
+ }
+
+}
diff --git a/libjava/classpath/gnu/xml/stream/XIncludeFilter.java b/libjava/classpath/gnu/xml/stream/XIncludeFilter.java
new file mode 100644
index 00000000000..e151ac69d3c
--- /dev/null
+++ b/libjava/classpath/gnu/xml/stream/XIncludeFilter.java
@@ -0,0 +1,932 @@
+/* XIncludeFilter.java --
+ Copyright (C) 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.xml.stream;
+
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.IOException;
+import java.io.Reader;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.net.URLConnection;
+import java.util.HashSet;
+import java.util.NoSuchElementException;
+import java.util.StringTokenizer;
+import javax.xml.namespace.QName;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.stream.XMLInputFactory;
+import javax.xml.stream.XMLStreamConstants;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+import javax.xml.stream.util.ReaderDelegate;
+
+import org.w3c.dom.Attr;
+import org.w3c.dom.Document;
+import org.w3c.dom.DOMImplementation;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+import org.w3c.dom.ProcessingInstruction;
+import org.w3c.dom.TypeInfo;
+import org.w3c.dom.traversal.DocumentTraversal;
+import org.w3c.dom.traversal.NodeFilter;
+import org.w3c.dom.traversal.TreeWalker;
+import org.w3c.dom.xpath.XPathEvaluator;
+import org.w3c.dom.xpath.XPathNSResolver;
+import org.w3c.dom.xpath.XPathResult;
+import org.xml.sax.SAXException;
+
+/**
+ * StAX filter for performing XInclude processing.
+ *
+ * @see http://www.w3.org/TR/xinclude/
+ * @see http://www.w3.org/TR/xptr-framework/
+ * @see http://www.w3.org/TR/xptr-element/
+ *
+ * @author Chris Burdess
+ */
+class XIncludeFilter
+ extends ReaderDelegate
+{
+
+ static final String XINCLUDE_NS_URI = "http://www.w3.org/2001/XInclude";
+ static final int SHOW_FLAGS =
+ NodeFilter.SHOW_CDATA_SECTION |
+ NodeFilter.SHOW_COMMENT |
+ NodeFilter.SHOW_ELEMENT |
+ NodeFilter.SHOW_ENTITY_REFERENCE |
+ NodeFilter.SHOW_PROCESSING_INSTRUCTION |
+ NodeFilter.SHOW_TEXT;
+
+ final String systemId;
+ final boolean namespaceAware;
+ final boolean validating;
+ final boolean expandERefs;
+ String href;
+ int event;
+ boolean included;
+ XPathResult result;
+ int snapshotIndex;
+ Node current;
+ TreeWalker walker;
+ HashSet seen = new HashSet();
+ boolean backtracking;
+ boolean lookahead;
+
+ Reader includedText;
+ char[] buf;
+ int len = -1;
+ boolean inInclude, inFallback, seenFallback;
+
+ DocumentBuilder builder;
+
+ XIncludeFilter(XMLStreamReader reader, String systemId,
+ boolean namespaceAware, boolean validating,
+ boolean expandERefs)
+ {
+ super(reader);
+ this.systemId = XMLParser.absolutize(null, systemId);
+ this.namespaceAware = namespaceAware;
+ this.validating = validating;
+ this.expandERefs = expandERefs;
+ }
+
+ public int getAttributeCount()
+ {
+ if (current != null)
+ {
+ NamedNodeMap attrs = current.getAttributes();
+ return (attrs == null) ? 0 : attrs.getLength();
+ }
+ return super.getAttributeCount();
+ }
+
+ public String getAttributeName(int index)
+ {
+ if (current != null)
+ {
+ NamedNodeMap attrs = current.getAttributes();
+ if (attrs == null)
+ return null;
+ Node attr = attrs.item(index);
+ return attr.getLocalName();
+ }
+ return super.getAttributeName(index);
+ }
+
+ public String getAttributeNamespace(int index)
+ {
+ if (current != null)
+ {
+ NamedNodeMap attrs = current.getAttributes();
+ if (attrs == null)
+ return null;
+ Node attr = attrs.item(index);
+ return attr.getNamespaceURI();
+ }
+ return super.getAttributeNamespace(index);
+ }
+
+ public String getAttributePrefix(int index)
+ {
+ if (current != null)
+ {
+ NamedNodeMap attrs = current.getAttributes();
+ if (attrs == null)
+ return null;
+ Node attr = attrs.item(index);
+ return attr.getPrefix();
+ }
+ return super.getAttributePrefix(index);
+ }
+
+ public QName getAttributeQName(int index)
+ {
+ if (current != null)
+ {
+ NamedNodeMap attrs = current.getAttributes();
+ if (attrs == null)
+ return null;
+ Node attr = attrs.item(index);
+ String localName = attr.getLocalName();
+ String uri = attr.getNamespaceURI();
+ String prefix = attr.getPrefix();
+ return new QName(uri, localName, prefix);
+ }
+ return super.getAttributeQName(index);
+ }
+
+ public String getAttributeType(int index)
+ {
+ if (current != null)
+ {
+ NamedNodeMap attrs = current.getAttributes();
+ if (attrs == null)
+ return null;
+ Attr attr = (Attr) attrs.item(index);
+ TypeInfo ti = attr.getSchemaTypeInfo();
+ return (ti == null) ? "CDATA" : ti.getTypeName();
+ }
+ return super.getAttributeType(index);
+ }
+
+ public boolean isAttributeSpecified(int index)
+ {
+ if (current != null)
+ {
+ NamedNodeMap attrs = current.getAttributes();
+ if (attrs == null)
+ return false;
+ Attr attr = (Attr) attrs.item(index);
+ return attr.getSpecified();
+ }
+ return super.isAttributeSpecified(index);
+ }
+
+ public String getAttributeValue(int index)
+ {
+ if (current != null)
+ {
+ NamedNodeMap attrs = current.getAttributes();
+ if (attrs == null)
+ return null;
+ Node attr = attrs.item(index);
+ return attr.getNodeValue();
+ }
+ return super.getAttributeValue(index);
+ }
+
+ public String getAttributeValue(String uri, String localName)
+ {
+ if (current != null)
+ {
+ NamedNodeMap attrs = current.getAttributes();
+ if (attrs == null)
+ return null;
+ Node attr = attrs.getNamedItemNS(uri, localName);
+ return (attr == null) ? null : attr.getNodeValue();
+ }
+ return super.getAttributeValue(uri, localName);
+ }
+
+ public String getElementText()
+ throws XMLStreamException
+ {
+ if (current != null)
+ return current.getTextContent();
+ return super.getElementText();
+ }
+
+ public int getEventType()
+ {
+ return event;
+ }
+
+ public String getLocalName()
+ {
+ if (current != null)
+ return current.getLocalName();
+ return super.getLocalName();
+ }
+
+ public QName getName()
+ {
+ if (current != null)
+ {
+ String localName = current.getLocalName();
+ String uri = current.getNamespaceURI();
+ String prefix = current.getPrefix();
+ return new QName(uri, localName, prefix);
+ }
+ return super.getName();
+ }
+
+ public String getNamespaceURI()
+ {
+ if (current != null)
+ return current.getNamespaceURI();
+ return super.getNamespaceURI();
+ }
+
+ // TODO namespaces
+
+ public String getPIData()
+ {
+ if (current != null)
+ return ((ProcessingInstruction) current).getData();
+ return super.getPIData();
+ }
+
+ public String getPITarget()
+ {
+ if (current != null)
+ return ((ProcessingInstruction) current).getTarget();
+ return super.getPITarget();
+ }
+
+ public String getPrefix()
+ {
+ if (current != null)
+ return current.getPrefix();
+ return super.getPrefix();
+ }
+
+ public String getText()
+ {
+ if (current != null)
+ return current.getNodeValue();
+ if (walker != null)
+ {
+ Node n = walker.getCurrentNode();
+ if (n != null)
+ return n.getTextContent();
+ }
+ if (buf != null)
+ return new String(buf, 0, len);
+ return super.getText();
+ }
+
+ public char[] getTextCharacters()
+ {
+ if (current != null)
+ {
+ buf = current.getNodeValue().toCharArray();
+ len = buf.length;
+ }
+ if (buf != null)
+ return buf;
+ return super.getTextCharacters();
+ }
+
+ public int getTextCharacters(int sourceStart, char[] target,
+ int targetStart, int length)
+ throws XMLStreamException
+ {
+ if (current != null)
+ {
+ buf = current.getNodeValue().toCharArray();
+ len = buf.length;
+ }
+ if (buf != null)
+ {
+ int max = Math.min(len - sourceStart, length);
+ if (max > 0)
+ System.arraycopy(buf, sourceStart, target, targetStart, max);
+ return max;
+ }
+ return super.getTextCharacters(sourceStart, target, targetStart, length);
+ }
+
+ public int getTextLength()
+ {
+ if (current != null)
+ {
+ buf = current.getNodeValue().toCharArray();
+ len = buf.length;
+ }
+ if (buf != null)
+ return len;
+ return super.getTextLength();
+ }
+
+ public int getTextStart()
+ {
+ if (current != null)
+ {
+ buf = current.getNodeValue().toCharArray();
+ len = buf.length;
+ }
+ if (buf != null)
+ return 0;
+ return super.getTextStart();
+ }
+
+ public boolean hasNext()
+ throws XMLStreamException
+ {
+ if (!lookahead)
+ {
+ try
+ {
+ next();
+ }
+ catch (NoSuchElementException e)
+ {
+ event = -1;
+ }
+ lookahead = true;
+ }
+ return (event != -1);
+ }
+
+ public int next()
+ throws XMLStreamException
+ {
+ if (lookahead)
+ {
+ lookahead = false;
+ return event;
+ }
+ buf = null;
+ len = 0;
+ if (walker != null)
+ {
+ Node c = walker.getCurrentNode();
+ Node n = null;
+ if (c.getNodeType() == Node.ELEMENT_NODE)
+ {
+ boolean isStartElement = !seen.contains(c);
+ if (isStartElement)
+ {
+ seen.add(c);
+ current = c;
+ event = XMLStreamConstants.START_ELEMENT;
+ return event;
+ }
+ else if (backtracking)
+ {
+ n = walker.nextSibling();
+ if (n != null)
+ backtracking = false;
+ }
+ else
+ {
+ n = walker.firstChild();
+ if (n == null)
+ n = walker.nextSibling();
+ }
+ }
+ else
+ {
+ n = walker.firstChild();
+ if (n == null)
+ n = walker.nextSibling();
+ }
+ if (n == null)
+ {
+ current = walker.parentNode();
+ if (current != null && current.getNodeType() == Node.ELEMENT_NODE)
+ {
+ // end-element
+ backtracking = true;
+ event = XMLStreamConstants.END_ELEMENT;
+ return event;
+ }
+ else
+ {
+ walker = null;
+ current = null;
+ }
+ }
+ else
+ {
+ current = n;
+ switch (n.getNodeType())
+ {
+ case Node.ELEMENT_NODE:
+ return next();
+ case Node.TEXT_NODE:
+ String text = n.getNodeValue();
+ buf = text.toCharArray();
+ len = buf.length;
+ event = isSpace(buf, len) ?
+ XMLStreamConstants.SPACE :
+ XMLStreamConstants.CHARACTERS;
+ return event;
+ case Node.CDATA_SECTION_NODE:
+ event = XMLStreamConstants.CDATA;
+ return event;
+ case Node.COMMENT_NODE:
+ event = XMLStreamConstants.COMMENT;
+ return event;
+ case Node.PROCESSING_INSTRUCTION_NODE:
+ event = XMLStreamConstants.PROCESSING_INSTRUCTION;
+ return event;
+ case Node.ENTITY_REFERENCE_NODE:
+ event = XMLStreamConstants.ENTITY_REFERENCE;
+ return event;
+ default:
+ throw new IllegalStateException();
+ }
+ }
+ }
+ if (result != null)
+ {
+ switch (result.getResultType())
+ {
+ case XPathResult.BOOLEAN_TYPE:
+ boolean bval = result.getBooleanValue();
+ String btext = bval ? "true" : "false";
+ buf = btext.toCharArray();
+ len = buf.length;
+ result = null;
+ event = XMLStreamConstants.CHARACTERS;
+ return event;
+ case XPathResult.NUMBER_TYPE:
+ double nval = result.getNumberValue();
+ String ntext = new Double(nval).toString();
+ buf = ntext.toCharArray();
+ len = buf.length;
+ result = null;
+ event = XMLStreamConstants.CHARACTERS;
+ return event;
+ case XPathResult.STRING_TYPE:
+ String stext = result.getStringValue();
+ buf = stext.toCharArray();
+ len = buf.length;
+ result = null;
+ event = isSpace(buf, len) ?
+ XMLStreamConstants.SPACE :
+ XMLStreamConstants.CHARACTERS;
+ return event;
+ case XPathResult.ANY_UNORDERED_NODE_TYPE:
+ case XPathResult.FIRST_ORDERED_NODE_TYPE:
+ Node n1 = result.getSingleNodeValue();
+ Document d1 = getDocument(n1);
+ walker = getDocumentTraversal(d1)
+ .createTreeWalker(n1, SHOW_FLAGS, null, expandERefs);
+ result = null;
+ return next();
+ case XPathResult.ORDERED_NODE_ITERATOR_TYPE:
+ case XPathResult.UNORDERED_NODE_ITERATOR_TYPE:
+ Node n2 = result.iterateNext();
+ if (n2 == null)
+ {
+ result = null;
+ return next();
+ }
+ Document d2 = getDocument(n2);
+ walker = getDocumentTraversal(d2)
+ .createTreeWalker(n2, SHOW_FLAGS, null, expandERefs);
+ return next();
+ case XPathResult.ORDERED_NODE_SNAPSHOT_TYPE:
+ case XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE:
+ Node n3 = result.snapshotItem(snapshotIndex++);
+ if (n3 == null)
+ {
+ result = null;
+ return next();
+ }
+ Document d3 = getDocument(n3);
+ walker = getDocumentTraversal(d3)
+ .createTreeWalker(n3, SHOW_FLAGS, null, expandERefs);
+ return next();
+ default:
+ throw new IllegalStateException();
+ }
+ }
+ if (includedText != null)
+ {
+ // fill buffer
+ if (buf == null)
+ buf = new char[2048];
+ try
+ {
+ len = includedText.read(buf, 0, buf.length);
+ if (len == -1)
+ {
+ includedText = null;
+ buf = null;
+ return next();
+ }
+ // chars or space?
+ return (event = isSpace(buf, len) ?
+ XMLStreamConstants.SPACE :
+ XMLStreamConstants.CHARACTERS);
+ }
+ catch (IOException e)
+ {
+ XMLStreamException e2 = new XMLStreamException(e.getMessage());
+ e2.initCause(e);
+ throw e2;
+ }
+ }
+ event = super.next();
+ switch (event)
+ {
+ case XMLStreamConstants.START_ELEMENT:
+ String uri = getNamespaceURI();
+ if (XINCLUDE_NS_URI.equals(uri))
+ {
+ String localName = getLocalName();
+ if ("include".equals(localName))
+ {
+ href = getAttributeValue(null, "href");
+ String parse = getAttributeValue(null, "parse");
+ String xpointer = getAttributeValue(null, "xpointer");
+ String encoding = getAttributeValue(null, "encoding");
+ String accept = getAttributeValue(null, "accept");
+ String acceptLanguage = getAttributeValue(null,
+ "accept-language");
+ if (includeResource(href, parse, xpointer, encoding,
+ accept, acceptLanguage))
+ {
+ // Skip to xi:include end-element event
+ int depth = 0;
+ while (depth >= 0)
+ {
+ event = super.next();
+ switch (event)
+ {
+ case XMLStreamConstants.START_ELEMENT:
+ depth++;
+ break;
+ case XMLStreamConstants.END_ELEMENT:
+ depth--;
+ }
+ }
+ }
+ else
+ inInclude = true;
+ }
+ else if (inInclude && "fallback".equals(localName))
+ {
+ if (!seenFallback)
+ inFallback = seenFallback = true;
+ else
+ throw new XMLStreamException("duplicate xi:fallback element");
+ }
+ else if (inInclude)
+ {
+ throw new XMLStreamException("illegal xi element '" +
+ localName + "'");
+ }
+ return next();
+ }
+ break;
+ case XMLStreamConstants.END_ELEMENT:
+ String uri2 = getNamespaceURI();
+ if (XINCLUDE_NS_URI.equals(uri2))
+ {
+ String localName = getLocalName();
+ if ("include".equals(localName))
+ {
+ if (!seenFallback && included)
+ {
+ String msg = "Unable to read " + href +
+ " and no xi:fallback element present";
+ throw new XMLStreamException(msg);
+ }
+ included = false;
+ href = null;
+ inInclude = inFallback = seenFallback = false;
+ }
+ else if ("fallback".equals(localName))
+ inFallback = false;
+ return next();
+ }
+ break;
+ }
+ if (inInclude && !inFallback)
+ return next();
+ return event;
+ }
+
+ boolean isSpace(char[] text, int len)
+ {
+ boolean space = true;
+ for (int i = 0; i < len; i++)
+ {
+ char c = text[i];
+ if (c != ' ' && c != '\t' && c != '\n' && c != '\r')
+ {
+ space = false;
+ break;
+ }
+ }
+ return space;
+ }
+
+ String getBaseURI()
+ {
+ String base = (String) getParent().getProperty("gnu.xml.stream.baseURI");
+ return (base == null) ? systemId : base;
+ }
+
+ boolean includeResource(String href, String parse, String xpointer,
+ String encoding, String accept,
+ String acceptLanguage)
+ {
+ included = false;
+ try
+ {
+ if (xpointer != null)
+ throw new XMLStreamException("xpointer attribute not yet supported");
+ String base = getBaseURI();
+ if (href == null || "".equals(href))
+ href = base;
+ else
+ href = XMLParser.absolutize(base, href);
+ if (parse == null || "xml".equals(parse))
+ {
+ seen.clear();
+ result = null;
+ snapshotIndex = 0;
+ walker = null;
+ current = null;
+ backtracking = false;
+
+ URLConnection connection = getURLConnection(href, accept,
+ acceptLanguage);
+ InputStream in = connection.getInputStream();
+ Document doc = getDocumentBuilder().parse(in, href);
+ DocumentTraversal dt = getDocumentTraversal(doc);
+ if (xpointer == null)
+ {
+ result = null;
+ Node item = doc.getDocumentElement();
+ walker = dt.createTreeWalker(item, SHOW_FLAGS, null,
+ expandERefs);
+ }
+ else
+ {
+ result = null;
+ snapshotIndex = 0;
+ walker = null;
+ // shorthand or scheme-based?
+ int lpi = xpointer.indexOf('(');
+ int rpi = xpointer.indexOf(')', lpi);
+ if (lpi != -1 && rpi != -1)
+ {
+ String scheme = xpointer.substring(0, lpi);
+ if ("element".equals(scheme))
+ {
+ // element() scheme
+ String elementSchemeData =
+ xpointer.substring(lpi + 1, rpi);
+ Node item = doc;
+ int si = elementSchemeData.indexOf('/');
+ if (si == -1)
+ {
+ if (elementSchemeData.length() > 0)
+ item = doc.getElementById(elementSchemeData);
+ }
+ else
+ {
+ if (si > 0)
+ {
+ String context =
+ elementSchemeData.substring(0, si);
+ item = doc.getElementById(context);
+ elementSchemeData =
+ elementSchemeData.substring(si + 1);
+ }
+ StringTokenizer st =
+ new StringTokenizer(elementSchemeData, "/");
+ while (st.hasMoreTokens() && item != null)
+ {
+ int n = Integer.parseInt(st.nextToken());
+ Node ctx = item.getFirstChild();
+ int count = 1;
+ while (ctx != null && count++ < n)
+ ctx = ctx.getNextSibling();
+ item = ctx;
+ }
+ }
+ walker = dt.createTreeWalker(item, SHOW_FLAGS, null,
+ expandERefs);
+ included = true;
+ }
+ else if ("xpointer".equals(scheme))
+ {
+ xpointer = xpointer.substring(lpi + 1, rpi);
+ XPathEvaluator eval = getXPathEvaluator(doc);
+ XPathNSResolver resolver = eval.createNSResolver(doc);
+ result =
+ (XPathResult) eval.evaluate(xpointer, doc,
+ resolver,
+ XPathResult.ANY_TYPE,
+ null);
+ // TODO xpointer() scheme functions
+ included = true;
+ }
+ else
+ {
+ String msg = "Unknown XPointer scheme: " + scheme;
+ throw new XMLStreamException(msg);
+ }
+ }
+ else
+ {
+ Node item = doc.getElementById(xpointer);
+ walker = dt.createTreeWalker(item, SHOW_FLAGS, null,
+ expandERefs);
+ included = true;
+ }
+ }
+ }
+ else if ("text".equals(parse))
+ {
+ URLConnection connection = getURLConnection(href, accept,
+ acceptLanguage);
+ InputStream in = connection.getInputStream();
+ if (encoding == null)
+ {
+ encoding = connection.getContentEncoding();
+ if (encoding == null)
+ {
+ String contentType = connection.getContentType();
+ if (contentType != null)
+ encoding = getParameter(contentType, "charset");
+ }
+ }
+ if (encoding == null)
+ includedText = new InputStreamReader(in, "UTF-8");
+ else
+ includedText = new InputStreamReader(in, encoding);
+ included = true;
+ }
+ else
+ throw new XMLStreamException("value of 'parse' attribute must be "+
+ "'xml' or 'text'");
+ return true;
+ }
+ catch (IOException e)
+ {
+ return false;
+ }
+ catch (XMLStreamException e)
+ {
+ return false;
+ }
+ catch (SAXException e)
+ {
+ return false;
+ }
+ }
+
+ URLConnection getURLConnection(String href, String accept,
+ String acceptLanguage)
+ throws IOException
+ {
+ URL url = new URL(href);
+ URLConnection connection = url.openConnection();
+ if (connection instanceof HttpURLConnection)
+ {
+ HttpURLConnection http = (HttpURLConnection) connection;
+ http.setInstanceFollowRedirects(true);
+ if (accept != null)
+ http.setRequestProperty("Accept", accept);
+ if (acceptLanguage != null)
+ http.setRequestProperty("Accept-Language", acceptLanguage);
+ }
+ return connection;
+ }
+
+ Document getDocument(Node node)
+ {
+ if (node.getNodeType() == Node.DOCUMENT_NODE)
+ return (Document) node;
+ return node.getOwnerDocument();
+ }
+
+ DocumentBuilder getDocumentBuilder()
+ throws XMLStreamException
+ {
+ if (builder == null)
+ {
+ try
+ {
+ DocumentBuilderFactory f = DocumentBuilderFactory.newInstance();
+ f.setXIncludeAware(true);
+ f.setNamespaceAware(namespaceAware);
+ f.setValidating(validating);
+ builder = f.newDocumentBuilder();
+ }
+ catch (ParserConfigurationException e)
+ {
+ XMLStreamException e2 = new XMLStreamException(e.getMessage());
+ e2.initCause(e);
+ throw e2;
+ }
+ }
+ builder.reset();
+ return builder;
+ }
+
+ DocumentTraversal getDocumentTraversal(Document doc)
+ throws XMLStreamException
+ {
+ DOMImplementation dom = doc.getImplementation();
+ if (!dom.hasFeature("Traversal", "2.0"))
+ throw new XMLStreamException("Traversal not supported");
+ return (DocumentTraversal) doc;
+ }
+
+ XPathEvaluator getXPathEvaluator(Document doc)
+ throws XMLStreamException
+ {
+ DOMImplementation dom = doc.getImplementation();
+ if (!dom.hasFeature("XPath", "3.0"))
+ throw new XMLStreamException("XPath not supported");
+ return (XPathEvaluator) doc;
+ }
+
+ static String getParameter(String contentType, String name)
+ {
+ StringTokenizer st = new StringTokenizer(contentType, " ;");
+ if (st.hasMoreTokens())
+ st.nextToken();
+ while (st.hasMoreTokens())
+ {
+ String token = st.nextToken();
+ int ei = token.indexOf('=');
+ if (ei != -1)
+ {
+ String key = token.substring(0, ei);
+ if (key.equals(name))
+ {
+ String value = token.substring(ei + 1);
+ int len = value.length();
+ if (len > 1 &&
+ value.charAt(0) == '"' &&
+ value.charAt(len - 1) == '"')
+ value = value.substring(1, len - 1);
+ else if (len > 1 &&
+ value.charAt(0) == '\'' &&
+ value.charAt(len - 1) == '\'')
+ value = value.substring(1, len - 1);
+ return value;
+ }
+ }
+ }
+ return null;
+ }
+
+}
diff --git a/libjava/classpath/gnu/xml/stream/XMLInputFactoryImpl.java b/libjava/classpath/gnu/xml/stream/XMLInputFactoryImpl.java
index c99f564b623..164774d8236 100644
--- a/libjava/classpath/gnu/xml/stream/XMLInputFactoryImpl.java
+++ b/libjava/classpath/gnu/xml/stream/XMLInputFactoryImpl.java
@@ -77,6 +77,9 @@ public class XMLInputFactoryImpl
protected boolean replacingEntityReferences = true;
protected boolean externalEntities = true;
protected boolean supportDTD = true;
+ protected boolean xIncludeAware = false;
+ protected boolean baseAware = true;
+ protected boolean stringInterning = true;
public XMLInputFactoryImpl()
{
@@ -86,11 +89,28 @@ public class XMLInputFactoryImpl
public XMLStreamReader createXMLStreamReader(Reader reader)
throws XMLStreamException
{
+ /*
return new XMLStreamReaderImpl(reader, null, null,
resolver, reporter,
validating, namespaceAware,
coalescing, replacingEntityReferences,
externalEntities, supportDTD);
+ */
+ XMLParser ret = new XMLParser(reader, null,
+ validating,
+ namespaceAware,
+ coalescing,
+ replacingEntityReferences,
+ externalEntities,
+ supportDTD,
+ baseAware,
+ stringInterning,
+ reporter,
+ resolver);
+ if (xIncludeAware)
+ return new XIncludeFilter(ret, null, namespaceAware, validating,
+ replacingEntityReferences);
+ return ret;
}
public XMLStreamReader createXMLStreamReader(Source source)
@@ -98,21 +118,51 @@ public class XMLInputFactoryImpl
{
String systemId = source.getSystemId();
InputStream in = getInputStream(source);
- return new XMLStreamReaderImpl(in, null, systemId,
+ /*return new XMLStreamReaderImpl(in, null, systemId,
resolver, reporter,
validating, namespaceAware,
coalescing, replacingEntityReferences,
- externalEntities, supportDTD);
+ externalEntities, supportDTD);*/
+ XMLParser ret = new XMLParser(in, systemId,
+ validating,
+ namespaceAware,
+ coalescing,
+ replacingEntityReferences,
+ externalEntities,
+ supportDTD,
+ baseAware,
+ stringInterning,
+ reporter,
+ resolver);
+ if (xIncludeAware)
+ return new XIncludeFilter(ret, systemId, namespaceAware, validating,
+ replacingEntityReferences);
+ return ret;
}
public XMLStreamReader createXMLStreamReader(InputStream in)
throws XMLStreamException
{
- return new XMLStreamReaderImpl(in, null, null,
+ /*return new XMLStreamReaderImpl(in, null, null,
resolver, reporter,
validating, namespaceAware,
coalescing, replacingEntityReferences,
- externalEntities, supportDTD);
+ externalEntities, supportDTD);*/
+ XMLParser ret = new XMLParser(in, null,
+ validating,
+ namespaceAware,
+ coalescing,
+ replacingEntityReferences,
+ externalEntities,
+ supportDTD,
+ baseAware,
+ stringInterning,
+ reporter,
+ resolver);
+ if (xIncludeAware)
+ return new XIncludeFilter(ret, null, namespaceAware, validating,
+ replacingEntityReferences);
+ return ret;
}
public XMLStreamReader createXMLStreamReader(InputStream in, String encoding)
@@ -210,6 +260,12 @@ public class XMLInputFactoryImpl
resolver = (XMLResolver) value;
else if (name.equals(ALLOCATOR))
allocator = (XMLEventAllocator) value;
+ else if (name.equals("gnu.xml.stream.stringInterning"))
+ stringInterning = ((Boolean) value).booleanValue();
+ else if (name.equals("gnu.xml.stream.baseAware"))
+ baseAware = ((Boolean) value).booleanValue();
+ else if (name.equals("gnu.xml.stream.xIncludeAware"))
+ xIncludeAware = ((Boolean) value).booleanValue();
else
throw new IllegalArgumentException(name);
}
@@ -235,6 +291,12 @@ public class XMLInputFactoryImpl
return resolver;
if (name.equals(ALLOCATOR))
return allocator;
+ if (name.equals("gnu.xml.stream.stringInterning"))
+ return stringInterning ? Boolean.TRUE : Boolean.FALSE;
+ if (name.equals("gnu.xml.stream.baseAware"))
+ return baseAware ? Boolean.TRUE : Boolean.FALSE;
+ if (name.equals("gnu.xml.stream.xIncludeAware"))
+ return xIncludeAware ? Boolean.TRUE : Boolean.FALSE;
throw new IllegalArgumentException(name);
}
@@ -248,7 +310,10 @@ public class XMLInputFactoryImpl
name.equals(SUPPORT_DTD) ||
name.equals(REPORTER) ||
name.equals(RESOLVER) ||
- name.equals(ALLOCATOR);
+ name.equals(ALLOCATOR) ||
+ name.equals("gnu.xml.stream.stringInterning") ||
+ name.equals("gnu.xml.stream.baseAware") ||
+ name.equals("gnu.xml.stream.xIncludeAware");
}
public void setEventAllocator(XMLEventAllocator allocator)
diff --git a/libjava/classpath/gnu/xml/stream/XMLParser.java b/libjava/classpath/gnu/xml/stream/XMLParser.java
new file mode 100644
index 00000000000..6f10b9303dc
--- /dev/null
+++ b/libjava/classpath/gnu/xml/stream/XMLParser.java
@@ -0,0 +1,5266 @@
+/* XMLParser.java --
+ Copyright (C) 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version.
+
+Partly derived from code which carried the following notice:
+
+ Copyright (c) 1997, 1998 by Microstar Software Ltd.
+
+ AElfred is free for both commercial and non-commercial use and
+ redistribution, provided that Microstar's copyright and disclaimer are
+ retained intact. You are free to modify AElfred for your own use and
+ to redistribute AElfred with your modifications, provided that the
+ modifications are clearly documented.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ merchantability or fitness for a particular purpose. Please use it AT
+ YOUR OWN RISK.
+*/
+
+package gnu.xml.stream;
+
+import java.io.BufferedInputStream;
+import java.io.EOFException;
+import java.io.File;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.IOException;
+import java.io.Reader;
+import java.io.StringReader;
+import java.io.UnsupportedEncodingException;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.LinkedList;
+import java.util.Map;
+import java.util.NoSuchElementException;
+import java.util.StringTokenizer;
+
+import javax.xml.XMLConstants;
+import javax.xml.namespace.NamespaceContext;
+import javax.xml.namespace.QName;
+import javax.xml.stream.Location;
+import javax.xml.stream.XMLInputFactory;
+import javax.xml.stream.XMLReporter;
+import javax.xml.stream.XMLResolver;
+import javax.xml.stream.XMLStreamConstants;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+
+import gnu.java.net.CRLFInputStream;
+
+/**
+ * An XML parser.
+ * This parser supports the following additional StAX properties:
+ *
+ * gnu.xml.stream.stringInterning
+ * Boolean
+ * Indicates whether markup strings will be interned
+ * gnu.xml.stream.xmlBase
+ * Boolean
+ * Indicates whether XML Base processing will be performed
+ * gnu.xml.stream.baseURI
+ * String
+ * Returns the base URI of the current event
+ *
+ *
+ * @see http://www.w3.org/TR/REC-xml/
+ * @see http://www.w3.org/TR/xml11/
+ * @see http://www.w3.org/TR/REC-xml-names
+ * @see http://www.w3.org/TR/xml-names11
+ * @see http://www.w3.org/TR/xmlbase/
+ *
+ * @author Chris Burdess
+ */
+public class XMLParser
+ implements XMLStreamReader, NamespaceContext
+{
+
+ // -- parser state machine states --
+ private static final int INIT = 0; // start state
+ private static final int PROLOG = 1; // in prolog
+ private static final int CONTENT = 2; // in content
+ private static final int EMPTY_ELEMENT = 3; // empty element state
+ private static final int MISC = 4; // in Misc (after root element)
+
+ // -- parameters for parsing literals --
+ private final static int LIT_ENTITY_REF = 2;
+ private final static int LIT_NORMALIZE = 4;
+ private final static int LIT_ATTRIBUTE = 8;
+ private final static int LIT_DISABLE_PE = 16;
+ private final static int LIT_DISABLE_CREF = 32;
+ private final static int LIT_DISABLE_EREF = 64;
+ private final static int LIT_PUBID = 256;
+
+ // -- types of attribute values --
+ final static int ATTRIBUTE_DEFAULT_UNDECLARED = 30;
+ final static int ATTRIBUTE_DEFAULT_SPECIFIED = 31;
+ final static int ATTRIBUTE_DEFAULT_IMPLIED = 32;
+ final static int ATTRIBUTE_DEFAULT_REQUIRED = 33;
+ final static int ATTRIBUTE_DEFAULT_FIXED = 34;
+
+ /**
+ * The current input.
+ */
+ private Input input;
+
+ /**
+ * Stack of inputs representing XML general entities.
+ * The input representing the XML input stream or reader is always the
+ * first element in this stack.
+ */
+ private LinkedList inputStack = new LinkedList();
+
+ /**
+ * Stack of start-entity events to be reported.
+ */
+ private LinkedList startEntityStack = new LinkedList();
+
+ /**
+ * Stack of end-entity events to be reported.
+ */
+ private LinkedList endEntityStack = new LinkedList();
+
+ /**
+ * Current parser state within the main state machine.
+ */
+ private int state = INIT;
+
+ /**
+ * The (type of the) current event.
+ */
+ private int event;
+
+ /**
+ * Whether we are looking ahead. Used by hasNext.
+ */
+ private boolean lookahead;
+
+ /**
+ * The element name stack. The first element in this stack will be the
+ * root element.
+ */
+ private LinkedList stack = new LinkedList();
+
+ /**
+ * Stack of namespace contexts. These are maps specifying prefix-to-URI
+ * mappings. The first element in this stack is the most recent namespace
+ * context (i.e. the other way around from the element name stack).
+ */
+ private LinkedList namespaces = new LinkedList();
+
+ /**
+ * The base-URI stack. This holds the base URI context for each element.
+ * The first element in this stack is the most recent context (i.e. the
+ * other way around from the element name stack).
+ */
+ private LinkedList bases = new LinkedList();
+
+ /**
+ * The list of attributes for the current element, in the order defined in
+ * the XML stream.
+ */
+ private ArrayList attrs = new ArrayList();
+
+ /**
+ * Buffer for text and character data.
+ */
+ private StringBuffer buf = new StringBuffer();
+
+ /**
+ * Buffer for NMTOKEN strings (markup).
+ */
+ private StringBuffer nmtokenBuf = new StringBuffer();
+
+ /**
+ * Buffer for string literals. (e.g. attribute values)
+ */
+ private StringBuffer literalBuf = new StringBuffer();
+
+ /**
+ * Temporary Unicode character buffer used during character data reads.
+ */
+ private int[] tmpBuf = new int[1024];
+
+ /**
+ * The element content model for the current element.
+ */
+ private ContentModel currentContentModel;
+
+ /**
+ * The validation stack. This holds lists of the elements seen for each
+ * element, in order to determine whether the names and order of these
+ * elements match the content model for the element. The last entry in
+ * this stack represents the current element.
+ */
+ private LinkedList validationStack;
+
+ /**
+ * These sets contain the IDs and the IDREFs seen in the document, to
+ * ensure that IDs are unique and that each IDREF refers to an ID in the
+ * document.
+ */
+ private HashSet ids, idrefs;
+
+ /**
+ * The target and data associated with the current processing instruction
+ * event.
+ */
+ private String piTarget, piData;
+
+ /**
+ * The XML version declared in the XML declaration.
+ */
+ private String xmlVersion;
+
+ /**
+ * The encoding declared in the XML declaration.
+ */
+ private String xmlEncoding;
+
+ /**
+ * The standalone value declared in the XML declaration.
+ */
+ private Boolean xmlStandalone;
+
+ /**
+ * The document type definition.
+ */
+ Doctype doctype;
+
+ /**
+ * State variables for determining parameter-entity expansion.
+ */
+ private boolean expandPE, peIsError;
+
+ /**
+ * Whether this is a validating parser.
+ */
+ private final boolean validating;
+
+ /**
+ * Whether strings representing markup will be interned.
+ */
+ private final boolean stringInterning;
+
+ /**
+ * If true, CDATA sections will be merged with adjacent text nodes into a
+ * single event.
+ */
+ private final boolean coalescing;
+
+ /**
+ * Whether to replace general entity references with their replacement
+ * text automatically during parsing.
+ * Otherwise entity-reference events will be issued.
+ */
+ private final boolean replaceERefs;
+
+ /**
+ * Whether to support external entities.
+ */
+ private final boolean externalEntities;
+
+ /**
+ * Whether to support DTDs.
+ */
+ private final boolean supportDTD;
+
+ /**
+ * Whether to support XML namespaces. If true, namespace information will
+ * be available. Otherwise namespaces will simply be reported as ordinary
+ * attributes.
+ */
+ private final boolean namespaceAware;
+
+ /**
+ * Whether to support XML Base. If true, URIs specified in xml:base
+ * attributes will be honoured when resolving external entities.
+ */
+ private final boolean baseAware;
+
+ /**
+ * The reporter to receive parsing warnings.
+ */
+ final XMLReporter reporter;
+
+ /**
+ * Callback interface for resolving external entities.
+ */
+ final XMLResolver resolver;
+
+ // -- Constants for testing the next kind of markup event --
+ private static final String TEST_START_ELEMENT = "<";
+ private static final String TEST_END_ELEMENT = "";
+ private static final String TEST_COMMENT = "";
out.write(encodeText(value));
Node cp = node.getParentNode();
if (cp != null && cp.getNodeType() == Node.DOCUMENT_NODE)
- {
- out.write(encodeText(eol));
- }
+ out.write(encodeText(eol));
break;
case Node.DOCUMENT_NODE:
case Node.DOCUMENT_FRAGMENT_NODE:
@@ -355,29 +366,23 @@ public class StreamSerializer
(Document) node : null;
String version = (doc != null) ? doc.getXmlVersion() : null;
if (version == null)
- {
- version = (String) node.getUserData("version");
- }
+ version = (String) node.getUserData("version");
if (version == null)
- {
- version = "1.0";
- }
+ version = "1.0";
out.write(BRA);
out.write(0x3f);
- out.write("xml version='".getBytes("US-ASCII"));
+ out.write("xml version=\"".getBytes("US-ASCII"));
out.write(version.getBytes("US-ASCII"));
- out.write(APOS);
+ out.write(0x22);
if (!("UTF-8".equalsIgnoreCase(encoding)))
{
- out.write(" encoding='".getBytes("US-ASCII"));
+ out.write(" encoding=\"".getBytes("US-ASCII"));
out.write(encoding.getBytes("US-ASCII"));
- out.write(APOS);
+ out.write(0x22);
}
if ((doc != null && doc.getXmlStandalone()) ||
"yes".equals(node.getUserData("standalone")))
- {
- out.write(" standalone='yes'".getBytes("US-ASCII"));
- }
+ out.write(" standalone=\"yes\"".getBytes("US-ASCII"));
out.write(0x3f);
out.write(KET);
out.write(encodeText(eol));
@@ -387,12 +392,10 @@ public class StreamSerializer
}
else if (mode == Stylesheet.OUTPUT_HTML)
{
- // Ensure that encoding is accessible
+ // Ensure that encoding is accessible if head element is present
String mediaType = (String) node.getUserData("media-type");
if (mediaType == null)
- {
- mediaType = "text/html";
- }
+ mediaType = "text/html";
String contentType = mediaType + "; charset=" +
((encoding.indexOf(' ') != -1) ?
"\"" + encoding + "\"" :
@@ -403,133 +406,87 @@ public class StreamSerializer
for (Node ctx = node.getFirstChild(); ctx != null;
ctx = ctx.getNextSibling())
{
- if (ctx.getNodeType() == Node.ELEMENT_NODE)
+ if (ctx.getNodeType() == Node.ELEMENT_NODE &&
+ isHTMLElement(ctx, "html"))
{
html = ctx;
break;
}
}
- if (html == null)
- {
- html = doc.createElement("html");
- node.appendChild(html);
- }
- Node head = null;
- for (Node ctx = html.getFirstChild(); ctx != null;
- ctx = ctx.getNextSibling())
+ if (html != null)
{
- if (ctx.getNodeType() == Node.ELEMENT_NODE)
- {
- String name = ctx.getLocalName();
- if (name == null)
- {
- name = ctx.getNodeName();
- }
- if ("head".equalsIgnoreCase(name))
- {
- head = ctx;
- break;
- }
- }
- }
- if (head == null)
- {
- head = doc.createElement("head");
- Node c1 = null;
+ Node head = null;
for (Node ctx = html.getFirstChild(); ctx != null;
ctx = ctx.getNextSibling())
{
- if (ctx.getNodeType() == Node.ELEMENT_NODE)
+ if (isHTMLElement(ctx, "head"))
{
- c1 = ctx;
+ head = ctx;
break;
}
}
- if (c1 != null)
- {
- html.insertBefore(head, c1);
- }
- else
- {
- html.appendChild(head);
- }
- }
- Node meta = null;
- Node metaContent = null;
- for (Node ctx = head.getFirstChild(); ctx != null;
- ctx = ctx.getNextSibling())
- {
- if (ctx.getNodeType() == Node.ELEMENT_NODE)
+ if (head != null)
{
- String name = ctx.getLocalName();
- if (name == null)
- {
- name = ctx.getNodeName();
- }
- if ("meta".equalsIgnoreCase(name))
+ Node meta = null;
+ Node metaContent = null;
+ for (Node ctx = head.getFirstChild(); ctx != null;
+ ctx = ctx.getNextSibling())
{
- NamedNodeMap metaAttrs = ctx.getAttributes();
- int len = metaAttrs.getLength();
- String httpEquiv = null;
- Node content = null;
- for (int i = 0; i < len; i++)
+ if (isHTMLElement(ctx, "meta"))
{
- Node attr = metaAttrs.item(i);
- String attrName = attr.getNodeName();
- if ("http-equiv".equalsIgnoreCase(attrName))
+ NamedNodeMap metaAttrs = ctx.getAttributes();
+ int len = metaAttrs.getLength();
+ String httpEquiv = null;
+ Node content = null;
+ for (int i = 0; i < len; i++)
{
- httpEquiv = attr.getNodeValue();
+ Node attr = metaAttrs.item(i);
+ String attrName = attr.getNodeName();
+ if ("http-equiv".equalsIgnoreCase(attrName))
+ httpEquiv = attr.getNodeValue();
+ else if ("content".equalsIgnoreCase(attrName))
+ content = attr;
}
- else if ("content".equalsIgnoreCase(attrName))
+ if ("Content-Type".equalsIgnoreCase(httpEquiv))
{
- content = attr;
+ meta = ctx;
+ metaContent = content;
+ break;
}
}
- if ("Content-Type".equalsIgnoreCase(httpEquiv))
- {
- meta = ctx;
- metaContent = content;
- break;
- }
}
+ if (meta == null)
+ {
+ meta = doc.createElement("meta");
+ // Insert first
+ Node first = head.getFirstChild();
+ if (first == null)
+ head.appendChild(meta);
+ else
+ head.insertBefore(meta, first);
+ Node metaHttpEquiv = doc.createAttribute("http-equiv");
+ meta.getAttributes().setNamedItem(metaHttpEquiv);
+ metaHttpEquiv.setNodeValue("Content-Type");
+ }
+ if (metaContent == null)
+ {
+ metaContent = doc.createAttribute("content");
+ meta.getAttributes().setNamedItem(metaContent);
+ }
+ metaContent.setNodeValue(contentType);
+ htmlEncoded = true;
}
}
- if (meta == null)
- {
- meta = doc.createElement("meta");
- // Insert first
- Node first = head.getFirstChild();
- if (first == null)
- {
- head.appendChild(meta);
- }
- else
- {
- head.insertBefore(meta, first);
- }
- Node metaHttpEquiv = doc.createAttribute("http-equiv");
- meta.getAttributes().setNamedItem(metaHttpEquiv);
- metaHttpEquiv.setNodeValue("Content-Type");
- }
- if (metaContent == null)
- {
- metaContent = doc.createAttribute("content");
- meta.getAttributes().setNamedItem(metaContent);
- }
- metaContent.setNodeValue(contentType);
- // phew
}
children = node.getFirstChild();
if (children != null)
- {
- serialize(children, out, convertToCdata);
- }
+ serialize(children, out, convertToCdata);
break;
case Node.DOCUMENT_TYPE_NODE:
DocumentType doctype = (DocumentType) node;
out.write(BRA);
out.write(BANG);
- out.write(encodeText("DOCTYPE "));
+ out.write(encodeText("DOCTYPE "));
value = doctype.getNodeName();
out.write(encodeText(value));
String publicId = doctype.getPublicId();
@@ -569,41 +526,73 @@ public class StreamSerializer
out.write(encodeText(eol));
}
break;
+ default:
+ System.err.println("Unhandled node type: "+nt);
}
- if (defined)
+ }
+
+ boolean isHTMLElement(Node node, String name)
+ {
+ if (node.getNodeType() != Node.ELEMENT_NODE)
+ return false;
+ String localName = node.getLocalName();
+ if (localName == null)
+ localName = node.getNodeName();
+ if (!name.equalsIgnoreCase(localName))
+ return false;
+ String uri = node.getNamespaceURI();
+ return (uri == null || HTML_URIS.contains(uri));
+ }
+
+ boolean isDefined(String uri, String prefix)
+ {
+ if (XMLConstants.XML_NS_URI.equals(uri))
+ return "xml".equals(prefix);
+ if (XMLConstants.XMLNS_ATTRIBUTE_NS_URI.equals(uri))
+ return "xmlns".equals(prefix);
+ if (prefix == null)
+ prefix = "";
+ for (Iterator i = namespaces.iterator(); i.hasNext(); )
{
- undefine(uri);
+ Map ctx = (Map) i.next();
+ String val = (String) ctx.get(uri);
+ if (val != null && val.equals(prefix))
+ return true;
}
+ return false;
}
- boolean isDefined(String uri)
+ void pushNamespaceContext()
{
- return XMLConstants.XML_NS_URI.equals(uri) ||
- XMLConstants.XMLNS_ATTRIBUTE_NS_URI.equals(uri) ||
- namespaces.containsKey(uri);
+ namespaces.addFirst(new HashMap());
}
String define(String uri, String prefix)
{
- while (namespaces.containsValue(prefix))
+ if (namespaces.isEmpty())
+ return prefix;
+ HashMap ctx = (HashMap) namespaces.getFirst();
+ while (ctx.containsValue(prefix))
{
// Fabricate new prefix
prefix = prefix + "_";
}
- namespaces.put(uri, prefix);
+ ctx.put(uri, prefix);
return prefix;
}
- void undefine(String uri)
+ void popNamespaceContext()
{
- namespaces.remove(uri);
+ namespaces.removeFirst();
}
final byte[] encodeText(String text)
throws IOException
{
encoder.reset();
- if (!encoder.canEncode(text))
+ boolean htmlNeedingEncoding =
+ (mode == Stylesheet.OUTPUT_HTML && !htmlEncoded);
+ if (!encoder.canEncode(text) || htmlNeedingEncoding)
{
// Check each character
StringBuffer buf = new StringBuffer();
@@ -611,11 +600,7 @@ public class StreamSerializer
for (int i = 0; i < len; i++)
{
char c = text.charAt(i);
- if (encoder.canEncode(c))
- {
- buf.append(c);
- }
- else
+ if (!encoder.canEncode(c))
{
// Replace with character entity reference
String hex = Integer.toHexString((int) c);
@@ -623,6 +608,20 @@ public class StreamSerializer
buf.append(hex);
buf.append(';');
}
+ else if (htmlNeedingEncoding)
+ {
+ String entityName = getHTMLCharacterEntity(c);
+ if (entityName != null)
+ {
+ buf.append('&');
+ buf.append(entityName);
+ buf.append(';');
+ }
+ else
+ buf.append(c);
+ }
+ else
+ buf.append(c);
}
text = buf.toString();
}
@@ -656,17 +655,13 @@ public class StreamSerializer
if (c == '<')
{
if (buf == null)
- {
- buf = new StringBuffer(text.substring(0, i));
- }
+ buf = new StringBuffer(text.substring(0, i));
buf.append("<");
}
else if (c == '>')
{
if (buf == null)
- {
- buf = new StringBuffer(text.substring(0, i));
- }
+ buf = new StringBuffer(text.substring(0, i));
buf.append(">");
}
else if (c == '&')
@@ -675,25 +670,19 @@ public class StreamSerializer
text.charAt(i + 1) == '{')
{
if (buf != null)
- {
- buf.append(c);
- }
+ buf.append(c);
}
else
{
if (buf == null)
- {
- buf = new StringBuffer(text.substring(0, i));
- }
+ buf = new StringBuffer(text.substring(0, i));
buf.append("&");
}
}
else if (c == '\'' && inAttr)
{
if (buf == null)
- {
- buf = new StringBuffer(text.substring(0, i));
- }
+ buf = new StringBuffer(text.substring(0, i));
if (mode == Stylesheet.OUTPUT_HTML)
// HTML does not define ', use character entity ref
buf.append("'");
@@ -703,9 +692,7 @@ public class StreamSerializer
else if (c == '"' && inAttr)
{
if (buf == null)
- {
- buf = new StringBuffer(text.substring(0, i));
- }
+ buf = new StringBuffer(text.substring(0, i));
buf.append(""");
}
else if (encodeCtl)
@@ -713,23 +700,17 @@ public class StreamSerializer
if (c < 0x20)
{
if (buf == null)
- {
- buf = new StringBuffer(text.substring(0, i));
- }
+ buf = new StringBuffer(text.substring(0, i));
buf.append('&');
buf.append('#');
buf.append((int) c);
buf.append(';');
}
else if (buf != null)
- {
- buf.append(c);
- }
+ buf.append(c);
}
else if (buf != null)
- {
- buf.append(c);
- }
+ buf.append(c);
}
return (buf == null) ? text : buf.toString();
}
@@ -763,4 +744,109 @@ public class StreamSerializer
return (attributes != null && attributes.contains(attrName));
}
+ static String getHTMLCharacterEntity(char c)
+ {
+ // Hardcode these here to avoid loading the HTML DTD
+ switch (c)
+ {
+ case 160: return "nbsp";
+ case 161: return "iexcl";
+ case 162: return "cent";
+ case 163: return "pound";
+ case 164: return "curren";
+ case 165: return "yen";
+ case 166: return "brvbar";
+ case 167: return "sect";
+ case 168: return "uml";
+ case 169: return "copy";
+ case 170: return "ordf";
+ case 171: return "laquo";
+ case 172: return "not";
+ case 173: return "shy";
+ case 174: return "reg";
+ case 175: return "macr";
+ case 176: return "deg";
+ case 177: return "plusmn";
+ case 178: return "sup2";
+ case 179: return "sup3";
+ case 180: return "acute";
+ case 181: return "micro";
+ case 182: return "para";
+ case 183: return "middot";
+ case 184: return "cedil";
+ case 185: return "sup1";
+ case 186: return "ordm";
+ case 187: return "raquo";
+ case 188: return "frac14";
+ case 189: return "frac12";
+ case 190: return "frac34";
+ case 191: return "iquest";
+ case 192: return "Agrave";
+ case 193: return "Aacute";
+ case 194: return "Acirc";
+ case 195: return "Atilde";
+ case 196: return "Auml";
+ case 197: return "Aring";
+ case 198: return "AElig";
+ case 199: return "Ccedil";
+ case 200: return "Egrave";
+ case 201: return "Eacute";
+ case 202: return "Ecirc";
+ case 203: return "Euml";
+ case 204: return "Igrave";
+ case 205: return "Iacute";
+ case 206: return "Icirc";
+ case 207: return "Iuml";
+ case 208: return "ETH";
+ case 209: return "Ntilde";
+ case 210: return "Ograve";
+ case 211: return "Oacute";
+ case 212: return "Ocirc";
+ case 213: return "Otilde";
+ case 214: return "Ouml";
+ case 215: return "times";
+ case 216: return "Oslash";
+ case 217: return "Ugrave";
+ case 218: return "Uacute";
+ case 219: return "Ucirc";
+ case 220: return "Uuml";
+ case 221: return "Yacute";
+ case 222: return "THORN";
+ case 223: return "szlig";
+ case 224: return "agrave";
+ case 225: return "aacute";
+ case 226: return "acirc";
+ case 227: return "atilde";
+ case 228: return "auml";
+ case 229: return "aring";
+ case 230: return "aelig";
+ case 231: return "ccedil";
+ case 232: return "egrave";
+ case 233: return "eacute";
+ case 234: return "ecirc";
+ case 235: return "euml";
+ case 236: return "igrave";
+ case 237: return "iacute";
+ case 238: return "icirc";
+ case 239: return "iuml";
+ case 240: return "eth";
+ case 241: return "ntilde";
+ case 242: return "ograve";
+ case 243: return "oacute";
+ case 244: return "ocirc";
+ case 245: return "otilde";
+ case 246: return "ouml";
+ case 247: return "divide";
+ case 248: return "oslash";
+ case 249: return "ugrave";
+ case 250: return "uacute";
+ case 251: return "ucirc";
+ case 252: return "uuml";
+ case 253: return "yacute";
+ case 254: return "thorn";
+ case 255: return "yuml";
+ default: return null;
+ }
+ }
+
}
diff --git a/libjava/classpath/gnu/xml/transform/StrippingInstruction.java b/libjava/classpath/gnu/xml/transform/StrippingInstruction.java
new file mode 100644
index 00000000000..c6391b9c521
--- /dev/null
+++ b/libjava/classpath/gnu/xml/transform/StrippingInstruction.java
@@ -0,0 +1,73 @@
+/* StrippingInstruction.java --
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.xml.transform;
+
+import gnu.xml.xpath.NameTest;
+
+/**
+ * An entry in a strip-space or preserve-space list.
+ *
+ * @author Chris Burdess
+ */
+class StrippingInstruction
+{
+
+ final NameTest element;
+ final int precedence;
+
+ StrippingInstruction(NameTest element, int precedence)
+ {
+ this.element = element;
+ this.precedence = precedence;
+ }
+
+ /**
+ * Returns the default priority of the element name test.
+ * @see http://www.w3.org/TR/xslt#dt-default-priority
+ */
+ float getPriority()
+ {
+ if (element.matchesAny())
+ return -0.5f;
+ else if (element.matchesAnyLocalName())
+ return -0.25f;
+ else
+ return 0.0f;
+ }
+
+}
diff --git a/libjava/classpath/gnu/xml/transform/Stylesheet.java b/libjava/classpath/gnu/xml/transform/Stylesheet.java
index 99431b699d8..51accaa3b9a 100644
--- a/libjava/classpath/gnu/xml/transform/Stylesheet.java
+++ b/libjava/classpath/gnu/xml/transform/Stylesheet.java
@@ -1,5 +1,5 @@
/* Stylesheet.java --
- Copyright (C) 2004 Free Software Foundation, Inc.
+ Copyright (C) 2004,2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -88,6 +88,8 @@ class Stylesheet
{
static final String XSL_NS = "http://www.w3.org/1999/XSL/Transform";
+ private static final NameTest STYLESHEET_PRESERVE_TEXT =
+ new NameTest(new QName(XSL_NS, "text"), false, false);
static final int OUTPUT_XML = 0;
static final int OUTPUT_HTML = 1;
@@ -208,6 +210,7 @@ class Stylesheet
preserveSpace = new LinkedHashSet();
outputCdataSectionElements = new LinkedHashSet();
xpath = (XPathImpl) factory.xpathFactory.newXPath();
+ xpath.setNamespaceContext(this);
if (parent == null)
{
bindings = new Bindings(this);
@@ -218,7 +221,6 @@ class Stylesheet
keys = new LinkedList();
decimalFormats = new LinkedHashMap();
initDefaultDecimalFormat();
- xpath.setNamespaceContext(this);
xpath.setXPathFunctionResolver(this);
}
else
@@ -241,7 +243,6 @@ class Stylesheet
templates = root.templates;
keys = root.keys;
decimalFormats = root.decimalFormats;
- xpath.setNamespaceContext(root);
xpath.setXPathFunctionResolver(root);
}
xpath.setXPathVariableResolver(bindings);
@@ -276,9 +277,7 @@ class Stylesheet
{
Stylesheet stylesheet = this;
while (stylesheet.parent != null)
- {
- stylesheet = stylesheet.parent;
- }
+ stylesheet = stylesheet.parent;
return stylesheet;
}
@@ -408,9 +407,7 @@ class Stylesheet
throws TransformerException
{
if (debug)
- {
- System.err.println("getTemplate: mode="+mode+" context="+context);
- }
+ System.err.println("getTemplate: mode="+mode+" context="+context);
Set candidates = new TreeSet();
for (Iterator j = templates.iterator(); j.hasNext(); )
{
@@ -425,15 +422,11 @@ class Stylesheet
throw new TransformerException(msg);
}
if (!currentTemplate.imports(t))
- {
- isMatch = false;
- }
+ isMatch = false;
}
//System.err.println("\t"+context+" "+t+"="+isMatch);
if (isMatch)
- {
- candidates.add(t);
- }
+ candidates.add(t);
}
//System.err.println("\tcandidates="+candidates);
if (candidates.isEmpty())
@@ -441,9 +434,7 @@ class Stylesheet
// Apply built-in template
// Current template is unchanged
if (debug)
- {
- System.err.println("\tbuiltInTemplate context="+context);
- }
+ System.err.println("\tbuiltInTemplate context="+context);
switch (context.getNodeType())
{
case Node.ELEMENT_NODE:
@@ -453,6 +444,7 @@ class Stylesheet
case Node.COMMENT_NODE:
return builtInNodeTemplate;
case Node.TEXT_NODE:
+ case Node.CDATA_SECTION_NODE:
case Node.ATTRIBUTE_NODE:
return builtInTextTemplate;
default:
@@ -465,9 +457,7 @@ class Stylesheet
// Set current template
currentTemplate = t;
if (debug)
- {
- System.err.println("\ttemplate="+t+" context="+context);
- }
+ System.err.println("\ttemplate="+t+" context="+context);
return t.node;
}
}
@@ -475,25 +465,17 @@ class Stylesheet
TemplateNode getTemplate(QName mode, QName name)
throws TransformerException
{
- //System.err.println("getTemplate: mode="+mode+" name="+name);
Set candidates = new TreeSet();
for (Iterator j = templates.iterator(); j.hasNext(); )
{
Template t = (Template) j.next();
boolean isMatch = t.matches(name);
- //System.err.println("\t"+name+" "+t+"="+isMatch);
if (isMatch)
- {
- candidates.add(t);
- }
+ candidates.add(t);
}
if (candidates.isEmpty())
- {
- return null;
- //throw new TransformerException("template '" + name + "' not found");
- }
+ return null;
Template t = (Template) candidates.iterator().next();
- //System.err.println("\ttemplate="+t+" context="+context);
return t.node;
}
@@ -538,42 +520,30 @@ class Stylesheet
output = node;
String method = getAttribute(attrs, "method");
if ("xml".equals(method) || method == null)
- {
- outputMethod = OUTPUT_XML;
- }
+ outputMethod = OUTPUT_XML;
else if ("html".equals(method))
- {
- outputMethod = OUTPUT_HTML;
- }
+ outputMethod = OUTPUT_HTML;
else if ("text".equals(method))
- {
- outputMethod = OUTPUT_TEXT;
- }
+ outputMethod = OUTPUT_TEXT;
else
{
String msg = "unsupported output method: " + method;
DOMSourceLocator l = new DOMSourceLocator(node);
throw new TransformerConfigurationException(msg, l);
}
- outputPublicId = getAttribute(attrs, "public-id");
- outputSystemId = getAttribute(attrs, "system-id");
+ outputPublicId = getAttribute(attrs, "doctype-public");
+ outputSystemId = getAttribute(attrs, "doctype-system");
outputEncoding = getAttribute(attrs, "encoding");
String indent = getAttribute(attrs, "indent");
if (indent != null)
- {
- outputIndent = "yes".equals(indent);
- }
+ outputIndent = "yes".equals(indent);
outputVersion = getAttribute(attrs, "version");
String omitXmlDecl = getAttribute(attrs, "omit-xml-declaration");
if (omitXmlDecl != null)
- {
- outputOmitXmlDeclaration = "yes".equals(omitXmlDecl);
- }
+ outputOmitXmlDeclaration = "yes".equals(omitXmlDecl);
String standalone = getAttribute(attrs, "standalone");
if (standalone != null)
- {
- outputStandalone = "yes".equals(standalone);
- }
+ outputStandalone = "yes".equals(standalone);
outputMediaType = getAttribute(attrs, "media-type");
String cdataSectionElements =
getAttribute(attrs, "cdata-section-elements");
@@ -581,9 +551,7 @@ class Stylesheet
{
StringTokenizer st = new StringTokenizer(cdataSectionElements, " ");
while (st.hasMoreTokens())
- {
- outputCdataSectionElements.add(st.nextToken());
- }
+ outputCdataSectionElements.add(st.nextToken());
}
}
@@ -728,9 +696,7 @@ class Stylesheet
parse(node.getFirstChild(), false);
}
else if ("template".equals(name))
- {
- templates.add(parseTemplate(node, attrs));
- }
+ templates.add(parseTemplate(node, attrs));
else if ("param".equals(name) ||
"variable".equals(name))
{
@@ -779,9 +745,7 @@ class Stylesheet
factory.newStylesheet(source, precedence + delta, this);
}
else if ("output".equals(name))
- {
- parseOutput(node, attrs);
- }
+ parseOutput(node, attrs);
else if ("preserve-space".equals(name))
{
String elements =
@@ -790,7 +754,9 @@ class Stylesheet
" \t\n\r");
while (st.hasMoreTokens())
{
- preserveSpace.add(parseNameTest(st.nextToken()));
+ NameTest element = parseNameTest(st.nextToken());
+ preserveSpace.add(new StrippingInstruction(element,
+ precedence));
}
}
else if ("strip-space".equals(name))
@@ -801,25 +767,19 @@ class Stylesheet
" \t\n\r");
while (st.hasMoreTokens())
{
- stripSpace.add(parseNameTest(st.nextToken()));
+ NameTest element = parseNameTest(st.nextToken());
+ stripSpace.add(new StrippingInstruction(element,
+ precedence));
}
}
else if ("key".equals(name))
- {
- parseKey(node, attrs);
- }
+ parseKey(node, attrs);
else if ("decimal-format".equals(name))
- {
- parseDecimalFormat(node, attrs);
- }
+ parseDecimalFormat(node, attrs);
else if ("namespace-alias".equals(name))
- {
- parseNamespaceAlias(node, attrs);
- }
+ parseNamespaceAlias(node, attrs);
else if ("attribute-set".equals(name))
- {
- parseAttributeSet(node, attrs);
- }
+ parseAttributeSet(node, attrs);
}
else if (root)
{
@@ -867,12 +827,10 @@ class Stylesheet
final NameTest parseNameTest(String token)
{
if ("*".equals(token))
- {
- return new NameTest(null, true, true);
- }
+ return new NameTest(null, true, true);
else if (token.endsWith(":*"))
{
- QName qName = getQName(token.substring(0, token.length() - 2));
+ QName qName = getQName(token);
return new NameTest(qName, true, false);
}
else
@@ -984,7 +942,13 @@ class Stylesheet
return ret;
}
- boolean isPreserved(Text text)
+ /**
+ * Whitespace stripping.
+ * @param text the text node
+ * @param source true if a source node, false if a stylesheet text node
+ * @see http://www.w3.org/TR/xslt#strip
+ */
+ boolean isPreserved(Text text, boolean source)
throws TransformerConfigurationException
{
// Check characters in text
@@ -996,39 +960,73 @@ class Stylesheet
{
char c = value.charAt(i);
if (c != 0x20 && c != 0x09 && c != 0x0a && c != 0x0d)
- {
- return true;
- }
+ return true;
}
}
// Check parent node
Node ctx = text.getParentNode();
- if (!preserveSpace.isEmpty())
+ if (source)
{
- for (Iterator i = preserveSpace.iterator(); i.hasNext(); )
+ // Source document text node
+ boolean preserve = true;
+ float psPriority = 0.0f, ssPriority = 0.0f;
+ if (!stripSpace.isEmpty())
{
- NameTest preserveTest = (NameTest) i.next();
- if (preserveTest.matches(ctx, 1, 1))
+ // Conflict resolution
+ StrippingInstruction ssi = null, psi = null;
+ for (Iterator i = stripSpace.iterator(); i.hasNext(); )
+ {
+ StrippingInstruction si = (StrippingInstruction) i.next();
+ if (si.element.matches(ctx, 1, 1))
+ {
+ if (ssi != null)
+ {
+ if (si.precedence < ssi.precedence)
+ continue;
+ float p = si.getPriority();
+ if (p < ssPriority)
+ continue;
+ }
+ ssi = si;
+ }
+ }
+ for (Iterator i = preserveSpace.iterator(); i.hasNext(); )
{
- boolean override = false;
- if (!stripSpace.isEmpty())
+ StrippingInstruction si = (StrippingInstruction) i.next();
+ if (si.element.matches(ctx, 1, 1))
{
- for (Iterator j = stripSpace.iterator(); j.hasNext(); )
+ if (psi != null)
{
- NameTest stripTest = (NameTest) j.next();
- if (stripTest.matches(ctx, 1, 1))
- {
- override = true;
- break;
- }
+ if (si.precedence < psi.precedence)
+ continue;
+ float p = si.getPriority();
+ if (p < psPriority)
+ continue;
}
+ psi = si;
}
- if (!override)
+ }
+ if (ssi != null)
+ {
+ if (psi != null)
{
- return true;
+ if (psi.precedence < ssi.precedence)
+ preserve = false;
+ else if (psPriority < ssPriority)
+ preserve = false;
}
+ else
+ preserve = false;
}
}
+ if (preserve)
+ return true;
+ }
+ else
+ {
+ // Stylesheet text node
+ if (STYLESHEET_PRESERVE_TEXT.matches(ctx, 1, 1))
+ return true;
}
// Check whether any ancestor specified xml:space
while (ctx != null)
@@ -1038,24 +1036,14 @@ class Stylesheet
Element element = (Element) ctx;
String xmlSpace = element.getAttribute("xml:space");
if ("default".equals(xmlSpace))
- {
- break;
- }
+ break;
else if ("preserve".equals(xmlSpace))
- {
- return true;
- }
+ return true;
else if (xmlSpace.length() > 0)
{
String msg = "Illegal value for xml:space: " + xmlSpace;
throw new TransformerConfigurationException(msg);
}
- else if ("text".equals(ctx.getLocalName()) &&
- XSL_NS.equals(ctx.getNamespaceURI()))
- {
- // xsl:text implies xml:space='preserve'
- return true;
- }
}
ctx = ctx.getParentNode();
}
@@ -1071,45 +1059,27 @@ class Stylesheet
if ("document".equals(localName) && (arity == 1 || arity == 2))
{
if (current == null)
- {
throw new RuntimeException("current is null");
- }
return new DocumentFunction(getRootStylesheet(), current);
}
else if ("key".equals(localName) && (arity == 2))
- {
- return new KeyFunction(getRootStylesheet());
- }
+ return new KeyFunction(getRootStylesheet());
else if ("format-number".equals(localName) &&
(arity == 2 || arity == 3))
- {
- return new FormatNumberFunction(getRootStylesheet());
- }
+ return new FormatNumberFunction(getRootStylesheet());
else if ("current".equals(localName) && (arity == 0))
- {
- return new CurrentFunction(getRootStylesheet());
- }
+ return new CurrentFunction(getRootStylesheet());
else if ("unparsed-entity-uri".equals(localName) && (arity == 1))
- {
- return new UnparsedEntityUriFunction();
- }
+ return new UnparsedEntityUriFunction();
else if ("generate-id".equals(localName) &&
(arity == 1 || arity == 0))
- {
- return new GenerateIdFunction();
- }
+ return new GenerateIdFunction();
else if ("system-property".equals(localName) && (arity == 1))
- {
- return new SystemPropertyFunction();
- }
+ return new SystemPropertyFunction();
else if ("element-available".equals(localName) && (arity == 1))
- {
- return new ElementAvailableFunction(this);
- }
+ return new ElementAvailableFunction(new NamespaceProxy(current));
else if ("function-available".equals(localName) && (arity == 1))
- {
- return new FunctionAvailableFunction(this);
- }
+ return new FunctionAvailableFunction(new NamespaceProxy(current));
}
return null;
}
@@ -1127,9 +1097,7 @@ class Stylesheet
QName mode = (m == null) ? null : getQName(m);
String s = getAttribute(attrs, "select");
if (s == null)
- {
- s = "child::node()";
- }
+ s = "child::node()";
Node children = node.getFirstChild();
List sortKeys = parseSortKeys(children);
List withParams = parseWithParams(children);
@@ -1411,13 +1379,9 @@ class Stylesheet
if (tnode != null)
{
if (first == null)
- {
- first = tnode;
- }
+ first = tnode;
if (previous != null)
- {
- previous.next = tnode;
- }
+ previous.next = tnode;
previous = tnode;
}
node = next;
@@ -1438,25 +1402,15 @@ class Stylesheet
{
String name = node.getLocalName();
if ("apply-templates".equals(name))
- {
- return parseApplyTemplates(node);
- }
+ return parseApplyTemplates(node);
else if ("call-template".equals(name))
- {
- return parseCallTemplate(node);
- }
+ return parseCallTemplate(node);
else if ("value-of".equals(name))
- {
- return parseValueOf(node);
- }
+ return parseValueOf(node);
else if ("for-each".equals(name))
- {
- return parseForEach(node);
- }
+ return parseForEach(node);
else if ("if".equals(name))
- {
- return parseIf(node);
- }
+ return parseIf(node);
else if ("choose".equals(name))
{
Node children = node.getFirstChild();
@@ -1465,9 +1419,7 @@ class Stylesheet
return ret;
}
else if ("when".equals(name))
- {
- return parseWhen(node);
- }
+ return parseWhen(node);
else if ("otherwise".equals(name))
{
Node children = node.getFirstChild();
@@ -1476,25 +1428,15 @@ class Stylesheet
return ret;
}
else if ("element".equals(name))
- {
- return parseElement(node);
- }
+ return parseElement(node);
else if ("attribute".equals(name))
- {
- return parseAttribute(node);
- }
+ return parseAttribute(node);
else if ("text".equals(name))
- {
- return parseText(node);
- }
+ return parseText(node);
else if ("copy".equals(name))
- {
- return parseCopy(node);
- }
+ return parseCopy(node);
else if ("processing-instruction".equals(name))
- {
- return parseProcessingInstruction(node);
- }
+ return parseProcessingInstruction(node);
else if ("comment".equals(name))
{
Node children = node.getFirstChild();
@@ -1503,9 +1445,7 @@ class Stylesheet
return ret;
}
else if ("number".equals(name))
- {
- return parseNumber(node);
- }
+ return parseNumber(node);
else if ("param".equals(name) ||
"variable".equals(name))
{
@@ -1538,13 +1478,9 @@ class Stylesheet
return ret;
}
else if ("copy-of".equals(name))
- {
- return parseCopyOf(node);
- }
+ return parseCopyOf(node);
else if ("message".equals(name))
- {
- return parseMessage(node);
- }
+ return parseMessage(node);
else if ("apply-imports".equals(name))
{
Node children = node.getFirstChild();
@@ -1562,22 +1498,30 @@ class Stylesheet
String prefix = node.getPrefix();
if (extensionElementPrefixes.contains(prefix))
{
- // Pass over extension elements
+ // Check for xsl:fallback
+ for (Node ctx = node.getFirstChild(); ctx != null;
+ ctx = ctx.getNextSibling())
+ {
+ String ctxUri = ctx.getNamespaceURI();
+ if (XSL_NS.equals(ctxUri) &&
+ "fallback".equals(ctx.getLocalName()))
+ {
+ ctx = ctx.getFirstChild();
+ return (ctx == null) ? null : parse(ctx);
+ }
+ }
+ // Otherwise pass over extension element
return null;
}
switch (node.getNodeType())
{
case Node.TEXT_NODE:
+ case Node.CDATA_SECTION_NODE:
// Determine whether to strip whitespace
Text text = (Text) node;
- if (!isPreserved(text))
+ if (!isPreserved(text, false))
{
// Strip
- /*String data = text.getData().trim();
- if (data.length() > 0)
- {
- text.setData(data);
- } // else */
text.getParentNode().removeChild(text);
return null;
}
@@ -1623,9 +1567,7 @@ class Stylesheet
String aname = attr.getNodeName();
if (Stylesheet.XSL_NS.equals(ans) &&
"use-attribute-sets".equals(attr.getLocalName()))
- {
- continue;
- }
+ continue;
String value = attr.getNodeValue();
TemplateNode grandchild =
parseAttributeValueTemplate(value, node);
@@ -1640,8 +1582,9 @@ class Stylesheet
}
String ename = node.getNodeName();
TemplateNode n = parseAttributeValueTemplate(ename, node);
- TemplateNode ns = (namespaceUri == null) ? null :
- parseAttributeValueTemplate(namespaceUri, node);
+ //TemplateNode ns = (namespaceUri == null) ? null :
+ // parseAttributeValueTemplate(namespaceUri, node);
+ TemplateNode ns = null;
ElementNode ret = new ElementNode(n, ns, useAttributeSets,
node);
ret.children = child;
@@ -1676,9 +1619,7 @@ class Stylesheet
NamedNodeMap attrs = node.getAttributes();
String s = getAttribute(attrs, "select");
if (s == null)
- {
- s = ".";
- }
+ s = ".";
Expr select = (Expr) xpath.compile(s);
String l = getAttribute(attrs, "lang");
TemplateNode lang = (l == null) ? null :
@@ -1728,9 +1669,7 @@ class Stylesheet
ret.add(new WithParam(name, expr));
}
else
- {
- ret.add(new WithParam(name, content));
- }
+ ret.add(new WithParam(name, content));
}
node = node.getNextSibling();
}
@@ -1757,27 +1696,19 @@ class Stylesheet
{
String prefix = attr.getLocalName();
if (XMLConstants.XMLNS_ATTRIBUTE.equals(prefix))
- {
- prefix = "#default";
- }
+ prefix = "#default";
String ns = attr.getNodeValue();
// Should the namespace be excluded?
if (XSL_NS.equals(ns) ||
extensionElementPrefixes.contains(prefix) ||
elementExcludeResultPrefixes.contains(prefix) ||
excludeResultPrefixes.contains(prefix))
- {
- continue;
- }
+ continue;
// Is the namespace already defined on the target?
if (prefix == "#default")
- {
- prefix = null;
- }
+ prefix = null;
if (target.lookupNamespaceURI(prefix) != null)
- {
- continue;
- }
+ continue;
attr = attr.cloneNode(true);
attr = doc.adoptNode(attr);
target.getAttributes().setNamedItemNS(attr);
@@ -1786,23 +1717,17 @@ class Stylesheet
}
Node parent = source.getParentNode();
if (parent != null)
- {
- addNamespaceNodes(parent, target, doc, elementExcludeResultPrefixes);
- }
+ addNamespaceNodes(parent, target, doc, elementExcludeResultPrefixes);
}
static final String getAttribute(NamedNodeMap attrs, String name)
{
Node attr = attrs.getNamedItem(name);
if (attr == null)
- {
- return null;
- }
+ return null;
String ret = attr.getNodeValue();
if (ret.length() == 0)
- {
- return null;
- }
+ return null;
return ret;
}
diff --git a/libjava/classpath/gnu/xml/transform/TransformerFactoryImpl.java b/libjava/classpath/gnu/xml/transform/TransformerFactoryImpl.java
index dde2017ff6b..16e3363f8c6 100644
--- a/libjava/classpath/gnu/xml/transform/TransformerFactoryImpl.java
+++ b/libjava/classpath/gnu/xml/transform/TransformerFactoryImpl.java
@@ -1,5 +1,5 @@
/* TransformerFactoryImpl.java --
- Copyright (C) 2004 Free Software Foundation, Inc.
+ Copyright (C) 2004,2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -37,7 +37,11 @@ exception statement from your version. */
package gnu.xml.transform;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.InputStream;
import java.io.IOException;
+import java.io.OutputStream;
import java.net.URL;
import java.util.Iterator;
import java.util.LinkedHashMap;
@@ -73,7 +77,7 @@ public class TransformerFactoryImpl
{
final XPathFactory xpathFactory;
- final XSLURIResolver resolver;
+ final XSLURIResolver resolver;
ErrorListener userListener;
URIResolver userResolver;
@@ -341,5 +345,46 @@ public class TransformerFactoryImpl
{
return userListener;
}
+
+ /**
+ * Syntax: TransformerFactoryImpl [ [ []]]
+ */
+ public static void main(String[] args)
+ throws Exception
+ {
+ InputStream stylesheet = null, in = null;
+ OutputStream out = null;
+ try
+ {
+ if (args.length > 0)
+ {
+ stylesheet = new FileInputStream(args[0]);
+ if (args.length > 1)
+ {
+ in = new FileInputStream(args[1]);
+ if (args.length > 2)
+ out = new FileOutputStream(args[2]);
+ }
+ }
+ if (in == null)
+ in = System.in;
+ if (out == null)
+ out = System.out;
+ TransformerFactory f = new TransformerFactoryImpl();
+ Transformer t = (stylesheet != null) ?
+ f.newTransformer(new StreamSource(stylesheet)) :
+ f.newTransformer();
+ t.transform(new StreamSource(in), new StreamResult(out));
+ }
+ finally
+ {
+ if (stylesheet != null)
+ stylesheet.close();
+ if (in != null && in instanceof FileInputStream)
+ in.close();
+ if (out != null && out instanceof FileOutputStream)
+ out.close();
+ }
+ }
}
diff --git a/libjava/classpath/gnu/xml/transform/TransformerImpl.java b/libjava/classpath/gnu/xml/transform/TransformerImpl.java
index cf404884736..b7ff668843b 100644
--- a/libjava/classpath/gnu/xml/transform/TransformerImpl.java
+++ b/libjava/classpath/gnu/xml/transform/TransformerImpl.java
@@ -1,5 +1,5 @@
/* TransformerImpl.java --
- Copyright (C) 2004, 2005 Free Software Foundation, Inc.
+ Copyright (C) 2004,2005,2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -128,8 +128,6 @@ class TransformerImpl
{
// Suppress mutation events
((DomDocument) doc).setBuilding(true);
- // TODO find a better/more generic way of doing this than
- // casting
}
// Get the result tree
Node parent = null, nextSibling = null;
@@ -147,8 +145,6 @@ class TransformerImpl
DomDocument drdoc = (DomDocument) rdoc;
drdoc.setBuilding(true);
drdoc.setCheckWellformedness(false);
- // TODO find a better/more generic way of doing this than
- // casting
}
}
boolean created = false;
@@ -184,9 +180,7 @@ class TransformerImpl
{
// Done transforming, reset document
if (doc instanceof DomDocument)
- {
- ((DomDocument) doc).setBuilding(false);
- }
+ ((DomDocument) doc).setBuilding(false);
throw e;
}
}
@@ -214,17 +208,11 @@ class TransformerImpl
}
Document sourceDoc = context.getOwnerDocument();
if (sourceDoc != resultDoc)
- {
- clone = resultDoc.adoptNode(clone);
- }
+ clone = resultDoc.adoptNode(clone);
if (nextSibling != null)
- {
- parent.insertBefore(clone, nextSibling);
- }
+ parent.insertBefore(clone, nextSibling);
else
- {
- parent.appendChild(clone);
- }
+ parent.appendChild(clone);
}
else
{
@@ -256,15 +244,18 @@ class TransformerImpl
DomDocument resultDoc = (DomDocument) parent;
Node root = resultDoc.getDocumentElement();
// Add doctype if specified
- if ((publicId != null || systemId != null) &&
- root != null)
+ if (publicId != null || systemId != null)
{
- // We must know the name of the root element to
- // create the document type
- resultDoc.appendChild(new DomDoctype(resultDoc,
- root.getNodeName(),
- publicId,
- systemId));
+ if (root != null)
+ {
+ // We must know the name of the root element to
+ // create the document type
+ DocumentType doctype = new DomDoctype(resultDoc,
+ root.getNodeName(),
+ publicId,
+ systemId);
+ resultDoc.insertBefore(doctype, root);
+ }
}
resultDoc.setBuilding(false);
resultDoc.setCheckWellformedness(true);
@@ -279,43 +270,25 @@ class TransformerImpl
(Document) parent :
parent.getOwnerDocument();
DOMImplementation impl = resultDoc.getImplementation();
- DocumentType doctype =
- impl.createDocumentType(resultDoc.getNodeName(),
- publicId,
- systemId);
- // Try to insert doctype before first element
- Node ctx = parent.getFirstChild();
- for (; ctx != null &&
- ctx.getNodeType() != Node.ELEMENT_NODE;
- ctx = ctx.getNextSibling())
+ Node root = resultDoc.getDocumentElement();
+ if (root != null)
{
- }
- if (ctx != null)
- {
- parent.insertBefore(doctype, ctx);
- }
- else
- {
- parent.appendChild(doctype);
+ DocumentType doctype =
+ impl.createDocumentType(root.getNodeName(),
+ publicId,
+ systemId);
+ resultDoc.insertBefore(doctype, root);
}
}
}
if (version != null)
- {
- parent.setUserData("version", version, stylesheet);
- }
+ parent.setUserData("version", version, stylesheet);
if (omitXmlDeclaration)
- {
- parent.setUserData("omit-xml-declaration", "yes", stylesheet);
- }
+ parent.setUserData("omit-xml-declaration", "yes", stylesheet);
if (standalone)
- {
- parent.setUserData("standalone", "yes", stylesheet);
- }
+ parent.setUserData("standalone", "yes", stylesheet);
if (mediaType != null)
- {
- parent.setUserData("media-type", mediaType, stylesheet);
- }
+ parent.setUserData("media-type", mediaType, stylesheet);
if (cdataSectionElements != null)
{
List list = new LinkedList();
@@ -390,13 +363,9 @@ class TransformerImpl
if (ex != null)
{
if (errorListener != null)
- {
- errorListener.error(new TransformerException(ex));
- }
+ errorListener.error(new TransformerException(ex));
else
- {
- ex.printStackTrace(System.err);
- }
+ ex.printStackTrace(System.err);
}
}
else if (outputTarget instanceof SAXResult)
@@ -407,22 +376,16 @@ class TransformerImpl
ContentHandler ch = sr.getHandler();
LexicalHandler lh = sr.getLexicalHandler();
if (lh == null && ch instanceof LexicalHandler)
- {
- lh = (LexicalHandler) ch;
- }
+ lh = (LexicalHandler) ch;
SAXSerializer serializer = new SAXSerializer();
serializer.serialize(parent, ch, lh);
}
catch (SAXException e)
{
if (errorListener != null)
- {
- errorListener.error(new TransformerException(e));
- }
+ errorListener.error(new TransformerException(e));
else
- {
- e.printStackTrace(System.err);
- }
+ e.printStackTrace(System.err);
}
}
}
@@ -430,7 +393,7 @@ class TransformerImpl
/**
* Strip whitespace from the source tree.
*/
- void strip(Node node)
+ boolean strip(Node node)
throws TransformerConfigurationException
{
short nt = node.getNodeType();
@@ -438,44 +401,101 @@ class TransformerImpl
{
// Replace entity reference with its content
Node parent = node.getParentNode();
+ Node nextSibling = node.getNextSibling();
Node child = node.getFirstChild();
- if (child != null)
- {
- strip(child);
- }
while (child != null)
{
Node next = child.getNextSibling();
node.removeChild(child);
- parent.insertBefore(child, node);
+ if (nextSibling != null)
+ parent.insertBefore(child, nextSibling);
+ else
+ parent.appendChild(child);
child = next;
}
- parent.removeChild(node);
+ return true;
}
if (nt == Node.TEXT_NODE || nt == Node.CDATA_SECTION_NODE)
{
- if (!stylesheet.isPreserved((Text) node))
+ // Denormalize text into whitespace and non-whitespace nodes
+ String text = node.getNodeValue();
+ String[] tokens = tokenizeWhitespace(text);
+ if (tokens.length > 1)
{
- node.getParentNode().removeChild(node);
- }
- else
- {
- String text = node.getNodeValue();
- String stripped = text.trim();
- if (!text.equals(stripped))
+ node.setNodeValue(tokens[0]);
+ Node parent = node.getParentNode();
+ Node nextSibling = node.getNextSibling();
+ Document doc = node.getOwnerDocument();
+ for (int i = 1; i < tokens.length; i++)
{
- node.setNodeValue(stripped);
+ Node newChild = (nt == Node.CDATA_SECTION_NODE) ?
+ doc.createCDATASection(tokens[i]) :
+ doc.createTextNode(tokens[i]);
+ if (nextSibling != null)
+ parent.insertBefore(newChild, nextSibling);
+ else
+ parent.appendChild(newChild);
}
}
+ return !stylesheet.isPreserved((Text) node, true);
}
else
{
- for (Node child = node.getFirstChild(); child != null;
- child = child.getNextSibling())
+ Node child = node.getFirstChild();
+ while (child != null)
{
- strip(child);
+ boolean remove = strip(child);
+ Node next = child.getNextSibling();
+ if (remove)
+ node.removeChild(child);
+ child = next;
}
}
+ return false;
+ }
+
+ /**
+ * Tokenize the specified text into contiguous whitespace-only and
+ * non-whitespace chunks.
+ */
+ private static String[] tokenizeWhitespace(String text)
+ {
+ int len = text.length();
+ int start = 0, end = len - 1;
+ // Find index of text start
+ for (int i = 0; i < len; i++)
+ {
+ char c = text.charAt(i);
+ boolean whitespace = (c == ' ' || c == '\n' || c == '\t' || c == '\r');
+ if (whitespace)
+ start++;
+ else
+ break;
+ }
+ if (start == end) // all whitespace
+ return new String[] { text };
+ // Find index of text end
+ for (int i = end; i > start; i--)
+ {
+ char c = text.charAt(i);
+ boolean whitespace = (c == ' ' || c == '\n' || c == '\t' || c == '\r');
+ if (whitespace)
+ end--;
+ else
+ break;
+ }
+ if (start == 0 && end == len - 1) // all non-whitespace
+ return new String[] { text };
+ // whitespace, then text, then whitespace
+ String[] ret = (start > 0 && end < len - 1) ?
+ new String[3] : new String[2];
+ int i = 0;
+ if (start > 0)
+ ret[i++] = text.substring(0, start);
+ ret[i++] = text.substring(start, end + 1);
+ if (end < len - 1)
+ ret[i++] = text.substring(end + 1);
+ return ret;
}
/**
@@ -487,6 +507,7 @@ class TransformerImpl
throws IOException
{
OutputStream out = null;
+ boolean created = false;
try
{
out = sr.getOutputStream();
@@ -494,9 +515,7 @@ class TransformerImpl
{
Writer writer = sr.getWriter();
if (writer != null)
- {
- out = new WriterOutputStream(writer);
- }
+ out = new WriterOutputStream(writer);
}
if (out == null)
{
@@ -523,6 +542,7 @@ class TransformerImpl
URL url = new URL(systemId);
out = new FileOutputStream(url.getPath());
}
+ created = true;
}
out = new BufferedOutputStream(out);
StreamSerializer serializer =
@@ -539,10 +559,8 @@ class TransformerImpl
{
try
{
- if (out != null)
- {
- out.close();
- }
+ if (out != null && created)
+ out.close();
}
catch (IOException e)
{
@@ -564,17 +582,13 @@ class TransformerImpl
public void setParameter(String name, Object value)
{
if (stylesheet != null)
- {
- stylesheet.bindings.set(new QName(null, name), value, Bindings.PARAM);
- }
+ stylesheet.bindings.set(new QName(null, name), value, Bindings.PARAM);
}
public Object getParameter(String name)
{
if (stylesheet != null)
- {
- return stylesheet.bindings.get(new QName(null, name), null, 1, 1);
- }
+ return stylesheet.bindings.get(new QName(null, name), null, 1, 1);
return null;
}
@@ -601,13 +615,9 @@ class TransformerImpl
throws IllegalArgumentException
{
if (oformat == null)
- {
- outputProperties.clear();
- }
+ outputProperties.clear();
else
- {
- outputProperties.putAll(oformat);
- }
+ outputProperties.putAll(oformat);
}
public Properties getOutputProperties()
@@ -689,9 +699,7 @@ class TransformerImpl
StringBuffer buf = new StringBuffer();
buf.append('\n');
for (int i = 0; i < offset + 1; i++)
- {
- buf.append(INDENT_WHITESPACE);
- }
+ buf.append(INDENT_WHITESPACE);
String ws = buf.toString();
for (Iterator i = children.iterator(); i.hasNext(); )
{
@@ -703,9 +711,7 @@ class TransformerImpl
buf.append('\n');
ws = buf.toString();
for (int i = 0; i < offset; i++)
- {
- buf.append(INDENT_WHITESPACE);
- }
+ buf.append(INDENT_WHITESPACE);
node.appendChild(doc.createTextNode(ws));
}
}
@@ -749,9 +755,7 @@ class TransformerImpl
while (ctx != null)
{
if (ctx.hasChildNodes())
- {
- convertCdataSectionElements(doc, ctx, list);
- }
+ convertCdataSectionElements(doc, ctx, list);
ctx = ctx.getNextSibling();
}
}
@@ -761,9 +765,7 @@ class TransformerImpl
String ln1 = qname.getLocalPart();
String ln2 = node.getLocalName();
if (ln2 == null)
- {
- return ln1.equals(node.getNodeName());
- }
+ return ln1.equals(node.getNodeName());
else
{
String uri1 = qname.getNamespaceURI();
diff --git a/libjava/classpath/gnu/xml/transform/ValueOfNode.java b/libjava/classpath/gnu/xml/transform/ValueOfNode.java
index 430598a94b3..24c229ea3b3 100644
--- a/libjava/classpath/gnu/xml/transform/ValueOfNode.java
+++ b/libjava/classpath/gnu/xml/transform/ValueOfNode.java
@@ -1,5 +1,5 @@
/* ValueOfNode.java --
- Copyright (C) 2004 Free Software Foundation, Inc.
+ Copyright (C) 2004,2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -69,26 +69,18 @@ final class ValueOfNode
TemplateNode ret = new ValueOfNode(select.clone(stylesheet),
disableOutputEscaping);
if (children != null)
- {
- ret.children = children.clone(stylesheet);
- }
+ ret.children = children.clone(stylesheet);
if (next != null)
- {
- ret.next = next.clone(stylesheet);
- }
+ ret.next = next.clone(stylesheet);
return ret;
}
void doApply(Stylesheet stylesheet, QName mode,
- Node context, int pos, int len,
- Node parent, Node nextSibling)
+ Node context, int pos, int len,
+ Node parent, Node nextSibling)
throws TransformerException
{
Object ret = select.evaluate(context, pos, len);
- /*if (stylesheet.debug)
- {
- System.err.println("value-of: " + select + " -> " + ret);
- }*/
String value;
if (ret instanceof Collection)
{
@@ -100,47 +92,35 @@ final class ValueOfNode
}
value = buf.toString();
}
+ else if (ret == null)
+ value = "";
else
- {
- value = Expr._string(context, ret);
- }
+ value = Expr._string(context, ret);
if (stylesheet.debug)
- {
- System.err.println("value-of: "+context+" "+ select + " -> "+ value);
- }
+ System.err.println("value-of: "+context+" "+ select + " -> "+ value);
if (value != null && value.length() > 0)
{
Document doc = (parent instanceof Document) ?
(Document) parent : parent.getOwnerDocument();
Text textNode = doc.createTextNode(value);
if (disableOutputEscaping)
- {
- textNode.setUserData("disable-output-escaping", "yes", stylesheet);
- }
+ textNode.setUserData("disable-output-escaping", "yes", stylesheet);
if (nextSibling != null)
- {
- parent.insertBefore(textNode, nextSibling);
- }
+ parent.insertBefore(textNode, nextSibling);
else
- {
- parent.appendChild(textNode);
- }
+ parent.appendChild(textNode);
}
// value-of doesn't process children
if (next != null)
- {
- next.apply(stylesheet, mode,
- context, pos, len,
- parent, nextSibling);
- }
+ next.apply(stylesheet, mode,
+ context, pos, len,
+ parent, nextSibling);
}
public boolean references(QName var)
{
if (select != null && select.references(var))
- {
- return true;
- }
+ return true;
return super.references(var);
}
@@ -151,9 +131,7 @@ final class ValueOfNode
buf.append("select=");
buf.append(select);
if (disableOutputEscaping)
- {
- buf.append(",disableOutputEscaping");
- }
+ buf.append(",disableOutputEscaping");
buf.append(']');
return buf.toString();
}
diff --git a/libjava/classpath/gnu/xml/xpath/Expr.java b/libjava/classpath/gnu/xml/xpath/Expr.java
index b4b55dcf94e..76fd49eeff5 100644
--- a/libjava/classpath/gnu/xml/xpath/Expr.java
+++ b/libjava/classpath/gnu/xml/xpath/Expr.java
@@ -1,5 +1,5 @@
/* Expr.java --
- Copyright (C) 2004 Free Software Foundation, Inc.
+ Copyright (C) 2004,2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -233,9 +233,11 @@ public abstract class Expr
*/
public static String _local_name(Node context, Collection nodeSet)
{
- Node node = (nodeSet == null || nodeSet.size() == 0) ? context :
- firstNode(nodeSet);
- return node.getLocalName();
+ if (nodeSet == null || nodeSet.isEmpty())
+ return "";
+ Node node = firstNode(nodeSet);
+ String ret = node.getLocalName();
+ return (ret == null) ? "" : ret;
}
/**
@@ -248,9 +250,11 @@ public abstract class Expr
*/
public static String _namespace_uri(Node context, Collection nodeSet)
{
- Node node = (nodeSet == null || nodeSet.size() == 0) ? context :
- firstNode(nodeSet);
- return node.getNamespaceURI();
+ if (nodeSet == null || nodeSet.isEmpty())
+ return "";
+ Node node = firstNode(nodeSet);
+ String ret = node.getNamespaceURI();
+ return (ret == null) ? "" : ret;
}
/**
@@ -271,17 +275,18 @@ public abstract class Expr
*/
public static String _name(Node context, Collection nodeSet)
{
- Node node = (nodeSet == null || nodeSet.size() == 0) ? context :
- firstNode(nodeSet);
+ if (nodeSet == null || nodeSet.isEmpty())
+ return "";
+ Node node = firstNode(nodeSet);
+ String ret = null;
switch (node.getNodeType())
{
case Node.ATTRIBUTE_NODE:
case Node.ELEMENT_NODE:
case Node.PROCESSING_INSTRUCTION_NODE:
- return node.getNodeName();
- default:
- return "";
+ ret = node.getNodeName();
}
+ return (ret == null) ? "" : ret;
}
/**
@@ -371,7 +376,10 @@ public abstract class Expr
}
if (object instanceof Double)
{
- return ((Double) object).doubleValue() != 0.0;
+ Double value = (Double) object;
+ if (value.isNaN())
+ return false;
+ return value.doubleValue() != 0.0;
}
if (object instanceof String)
{
@@ -473,4 +481,15 @@ public abstract class Expr
}
}
+ static int intValue(Object val)
+ {
+ if (val instanceof Double)
+ {
+ Double d = (Double) val;
+ return d.isNaN() ? 0 : d.intValue();
+ }
+ else
+ return (int) Math.ceil(_number(null, val));
+ }
+
}
diff --git a/libjava/classpath/gnu/xml/xpath/LocalNameFunction.java b/libjava/classpath/gnu/xml/xpath/LocalNameFunction.java
index f8ace9cd5f9..84fb6d48288 100644
--- a/libjava/classpath/gnu/xml/xpath/LocalNameFunction.java
+++ b/libjava/classpath/gnu/xml/xpath/LocalNameFunction.java
@@ -1,5 +1,5 @@
/* LocalNameFunction.java --
- Copyright (C) 2004 Free Software Foundation, Inc.
+ Copyright (C) 2004,2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -38,6 +38,7 @@ exception statement from your version. */
package gnu.xml.xpath;
import java.util.Collection;
+import java.util.Collections;
import java.util.List;
import javax.xml.namespace.QName;
import org.w3c.dom.Node;
@@ -70,7 +71,8 @@ final class LocalNameFunction
public Object evaluate(Node context, int pos, int len)
{
- Object val = (arg == null) ? null : arg.evaluate(context, pos, len);
+ Object val = (arg == null) ? Collections.singleton(context) :
+ arg.evaluate(context, pos, len);
return _local_name(context, (Collection) val);
}
diff --git a/libjava/classpath/gnu/xml/xpath/NameFunction.java b/libjava/classpath/gnu/xml/xpath/NameFunction.java
index dc5e612037a..ea49741fa57 100644
--- a/libjava/classpath/gnu/xml/xpath/NameFunction.java
+++ b/libjava/classpath/gnu/xml/xpath/NameFunction.java
@@ -1,5 +1,5 @@
/* NameFunction.java --
- Copyright (C) 2004 Free Software Foundation, Inc.
+ Copyright (C) 2004,2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -38,6 +38,7 @@ exception statement from your version. */
package gnu.xml.xpath;
import java.util.Collection;
+import java.util.Collections;
import java.util.List;
import javax.xml.namespace.QName;
import org.w3c.dom.Node;
@@ -78,7 +79,8 @@ final class NameFunction
public Object evaluate(Node context, int pos, int len)
{
- Object val = (arg == null) ? null : arg.evaluate(context, pos, len);
+ Object val = (arg == null) ? Collections.singleton(context) :
+ arg.evaluate(context, pos, len);
return _name(context, (Collection) val);
}
diff --git a/libjava/classpath/gnu/xml/xpath/NameTest.java b/libjava/classpath/gnu/xml/xpath/NameTest.java
index c89ba4dd16b..1710103903d 100644
--- a/libjava/classpath/gnu/xml/xpath/NameTest.java
+++ b/libjava/classpath/gnu/xml/xpath/NameTest.java
@@ -1,5 +1,5 @@
/* NameTest.java --
- Copyright (C) 2004 Free Software Foundation, Inc.
+ Copyright (C) 2004,2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -91,29 +91,32 @@ public final class NameTest
return false;
}
if (any)
- {
- return true;
- }
+ return true;
String uri = qName.getNamespaceURI();
String nodeUri = node.getNamespaceURI();
- String nodeLocalName = node.getLocalName();
- if (nodeLocalName != null && !equal(uri, nodeUri))
- {
- return false;
- }
+ if (!equal(uri, nodeUri))
+ return false;
if (anyLocalName)
- {
- return true;
- }
+ return true;
String localName = qName.getLocalPart();
- if (nodeLocalName != null)
+ String nodeLocalName = getLocalName(node);
+ return (localName.equals(nodeLocalName));
+ }
+
+ static String getLocalName(Node node)
+ {
+ String localName = node.getLocalName();
+ if (localName == null)
{
- nodeLocalName = node.getNodeName();
+ localName = node.getNodeName();
+ int ci = localName.indexOf(':');
+ if (ci != -1)
+ localName = localName.substring(ci + 1);
}
- return (localName.equals(nodeLocalName));
+ return localName;
}
- final boolean equal(String s1, String s2)
+ static boolean equal(String s1, String s2)
{
return (((s1 == null || s1.length() == 0) &&
(s2 == null || s2.length() == 0)) ||
@@ -133,9 +136,7 @@ public final class NameTest
public String toString ()
{
if (any)
- {
- return "*";
- }
+ return "*";
return qName.toString();
}
diff --git a/libjava/classpath/gnu/xml/xpath/NamespaceTest.java b/libjava/classpath/gnu/xml/xpath/NamespaceTest.java
index 6d41166bcb9..d93b76d9de8 100644
--- a/libjava/classpath/gnu/xml/xpath/NamespaceTest.java
+++ b/libjava/classpath/gnu/xml/xpath/NamespaceTest.java
@@ -81,28 +81,22 @@ public final class NamespaceTest
if (XMLConstants.XMLNS_ATTRIBUTE_NS_URI.equals(uri) ||
XMLConstants.XMLNS_ATTRIBUTE.equals(node.getPrefix()) ||
XMLConstants.XMLNS_ATTRIBUTE.equals(node.getNodeName()))
- {
- break;
- }
+ break;
// Fall through
default:
// Only process namespace attributes
return false;
}
if (any)
- {
- return true;
- }
+ return true;
+ String uri = qName.getNamespaceURI();
+ String nodeUri = node.getNamespaceURI();
+ if (!NameTest.equal(uri, nodeUri))
+ return false;
if (anyLocalName)
- {
- return true;
- }
+ return true;
String localName = qName.getLocalPart();
- String nodeLocalName = node.getLocalName();
- if (nodeLocalName == null)
- {
- nodeLocalName = node.getNodeName();
- }
+ String nodeLocalName = NameTest.getLocalName(node);
return (localName.equals(nodeLocalName));
}
@@ -119,9 +113,7 @@ public final class NamespaceTest
public String toString ()
{
if (any)
- {
- return "*";
- }
+ return "*";
return qName.toString();
}
diff --git a/libjava/classpath/gnu/xml/xpath/NamespaceUriFunction.java b/libjava/classpath/gnu/xml/xpath/NamespaceUriFunction.java
index e67ec42065e..3ae46f7ee71 100644
--- a/libjava/classpath/gnu/xml/xpath/NamespaceUriFunction.java
+++ b/libjava/classpath/gnu/xml/xpath/NamespaceUriFunction.java
@@ -1,5 +1,5 @@
/* NamespaceUriFunction.java --
- Copyright (C) 2004 Free Software Foundation, Inc.
+ Copyright (C) 2004,2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -38,6 +38,7 @@ exception statement from your version. */
package gnu.xml.xpath;
import java.util.Collection;
+import java.util.Collections;
import java.util.List;
import javax.xml.namespace.QName;
import org.w3c.dom.Node;
@@ -70,7 +71,8 @@ final class NamespaceUriFunction
public Object evaluate(Node context, int pos, int len)
{
- Object val = (arg == null) ? null : arg.evaluate(context, pos, len);
+ Object val = (arg == null) ? Collections.singleton(context) :
+ arg.evaluate(context, pos, len);
return _namespace_uri(context, (Collection) val);
}
diff --git a/libjava/classpath/gnu/xml/xpath/NodeTypeTest.java b/libjava/classpath/gnu/xml/xpath/NodeTypeTest.java
index 807374132e5..09e92d0d9a2 100644
--- a/libjava/classpath/gnu/xml/xpath/NodeTypeTest.java
+++ b/libjava/classpath/gnu/xml/xpath/NodeTypeTest.java
@@ -1,5 +1,5 @@
/* NodeTypeTest.java --
- Copyright (C) 2004 Free Software Foundation, Inc.
+ Copyright (C) 2004,2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -39,6 +39,7 @@ package gnu.xml.xpath;
import javax.xml.namespace.QName;
import org.w3c.dom.Node;
+import org.w3c.dom.ProcessingInstruction;
/**
* Tests whether a node is of a given type.
@@ -83,17 +84,20 @@ public final class NodeTypeTest
case Node.TEXT_NODE:
case Node.CDATA_SECTION_NODE:
case Node.COMMENT_NODE:
+ if (type > 0)
+ {
+ if (nodeType != type)
+ return false;
+ }
+ return true;
case Node.PROCESSING_INSTRUCTION_NODE:
if (type > 0)
{
if (nodeType != type)
- {
- return false;
- }
- if (data != null && !data.equals(node.getNodeValue()))
- {
- return false;
- }
+ return false;
+ if (data != null &&
+ !data.equals(((ProcessingInstruction) node).getTarget()))
+ return false;
}
return true;
default:
diff --git a/libjava/classpath/gnu/xml/xpath/Selector.java b/libjava/classpath/gnu/xml/xpath/Selector.java
index 598038064b5..93408e48b23 100644
--- a/libjava/classpath/gnu/xml/xpath/Selector.java
+++ b/libjava/classpath/gnu/xml/xpath/Selector.java
@@ -1,5 +1,5 @@
/* Selector.java --
- Copyright (C) 2004 Free Software Foundation, Inc.
+ Copyright (C) 2004,2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -85,11 +85,13 @@ public final class Selector
public Selector(int axis, List tests)
{
this.axis = axis;
- this.tests = new Test[tests.size()];
- tests.toArray(this.tests);
- if (axis == NAMESPACE &&
- this.tests.length > 0 &&
- this.tests[0] instanceof NameTest)
+ int len = tests.size();
+ this.tests = new Test[(len == 0) ? 1 : len];
+ if (len > 0)
+ tests.toArray(this.tests);
+ else
+ this.tests[0] = new NameTest(null, true, true);
+ if (axis == NAMESPACE && this.tests[0] instanceof NameTest)
{
NameTest nt = (NameTest) this.tests[0];
this.tests[0] = new NamespaceTest(nt.qName, nt.anyLocalName, nt.any);
@@ -111,16 +113,12 @@ public final class Selector
{
case CHILD:
if (nodeType == Node.ATTRIBUTE_NODE)
- {
- return false;
- }
+ return false;
break;
case ATTRIBUTE:
case NAMESPACE:
if (nodeType != Node.ATTRIBUTE_NODE)
- {
- return false;
- }
+ return false;
break;
case DESCENDANT_OR_SELF:
return true;
@@ -132,13 +130,13 @@ public final class Selector
{
int pos = getContextPosition(context);
int len = getContextSize(context);
+ if (len == 0)
+ System.err.println("WARNING: context size is 0");
for (int j = 0; j < tlen && len > 0; j++)
{
Test test = tests[j];
if (!test.matches(context, pos, len))
- {
- return false;
- }
+ return false;
}
}
return true;
@@ -149,9 +147,7 @@ public final class Selector
int pos = 1;
for (ctx = ctx.getPreviousSibling(); ctx != null;
ctx = ctx.getPreviousSibling())
- {
- pos++;
- }
+ pos++;
return pos;
}
@@ -159,15 +155,17 @@ public final class Selector
{
if (ctx.getNodeType() == Node.ATTRIBUTE_NODE)
{
- Node parent = ((Attr) ctx).getOwnerElement();
- return parent.getAttributes().getLength();
- }
- Node parent = ctx.getParentNode();
- if (parent != null)
- {
- return parent.getChildNodes().getLength();
+ Node owner = ((Attr) ctx).getOwnerElement();
+ return owner.getAttributes().getLength();
}
- return 1;
+ int count = 1;
+ Node sib = ctx.getPreviousSibling();
+ for (; sib != null; sib = sib.getPreviousSibling())
+ count++;
+ sib = ctx.getNextSibling();
+ for (; sib != null; sib = sib.getNextSibling())
+ count++;
+ return count;
}
public Object evaluate(Node context, int pos, int len)
@@ -175,7 +173,6 @@ public final class Selector
Set acc = new LinkedHashSet();
addCandidates(context, acc);
List candidates = new ArrayList(acc);
- //Collections.sort(candidates, documentOrderComparator);
List ret = filterCandidates(candidates, false);
return ret;
}
@@ -184,11 +181,8 @@ public final class Selector
{
Set acc = new LinkedHashSet();
for (Iterator i = ns.iterator(); i.hasNext(); )
- {
- addCandidates((Node) i.next(), acc);
- }
+ addCandidates((Node) i.next(), acc);
List candidates = new ArrayList(acc);
- //Collections.sort(candidates, documentOrderComparator);
List ret = filterCandidates(candidates, true);
return ret;
}
@@ -230,17 +224,7 @@ public final class Selector
}
}
if (test.matches(node, i + 1, len))
- {
- successful.add(node);
- }
- /*
- System.err.println("Testing "+node);
- int p = getContextPosition(node);
- int l = getContextSize(node);
- if (test.matches(node, p, l))
- {
- successful.add(node);
- }*/
+ successful.add(node);
}
candidates = successful;
len = candidates.size();
@@ -305,9 +289,7 @@ public final class Selector
{
acc.add(child);
if (recurse)
- {
- addChildNodes(child, acc, recurse);
- }
+ addChildNodes(child, acc, recurse);
child = child.getNextSibling();
}
}
@@ -320,55 +302,62 @@ public final class Selector
{
acc.add(parent);
if (recurse)
- {
- addParentNode(parent, acc, recurse);
- }
+ addParentNode(parent, acc, recurse);
}
}
void addFollowingNodes(Node context, Collection acc, boolean recurse)
{
- Node cur = context.getNextSibling();
+ if (context != null && recurse)
+ addChildNodes(context, acc, true);
+ Node cur = (context.getNodeType() == Node.ATTRIBUTE_NODE) ? null :
+ context.getNextSibling();
while (cur != null)
{
acc.add(cur);
if (recurse)
- {
- addChildNodes(cur, acc, true);
- }
+ addChildNodes(cur, acc, true);
cur = cur.getNextSibling();
}
if (recurse)
{
- context = (context.getNodeType() == Node.ATTRIBUTE_NODE) ?
- ((Attr) context).getOwnerElement() : context.getParentNode();
- if (context != null)
+ while (context != null)
{
- addFollowingNodes(context, acc, recurse);
+ context = (context.getNodeType() == Node.ATTRIBUTE_NODE) ?
+ ((Attr) context).getOwnerElement() : context.getParentNode();
+ if (context != null)
+ {
+ cur = context.getNextSibling();
+ while (cur != null)
+ {
+ acc.add(cur);
+ if (recurse)
+ addChildNodes(cur, acc, true);
+ cur = cur.getNextSibling();
+ }
+ }
}
}
}
void addPrecedingNodes(Node context, Collection acc, boolean recurse)
{
- Node cur = context.getPreviousSibling();
+ Node cur = (context.getNodeType() == Node.ATTRIBUTE_NODE) ? null :
+ context.getPreviousSibling();
while (cur != null)
{
acc.add(cur);
if (recurse)
- {
- addChildNodes(cur, acc, true);
- }
+ addChildNodes(cur, acc, true);
cur = cur.getPreviousSibling();
}
if (recurse)
{
- context = (context.getNodeType() == Node.ATTRIBUTE_NODE) ?
- ((Attr) context).getOwnerElement() : context.getParentNode();
- if (context != null)
- {
- addPrecedingNodes(context, acc, recurse);
- }
+ cur = context;
+ cur = (cur.getNodeType() == Node.ATTRIBUTE_NODE) ?
+ ((Attr) cur).getOwnerElement() : cur.getParentNode();
+ if (cur != null)
+ addPrecedingNodes(cur, acc, recurse);
}
}
@@ -399,9 +388,7 @@ public final class Selector
{
Node attr = attrs.item(i);
if (isNamespaceAttribute(attr))
- {
- acc.add(attr);
- }
+ acc.add(attr);
}
}
}
@@ -419,9 +406,7 @@ public final class Selector
int len = tests.length;
List tests2 = new ArrayList(len);
for (int i = 0; i < len; i++)
- {
- tests2.add(tests[i].clone(context));
- }
+ tests2.add(tests[i].clone(context));
return new Selector(axis, tests2);
}
@@ -430,9 +415,7 @@ public final class Selector
for (int i = 0; i < tests.length; i++)
{
if (tests[i].references(var))
- {
- return true;
- }
+ return true;
}
return false;
}
@@ -451,13 +434,9 @@ public final class Selector
case ATTRIBUTE:
if (tests.length == 0 ||
(tests[0] instanceof NameTest))
- {
- buf.append('@');
- }
+ buf.append('@');
else
- {
- buf.append("attribute::");
- }
+ buf.append("attribute::");
break;
case CHILD:
//buf.append("child::");
@@ -481,9 +460,7 @@ public final class Selector
if (tests.length == 0 ||
(tests[0] instanceof NodeTypeTest &&
((NodeTypeTest) tests[0]).type == 0))
- {
- return "..";
- }
+ return "..";
buf.append("parent::");
break;
case PRECEDING:
@@ -496,22 +473,16 @@ public final class Selector
if (tests.length == 0 ||
(tests[0] instanceof NodeTypeTest &&
((NodeTypeTest) tests[0]).type == 0))
- {
- return ".";
- }
+ return ".";
buf.append("self::");
break;
}
if (tests.length == 0)
- {
- buf.append('*');
- }
+ buf.append("[error]");
else
{
for (int i = 0; i < tests.length; i++)
- {
- buf.append(tests[i]);
- }
+ buf.append(tests[i]);
}
return buf.toString();
}
diff --git a/libjava/classpath/gnu/xml/xpath/SubstringFunction.java b/libjava/classpath/gnu/xml/xpath/SubstringFunction.java
index d65c4facb8a..e926f6c7aeb 100644
--- a/libjava/classpath/gnu/xml/xpath/SubstringFunction.java
+++ b/libjava/classpath/gnu/xml/xpath/SubstringFunction.java
@@ -78,31 +78,20 @@ final class SubstringFunction
Object val1 = arg1.evaluate(context, pos, len);
Object val2 = arg2.evaluate(context, pos, len);
String s = _string(context, val1);
- int p = (val2 instanceof Double) ?
- ((Double) val2).intValue() :
- (int) Math.round(_number(context, val2));
- p--;
+ int p = Expr.intValue(val2) - 1;
if (p < 0)
- {
- p = 0;
- }
+ p = 0;
int l = s.length() - p;
if (l <= 0)
- {
- return "";
- }
+ return "";
if (arg3 != null)
{
Object val3 = arg3.evaluate(context, pos, len);
- int v3 = (val3 instanceof Double) ?
- ((Double) val3).intValue() :
- (int) Math.round(_number(context, val3));
+ int v3 = Expr.intValue(val3);
if (v3 < l)
- {
- l = v3;
- }
+ l = v3;
}
return s.substring(p, p + l);
--
cgit v1.2.3