summaryrefslogtreecommitdiffstats
path: root/libjava/classpath/gnu/xml/transform
diff options
context:
space:
mode:
Diffstat (limited to 'libjava/classpath/gnu/xml/transform')
-rw-r--r--libjava/classpath/gnu/xml/transform/AttributeNode.java54
-rw-r--r--libjava/classpath/gnu/xml/transform/Bindings.java22
-rw-r--r--libjava/classpath/gnu/xml/transform/ElementAvailableFunction.java19
-rw-r--r--libjava/classpath/gnu/xml/transform/ElementNode.java157
-rw-r--r--libjava/classpath/gnu/xml/transform/FunctionAvailableFunction.java28
-rw-r--r--libjava/classpath/gnu/xml/transform/LiteralNode.java64
-rw-r--r--libjava/classpath/gnu/xml/transform/MessageNode.java23
-rw-r--r--libjava/classpath/gnu/xml/transform/NamespaceProxy.java77
-rw-r--r--libjava/classpath/gnu/xml/transform/StreamSerializer.java474
-rw-r--r--libjava/classpath/gnu/xml/transform/StrippingInstruction.java73
-rw-r--r--libjava/classpath/gnu/xml/transform/Stylesheet.java375
-rw-r--r--libjava/classpath/gnu/xml/transform/TransformerFactoryImpl.java49
-rw-r--r--libjava/classpath/gnu/xml/transform/TransformerImpl.java240
-rw-r--r--libjava/classpath/gnu/xml/transform/ValueOfNode.java56
14 files changed, 917 insertions, 794 deletions
diff --git a/libjava/classpath/gnu/xml/transform/AttributeNode.java b/libjava/classpath/gnu/xml/transform/AttributeNode.java
index 1e0eb1e961a..bc5bc30c9c1 100644
--- a/libjava/classpath/gnu/xml/transform/AttributeNode.java
+++ b/libjava/classpath/gnu/xml/transform/AttributeNode.java
@@ -1,5 +1,5 @@
/* AttributeNode.java --
- Copyright (C) 2004 Free Software Foundation, Inc.
+ Copyright (C) 2004,2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -75,13 +75,9 @@ final class AttributeNode
namespace.clone(stylesheet),
source);
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;
}
@@ -113,9 +109,7 @@ final class AttributeNode
// Use XPath string-value of fragment
namespaceValue = Expr.stringValue(fragment);
if (namespaceValue.length() == 0)
- {
- namespaceValue = null;
- }
+ namespaceValue = null;
}
String prefix = getPrefix(nameValue);
@@ -124,9 +118,7 @@ final class AttributeNode
if (prefix != null)
{
if (XMLConstants.XML_NS_PREFIX.equals(prefix))
- {
- namespaceValue = XMLConstants.XML_NS_URI;
- }
+ namespaceValue = XMLConstants.XML_NS_URI;
else
{
// Resolve namespace for this prefix
@@ -153,9 +145,7 @@ final class AttributeNode
// Resolve prefix for this namespace
prefix = source.lookupPrefix(namespaceValue);
if (prefix != null)
- {
- nameValue = prefix + ":" + nameValue;
- }
+ nameValue = prefix + ":" + nameValue;
else
{
if (namespaceValue != null)
@@ -196,27 +186,19 @@ final class AttributeNode
if (attrs != null)
{
if (namespace != null)
- {
- attrs.setNamedItemNS(attr);
- }
+ attrs.setNamedItemNS(attr);
else
- {
- attrs.setNamedItem(attr);
- }
+ attrs.setNamedItem(attr);
}
if (children != null)
- {
- children.apply(stylesheet, mode,
- context, pos, len,
- attr, null);
- }
+ children.apply(stylesheet, mode,
+ context, pos, len,
+ attr, null);
}
if (next != null)
- {
- next.apply(stylesheet, mode,
- context, pos, len,
- parent, nextSibling);
- }
+ next.apply(stylesheet, mode,
+ context, pos, len,
+ parent, nextSibling);
}
final String getPrefix(String name)
@@ -241,13 +223,9 @@ final class AttributeNode
public boolean references(QName var)
{
if (name != null && name.references(var))
- {
- return true;
- }
+ return true;
if (namespace != null && namespace.references(var))
- {
- return true;
- }
+ return true;
return super.references(var);
}
diff --git a/libjava/classpath/gnu/xml/transform/Bindings.java b/libjava/classpath/gnu/xml/transform/Bindings.java
index c372ea83091..4ee08322317 100644
--- a/libjava/classpath/gnu/xml/transform/Bindings.java
+++ b/libjava/classpath/gnu/xml/transform/Bindings.java
@@ -78,6 +78,11 @@ public class Bindings
*/
final LinkedList withParameters;
+ /**
+ * Only search globals.
+ */
+ boolean global;
+
Bindings(Stylesheet stylesheet)
{
this.stylesheet = stylesheet;
@@ -136,6 +141,12 @@ public class Bindings
public boolean containsKey(QName name, int type)
{
+ if (global)
+ {
+ Map ctx1 = (Map) variables.getLast();
+ Map ctx2 = (Map) parameters.getLast();
+ return (ctx1.containsKey(name) || ctx2.containsKey(name));
+ }
Iterator i = null;
switch (type)
{
@@ -165,6 +176,17 @@ public class Bindings
public Object get(QName name, Node context, int pos, int len)
{
+ if (global)
+ {
+ Map ctx = (Map) variables.getLast();
+ Object ret = ctx.get(name);
+ if (ret == null)
+ {
+ ctx = (Map) parameters.getLast();
+ ret = ctx.get(name);
+ }
+ return ret;
+ }
//System.err.println("bindings.get: "+name);
//System.err.println("\t"+toString());
Object ret = null;
diff --git a/libjava/classpath/gnu/xml/transform/ElementAvailableFunction.java b/libjava/classpath/gnu/xml/transform/ElementAvailableFunction.java
index 84cb6207af9..aa15981695e 100644
--- a/libjava/classpath/gnu/xml/transform/ElementAvailableFunction.java
+++ b/libjava/classpath/gnu/xml/transform/ElementAvailableFunction.java
@@ -144,8 +144,8 @@ class ElementAvailableFunction
{
return elements.contains(localName) ?
Boolean.TRUE : Boolean.FALSE;
- // TODO extension elements
}
+ // TODO extension elements
return Boolean.FALSE;
}
@@ -153,16 +153,12 @@ class ElementAvailableFunction
{
NamespaceContext n = nsctx;
if (context instanceof NamespaceContext)
- {
- n = (NamespaceContext) context;
- }
+ n = (NamespaceContext) context;
ElementAvailableFunction f = new ElementAvailableFunction(n);
int len = args.size();
List args2 = new ArrayList(len);
for (int i = 0; i < len; i++)
- {
- args2.add(((Expr) args.get(i)).clone(context));
- }
+ args2.add(((Expr) args.get(i)).clone(context));
f.setArguments(args2);
return f;
}
@@ -172,12 +168,15 @@ class ElementAvailableFunction
for (Iterator i = args.iterator(); i.hasNext(); )
{
if (((Expr) i.next()).references(var))
- {
- return true;
- }
+ return true;
}
return false;
}
+ public String toString()
+ {
+ return "element-available(" + args.get(0) + ")";
+ }
+
}
diff --git a/libjava/classpath/gnu/xml/transform/ElementNode.java b/libjava/classpath/gnu/xml/transform/ElementNode.java
index d8f7f6db6db..092c56a4b64 100644
--- a/libjava/classpath/gnu/xml/transform/ElementNode.java
+++ b/libjava/classpath/gnu/xml/transform/ElementNode.java
@@ -82,14 +82,10 @@ final class ElementNode
elementExcludeResultPrefixes = new HashSet();
StringTokenizer st = new StringTokenizer(attr.getNodeValue());
while (st.hasMoreTokens())
- {
- elementExcludeResultPrefixes.add(st.nextToken());
- }
+ elementExcludeResultPrefixes.add(st.nextToken());
}
else
- {
- elementExcludeResultPrefixes = Collections.EMPTY_SET;
- }
+ elementExcludeResultPrefixes = Collections.EMPTY_SET;
}
TemplateNode clone(Stylesheet stylesheet)
@@ -99,19 +95,15 @@ final class ElementNode
namespace.clone(stylesheet),
uas, source);
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
{
Document doc = (parent instanceof Document) ? (Document) parent :
@@ -137,96 +129,70 @@ final class ElementNode
// Use XPath string-value of fragment
namespaceValue = Expr.stringValue(fragment);
if (namespaceValue.length() == 0)
- {
- namespaceValue = null;
- }
- }
-
- String prefix = getPrefix(nameValue);
- if (XMLConstants.XMLNS_ATTRIBUTE.equals(prefix))
- {
- int ci = nameValue.indexOf(':');
- nameValue = nameValue.substring(ci + 1);
+ namespaceValue = null;
}
else
- {
- // Namespace aliasing
- if (prefix == null)
- {
- prefix = "#default";
- }
- String resultPrefix =
- (String) stylesheet.namespaceAliases.get(prefix);
- if (resultPrefix != null)
- {
- if ("#default".equals(resultPrefix))
- {
- resultPrefix = null;
- }
- namespaceValue = source.lookupNamespaceURI(resultPrefix);
- }
- if (prefix == "#default")
+ {
+ String prefix = getPrefix(nameValue);
+ if (XMLConstants.XMLNS_ATTRIBUTE.equals(prefix))
{
- prefix = null;
+ int ci = nameValue.indexOf(':');
+ nameValue = nameValue.substring(ci + 1);
}
- // Look up ordinary namespace for this prefix
- if (namespaceValue == null)
+ else
{
- if (XMLConstants.XML_NS_PREFIX.equals(prefix))
+ // Namespace aliasing
+ if (prefix == null)
+ prefix = "#default";
+ String resultPrefix =
+ (String) stylesheet.namespaceAliases.get(prefix);
+ if (resultPrefix != null)
{
- namespaceValue = XMLConstants.XML_NS_URI;
+ if ("#default".equals(resultPrefix))
+ resultPrefix = null;
+ namespaceValue = source.lookupNamespaceURI(resultPrefix);
}
- else
+ if (prefix == "#default")
+ prefix = null;
+ // Look up ordinary namespace for this prefix
+ if (namespaceValue == null)
{
- // Resolve namespace for this prefix
- namespaceValue = source.lookupNamespaceURI(prefix);
+ if (XMLConstants.XML_NS_PREFIX.equals(prefix))
+ namespaceValue = XMLConstants.XML_NS_URI;
+ else
+ {
+ // Resolve namespace for this prefix
+ namespaceValue = source.lookupNamespaceURI(prefix);
+ }
}
}
- /*if (prefix == null)
- {
- // Resolve prefix for this namespace
- prefix = parent.lookupPrefix(namespaceValue);
- if (prefix != null)
- {
- nameValue = prefix + ":" + nameValue;
- }
- }*/
}
+
// Create element
Element element = (namespaceValue != null) ?
doc.createElementNS(namespaceValue, nameValue) :
- doc.createElement(nameValue);
+ doc.createElement(nameValue);
if (nextSibling != null)
- {
- parent.insertBefore(element, nextSibling);
- }
+ parent.insertBefore(element, nextSibling);
else
- {
- parent.appendChild(element);
- }
+ parent.appendChild(element);
stylesheet.addNamespaceNodes(source, element, doc,
elementExcludeResultPrefixes);
if (uas != null)
{
StringTokenizer st = new StringTokenizer(uas, " ");
while (st.hasMoreTokens())
- {
- addAttributeSet(stylesheet, mode, context, pos, len,
- element, null, st.nextToken());
- }
+ addAttributeSet(stylesheet, mode, context, pos, len,
+ element, null, st.nextToken());
}
if (children != null)
- {
- children.apply(stylesheet, mode,
- context, pos, len,
- element, null);
- }
+ children.apply(stylesheet, mode,
+ context, pos, len,
+ element, null);
if (next != null)
- {
- next.apply(stylesheet, mode,
- context, pos, len,
- parent, nextSibling);
- }
+ next.apply(stylesheet, mode,
+ context, pos, len,
+ parent, nextSibling);
}
final String getPrefix(String name)
@@ -240,41 +206,33 @@ final class ElementNode
Node parent, Node nextSibling, String attributeSet)
throws TransformerException
{
+ stylesheet.bindings.global = true;
for (Iterator i = stylesheet.attributeSets.iterator(); i.hasNext(); )
{
AttributeSet as = (AttributeSet) i.next();
if (!as.name.equals(attributeSet))
- {
- continue;
- }
+ continue;
if (as.uas != null)
{
StringTokenizer st = new StringTokenizer(as.uas, " ");
while (st.hasMoreTokens())
- {
- addAttributeSet(stylesheet, mode, context, pos, len,
- parent, nextSibling, st.nextToken());
- }
+ addAttributeSet(stylesheet, mode, context, pos, len,
+ parent, nextSibling, st.nextToken());
}
if (as.children != null)
- {
- as.children.apply(stylesheet, mode,
- context, pos, len,
- parent, nextSibling);
- }
+ as.children.apply(stylesheet, mode,
+ context, pos, len,
+ parent, nextSibling);
}
+ stylesheet.bindings.global = false;
}
public boolean references(QName var)
{
if (name != null && name.references(var))
- {
- return true;
- }
+ return true;
if (namespace != null && namespace.references(var))
- {
- return true;
- }
+ return true;
return super.references(var);
}
@@ -283,6 +241,11 @@ final class ElementNode
StringBuffer buf = new StringBuffer(getClass().getName());
buf.append('[');
buf.append("name=");
+ if (namespace != null)
+ {
+ buf.append(",namespace=");
+ buf.append(namespace);
+ }
buf.append(name);
if (uas != null)
{
diff --git a/libjava/classpath/gnu/xml/transform/FunctionAvailableFunction.java b/libjava/classpath/gnu/xml/transform/FunctionAvailableFunction.java
index 7daf7ea3f70..ab86401d0e4 100644
--- a/libjava/classpath/gnu/xml/transform/FunctionAvailableFunction.java
+++ b/libjava/classpath/gnu/xml/transform/FunctionAvailableFunction.java
@@ -147,11 +147,16 @@ class FunctionAvailableFunction
uri = nsctx.getNamespaceURI(prefix);
if (uri == null)
{
- return xsltFunctions.contains(localName) ||
- xpathFunctions.contains(localName) ?
+ return (xpathFunctions.contains(localName) ||
+ xsltFunctions.contains(localName)) ?
Boolean.TRUE : Boolean.FALSE;
- // TODO extension functions
}
+ else if (Stylesheet.XSL_NS.equals(uri))
+ {
+ return xsltFunctions.contains(localName) ?
+ Boolean.TRUE : Boolean.FALSE;
+ }
+ // TODO extension functions
return Boolean.FALSE;
}
@@ -159,16 +164,12 @@ class FunctionAvailableFunction
{
NamespaceContext n = nsctx;
if (context instanceof NamespaceContext)
- {
- n = (NamespaceContext) context;
- }
+ n = (NamespaceContext) context;
FunctionAvailableFunction f = new FunctionAvailableFunction(n);
int len = args.size();
List args2 = new ArrayList(len);
for (int i = 0; i < len; i++)
- {
- args2.add(((Expr) args.get(i)).clone(context));
- }
+ args2.add(((Expr) args.get(i)).clone(context));
f.setArguments(args2);
return f;
}
@@ -178,12 +179,15 @@ class FunctionAvailableFunction
for (Iterator i = args.iterator(); i.hasNext(); )
{
if (((Expr) i.next()).references(var))
- {
- return true;
- }
+ return true;
}
return false;
}
+ public String toString()
+ {
+ return "function-available(" + args.get(0) + ")";
+ }
+
}
diff --git a/libjava/classpath/gnu/xml/transform/LiteralNode.java b/libjava/classpath/gnu/xml/transform/LiteralNode.java
index 0be2b35c84d..453c22c5e0d 100644
--- a/libjava/classpath/gnu/xml/transform/LiteralNode.java
+++ b/libjava/classpath/gnu/xml/transform/LiteralNode.java
@@ -1,5 +1,5 @@
/* LiteralNode.java --
- Copyright (C) 2004 Free Software Foundation, Inc.
+ Copyright (C) 2004,2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -77,38 +77,28 @@ final class LiteralNode
elementExcludeResultPrefixes = new HashSet();
StringTokenizer st = new StringTokenizer(attr.getNodeValue());
while (st.hasMoreTokens())
- {
- elementExcludeResultPrefixes.add(st.nextToken());
- }
+ elementExcludeResultPrefixes.add(st.nextToken());
}
else
- {
- elementExcludeResultPrefixes = Collections.EMPTY_SET;
- }
+ elementExcludeResultPrefixes = Collections.EMPTY_SET;
}
else
- {
- elementExcludeResultPrefixes = null;
- }
+ elementExcludeResultPrefixes = null;
}
TemplateNode clone(Stylesheet stylesheet)
{
TemplateNode ret = new LiteralNode(source);
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
{
Node result = null;
@@ -127,17 +117,13 @@ final class LiteralNode
{
String prefix = source.getPrefix();
if (prefix == null)
- {
- prefix = "#default";
- }
+ prefix = "#default";
String resultPrefix =
(String) stylesheet.namespaceAliases.get(prefix);
if (resultPrefix != null)
{
if ("#default".equals(resultPrefix))
- {
- resultPrefix = null;
- }
+ resultPrefix = null;
String uri = source.lookupNamespaceURI(resultPrefix);
String name = source.getNodeName();
// Create a new element node in the result document
@@ -189,33 +175,23 @@ final class LiteralNode
result = result2;
}
if (nextSibling != null)
- {
- parent.insertBefore(result, nextSibling);
- }
+ parent.insertBefore(result, nextSibling);
else
- {
- parent.appendChild(result);
- }
+ parent.appendChild(result);
if (nodeType == Node.ELEMENT_NODE)
- {
- stylesheet.addNamespaceNodes(source, result, doc,
- elementExcludeResultPrefixes);
- }
+ stylesheet.addNamespaceNodes(source, result, doc,
+ elementExcludeResultPrefixes);
// children
if (children != null)
- {
- children.apply(stylesheet, mode,
- context, pos, len,
- result, null);
- }
+ children.apply(stylesheet, mode,
+ context, pos, len,
+ result, null);
}
// next sibling
if (next != null)
- {
- next.apply(stylesheet, mode,
- context, pos, len,
- parent, nextSibling);
- }
+ next.apply(stylesheet, mode,
+ context, pos, len,
+ parent, nextSibling);
}
public String toString()
diff --git a/libjava/classpath/gnu/xml/transform/MessageNode.java b/libjava/classpath/gnu/xml/transform/MessageNode.java
index 1df716836e7..e8e07c6da29 100644
--- a/libjava/classpath/gnu/xml/transform/MessageNode.java
+++ b/libjava/classpath/gnu/xml/transform/MessageNode.java
@@ -1,5 +1,5 @@
/* MessageNode.java --
- Copyright (C) 2004 Free Software Foundation, Inc.
+ Copyright (C) 2004,2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -37,6 +37,7 @@ exception statement from your version. */
package gnu.xml.transform;
+import java.util.logging.Logger;
import javax.xml.namespace.QName;
import javax.xml.transform.TransformerException;
import org.w3c.dom.Document;
@@ -53,6 +54,8 @@ final class MessageNode
extends TemplateNode
{
+ static final Logger logger = Logger.getLogger("gnu.xml.transform");
+
final boolean terminate;
MessageNode(boolean terminate)
@@ -64,13 +67,9 @@ final class MessageNode
{
TemplateNode ret = new MessageNode(terminate);
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;
}
@@ -86,16 +85,12 @@ final class MessageNode
DocumentFragment fragment = doc.createDocumentFragment();
children.apply(stylesheet, mode, context, pos, len, fragment, null);
String message = Expr.stringValue(fragment);
- System.err.println(message);
+ logger.info(message);
if (terminate)
- {
- stylesheet.terminated = true;
- }
+ stylesheet.terminated = true;
}
if (next != null && !terminate)
- {
- next.apply(stylesheet, mode, context, pos, len, parent, nextSibling);
- }
+ next.apply(stylesheet, mode, context, pos, len, parent, nextSibling);
}
}
diff --git a/libjava/classpath/gnu/xml/transform/NamespaceProxy.java b/libjava/classpath/gnu/xml/transform/NamespaceProxy.java
new file mode 100644
index 00000000000..b3c233cd7a5
--- /dev/null
+++ b/libjava/classpath/gnu/xml/transform/NamespaceProxy.java
@@ -0,0 +1,77 @@
+/* NamespaceProxy.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 java.util.Collections;
+import java.util.Iterator;
+import javax.xml.namespace.NamespaceContext;
+import org.w3c.dom.Node;
+
+/**
+ * A namespace context using a DOM node to resolve the namespace.
+ *
+ * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
+ */
+class NamespaceProxy
+ implements NamespaceContext
+{
+
+ private final Node node;
+
+ NamespaceProxy(Node node)
+ {
+ this.node = node;
+ }
+
+ public String getNamespaceURI(String prefix)
+ {
+ return (node == null) ? null : node.lookupNamespaceURI(prefix);
+ }
+
+ public String getPrefix(String namespaceURI)
+ {
+ return (node == null) ? null : node.lookupPrefix(namespaceURI);
+ }
+
+ public Iterator getPrefixes(String namespaceURI)
+ {
+ // TODO
+ return Collections.singleton(getPrefix(namespaceURI)).iterator();
+ }
+
+}
diff --git a/libjava/classpath/gnu/xml/transform/StreamSerializer.java b/libjava/classpath/gnu/xml/transform/StreamSerializer.java
index 74b10057c12..fb8b1a601bc 100644
--- a/libjava/classpath/gnu/xml/transform/StreamSerializer.java
+++ b/libjava/classpath/gnu/xml/transform/StreamSerializer.java
@@ -1,5 +1,5 @@
/* StreamSerializer.java --
- Copyright (C) 2004 Free Software Foundation, Inc.
+ Copyright (C) 2004,2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -49,6 +49,8 @@ import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedList;
import java.util.Map;
import javax.xml.XMLConstants;
import org.w3c.dom.Attr;
@@ -149,16 +151,25 @@ public class StreamSerializer
HTML_BOOLEAN_ATTRIBUTES.put("script", set);
}
+ // HTML namespace URIs
+ static final HashSet HTML_URIS = new HashSet();
+ static {
+ HTML_URIS.add("http://www.w3.org/1999/xhtml");
+ }
+
protected final String encoding;
final Charset charset;
final CharsetEncoder encoder;
final int mode;
- final Map namespaces;
+ final LinkedList namespaces;
protected String eol;
Collection cdataSectionElements = Collections.EMPTY_SET;
protected boolean discardDefaultContent;
protected boolean xmlDeclaration = true;
+
+ // has a META element with the encoding been added?
+ private boolean htmlEncoded;
public StreamSerializer()
{
@@ -174,14 +185,12 @@ public class StreamSerializer
{
this.mode = mode;
if (encoding == null)
- {
- encoding = "UTF-8";
- }
+ encoding = (mode == Stylesheet.OUTPUT_HTML) ? "ISO-8859-1" : "UTF-8";
this.encoding = encoding.intern();
charset = Charset.forName(this.encoding);
encoder = charset.newEncoder();
this.eol = (eol != null) ? eol : System.getProperty("line.separator");
- namespaces = new HashMap();
+ namespaces = new LinkedList();
}
void setCdataSectionElements(Collection c)
@@ -212,18 +221,14 @@ public class StreamSerializer
throws IOException
{
if (out == null)
- {
- throw new NullPointerException("no output stream");
- }
+ throw new NullPointerException("no output stream");
+ htmlEncoded = false;
String value, prefix;
Node children;
String uri = node.getNamespaceURI();
- boolean defined = false;
short nt = node.getNodeType();
if (convertToCdata && nt == Node.TEXT_NODE)
- {
- nt = Node.CDATA_SECTION_NODE;
- }
+ nt = Node.CDATA_SECTION_NODE;
switch (nt)
{
case Node.ATTRIBUTE_NODE:
@@ -233,27 +238,28 @@ public class StreamSerializer
(prefix != null && prefix.startsWith("xmlns:")))
{
String nsuri = node.getNodeValue();
- if (isDefined(nsuri))
- {
- break;
- }
+ if (isDefined(nsuri, prefix))
+ break;
String name = node.getLocalName();
if (name == null)
{
+ // Namespace-unaware
name = node.getNodeName();
+ int ci = name.indexOf(':');
+ if (ci != -1)
+ name = name.substring(ci + 1);
}
define(nsuri, name);
}
- else if (uri != null && !isDefined(uri))
+ else if (uri != null && !isDefined(uri, prefix))
{
prefix = define(uri, prefix);
String nsname = (prefix == null) ? "xmlns" : "xmlns:" + prefix;
out.write(SPACE);
out.write(encodeText(nsname));
out.write(EQ);
- String nsvalue = "'" + encode(uri, true, true) + "'";
+ String nsvalue = "\"" + encode(uri, true, true) + "\"";
out.write(nsvalue.getBytes(encoding));
- defined = true;
}
out.write(SPACE);
String a_nodeName = node.getNodeName();
@@ -262,27 +268,26 @@ public class StreamSerializer
if (mode == Stylesheet.OUTPUT_HTML &&
a_nodeName.equals(a_nodeValue) &&
isHTMLBoolean((Attr) node, a_nodeName))
- {
- break;
- }
+ break;
out.write(EQ);
- value = "'" + encode(a_nodeValue, true, true) + "'";
+ value = "\"" + encode(a_nodeValue, true, true) + "\"";
out.write(encodeText(value));
break;
case Node.ELEMENT_NODE:
+ pushNamespaceContext();
value = node.getNodeName();
out.write(BRA);
out.write(encodeText(value));
- if (uri != null && !isDefined(uri))
+ prefix = node.getPrefix();
+ if (uri != null && !isDefined(uri, prefix))
{
- prefix = define(uri, node.getPrefix());
+ prefix = define(uri, prefix);
String nsname = (prefix == null) ? "xmlns" : "xmlns:" + prefix;
out.write(SPACE);
out.write(encodeText(nsname));
out.write(EQ);
- String nsvalue = "'" + encode(uri, true, true) + "'";
+ String nsvalue = "\"" + encode(uri, true, true) + "\"";
out.write(encodeText(nsvalue));
- defined = true;
}
NamedNodeMap attrs = node.getAttributes();
if (attrs != null)
@@ -296,9 +301,7 @@ public class StreamSerializer
// NOOP
}
else
- {
- serialize(attr, out, false);
- }
+ serialize(attr, out, false);
}
}
convertToCdata = cdataSectionElements.contains(value);
@@ -317,27 +320,35 @@ public class StreamSerializer
out.write(encodeText(value));
out.write(KET);
}
+ popNamespaceContext();
break;
case Node.TEXT_NODE:
value = node.getNodeValue();
if (!"yes".equals(node.getUserData("disable-output-escaping")))
- {
- value = encode(value, false, false);
- }
+ value = encode(value, false, false);
out.write(encodeText(value));
break;
case Node.CDATA_SECTION_NODE:
- value = "<![CDATA[" + node.getNodeValue() + "]]>";
- out.write(encodeText(value));
+ value = node.getNodeValue();
+ // Where any instanceof of ]]> occur, split into multiple CDATA
+ // sections
+ int bbk = value.indexOf("]]>");
+ while (bbk != -1)
+ {
+ String head = value.substring(0, bbk + 2);
+ out.write(encodeText("<![CDATA[" + head + "]]>"));
+ value = value.substring(bbk + 2);
+ bbk = value.indexOf("]]>");
+ }
+ // Write final tail value
+ out.write(encodeText("<![CDATA[" + value + "]]>"));
break;
case Node.COMMENT_NODE:
value = "<!--" + node.getNodeValue() + "-->";
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("&lt;");
}
else if (c == '>')
{
if (buf == null)
- {
- buf = new StringBuffer(text.substring(0, i));
- }
+ buf = new StringBuffer(text.substring(0, i));
buf.append("&gt;");
}
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("&amp;");
}
}
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 &apos;, use character entity ref
buf.append("&#x27;");
@@ -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("&quot;");
}
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 <a href='mailto:dog@gnu.org'>Chris Burdess</a>
+ */
+class StrippingInstruction
+{
+
+ final NameTest element;
+ final int precedence;
+
+ StrippingInstruction(NameTest element, int precedence)
+ {
+ this.element = element;
+ this.precedence = precedence;
+ }
+
+ /**
+ * Returns the <i>default priority</i> 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 [<stylesheet> [<input> [<output>]]]
+ */
+ 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();
}
OpenPOWER on IntegriCloud