Initial revision
From-SVN: r102074
This commit is contained in:
@@ -0,0 +1,328 @@
|
||||
/* AbstractNumberNode.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.transform;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import javax.xml.namespace.QName;
|
||||
import javax.xml.transform.TransformerException;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.DocumentFragment;
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.Text;
|
||||
import gnu.xml.xpath.Expr;
|
||||
|
||||
/**
|
||||
* A template node representing the XSL <code>number</code> instruction.
|
||||
*
|
||||
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
|
||||
*/
|
||||
abstract class AbstractNumberNode
|
||||
extends TemplateNode
|
||||
{
|
||||
|
||||
static final int ALPHABETIC = 0;
|
||||
static final int TRADITIONAL = 1;
|
||||
|
||||
final TemplateNode format;
|
||||
final String lang;
|
||||
final int letterValue;
|
||||
final String groupingSeparator;
|
||||
final int groupingSize;
|
||||
|
||||
AbstractNumberNode(TemplateNode format, String lang,
|
||||
int letterValue, String groupingSeparator,
|
||||
int groupingSize)
|
||||
{
|
||||
this.format = format;
|
||||
this.lang = lang;
|
||||
this.letterValue = letterValue;
|
||||
this.groupingSeparator = groupingSeparator;
|
||||
this.groupingSize = groupingSize;
|
||||
}
|
||||
|
||||
void doApply(Stylesheet stylesheet, QName mode,
|
||||
Node context, int pos, int len,
|
||||
Node parent, Node nextSibling)
|
||||
throws TransformerException
|
||||
{
|
||||
Document doc = (parent instanceof Document) ? (Document) parent :
|
||||
parent.getOwnerDocument();
|
||||
DocumentFragment fragment = doc.createDocumentFragment();
|
||||
format.apply(stylesheet, mode, context, pos, len, fragment, null);
|
||||
String f = Expr._string(context, Collections.singleton(fragment));
|
||||
String value = format(f, compute(stylesheet, context, pos, len));
|
||||
Text text = doc.createTextNode(value);
|
||||
if (nextSibling != null)
|
||||
{
|
||||
parent.insertBefore(text, nextSibling);
|
||||
}
|
||||
else
|
||||
{
|
||||
parent.appendChild(text);
|
||||
}
|
||||
// xsl:number doesn't process children
|
||||
if (next != null)
|
||||
{
|
||||
next.apply(stylesheet, mode,
|
||||
context, pos, len,
|
||||
parent, nextSibling);
|
||||
}
|
||||
}
|
||||
|
||||
String format(String format, int[] number)
|
||||
{
|
||||
if (number.length == 0)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
int start = 0, end = 0, len = format.length(); // region of format
|
||||
// Tokenize
|
||||
List tokens = new ArrayList((number.length * 2) + 1);
|
||||
List types = new ArrayList(tokens.size());
|
||||
while (end < len)
|
||||
{
|
||||
while (end < len && !isAlphanumeric(format.charAt(end)))
|
||||
{
|
||||
end++;
|
||||
}
|
||||
if (end > start)
|
||||
{
|
||||
tokens.add(format.substring(start, end));
|
||||
types.add(Boolean.FALSE);
|
||||
}
|
||||
start = end;
|
||||
while (end < len && isAlphanumeric(format.charAt(end)))
|
||||
{
|
||||
end++;
|
||||
}
|
||||
if (end > start)
|
||||
{
|
||||
tokens.add(format.substring(start, end));
|
||||
types.add(Boolean.TRUE);
|
||||
}
|
||||
start = end;
|
||||
}
|
||||
// Process tokens
|
||||
StringBuffer buf = new StringBuffer();
|
||||
len = tokens.size();
|
||||
int pos = 0;
|
||||
for (int i = 0; i < len; i++)
|
||||
{
|
||||
String token = (i < 0) ? "." : (String) tokens.get(i);
|
||||
boolean alpha = (i < 0) ? true :
|
||||
((Boolean) types.get(i)).booleanValue();
|
||||
if (!alpha)
|
||||
{
|
||||
buf.append(token);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (pos < number.length)
|
||||
{
|
||||
format(buf, number[pos++], token);
|
||||
if (((i + 1 == len) || (i + 2 == len)) &&
|
||||
(pos < number.length))
|
||||
{
|
||||
// More numbers than tokens, reuse last token
|
||||
i -= 2;
|
||||
}
|
||||
}
|
||||
if (pos == number.length && i < (len - 2))
|
||||
{
|
||||
// No more numbers. Skip to the end...
|
||||
i = len - 2;
|
||||
if (((Boolean) types.get(i + 1)).booleanValue())
|
||||
{
|
||||
// number formatting token, ignore
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//System.err.println("format: '"+format+"' "+asList(number)+" = '"+buf.toString()+"'");
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
/*List asList(int[] number)
|
||||
{
|
||||
List l = new ArrayList();
|
||||
for (int i = 0; i < number.length; i++)
|
||||
l.add(new Integer(number[i]));
|
||||
return l;
|
||||
}*/
|
||||
|
||||
void format(StringBuffer buf, int number, String formatToken)
|
||||
{
|
||||
int len = formatToken.length();
|
||||
char c = formatToken.charAt(len - 1);
|
||||
if (Character.digit(c, 10) == 1)
|
||||
{
|
||||
// Check preceding characters
|
||||
for (int i = len - 2; i >= 0; i--)
|
||||
{
|
||||
if (formatToken.charAt(i) != (c - 1))
|
||||
{
|
||||
format(buf, number, "1");
|
||||
return;
|
||||
}
|
||||
}
|
||||
// Decimal representation
|
||||
String val = Integer.toString(number);
|
||||
for (int d = len - val.length(); d > 0; d--)
|
||||
{
|
||||
buf.append('0');
|
||||
}
|
||||
buf.append(val);
|
||||
}
|
||||
else if ("A".equals(formatToken))
|
||||
{
|
||||
buf.append(alphabetic('@', number));
|
||||
}
|
||||
else if ("a".equals(formatToken))
|
||||
{
|
||||
buf.append(alphabetic('`', number));
|
||||
}
|
||||
else if ("i".equals(formatToken))
|
||||
{
|
||||
buf.append(roman(false, number));
|
||||
}
|
||||
else if ("I".equals(formatToken))
|
||||
{
|
||||
buf.append(roman(true, number));
|
||||
}
|
||||
else
|
||||
{
|
||||
// Unknown numbering sequence
|
||||
format(buf, number, "1");
|
||||
}
|
||||
}
|
||||
|
||||
static final boolean isAlphanumeric(char c)
|
||||
{
|
||||
switch (Character.getType(c))
|
||||
{
|
||||
case Character.DECIMAL_DIGIT_NUMBER: // Nd
|
||||
case Character.LETTER_NUMBER: // Nl
|
||||
case Character.OTHER_NUMBER: // No
|
||||
case Character.UPPERCASE_LETTER: // Lu
|
||||
case Character.LOWERCASE_LETTER: // Ll
|
||||
case Character.TITLECASE_LETTER: // Lt
|
||||
case Character.MODIFIER_LETTER: // Lm
|
||||
case Character.OTHER_LETTER: // Lo
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static final String alphabetic(char offset, int number)
|
||||
{
|
||||
StringBuffer buf = new StringBuffer();
|
||||
while (number > 0)
|
||||
{
|
||||
int r = number % 26;
|
||||
number = number / 26;
|
||||
buf.insert(0, (char) (offset + r));
|
||||
}
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
static final int[] roman_numbers = {1, 5, 10, 50, 100, 500, 1000};
|
||||
static final char[] roman_chars = {'i', 'v', 'x', 'l', 'c', 'd', 'm'};
|
||||
|
||||
static final String roman(boolean upper, int number)
|
||||
{
|
||||
StringBuffer buf = new StringBuffer();
|
||||
for (int pos = roman_numbers.length - 1; pos >= 0; pos -= 2)
|
||||
{
|
||||
int f = number / roman_numbers[pos];
|
||||
if (f != 0)
|
||||
{
|
||||
number = number % (f * roman_numbers[pos]);
|
||||
}
|
||||
if (f > 4 && f < 9)
|
||||
{
|
||||
buf.append(roman_chars[pos + 1]);
|
||||
f -= 5;
|
||||
}
|
||||
if (f == 4)
|
||||
{
|
||||
buf.append(roman_chars[pos]);
|
||||
buf.append(roman_chars[pos + 1]);
|
||||
}
|
||||
else if (f == 9)
|
||||
{
|
||||
buf.append(roman_chars[pos]);
|
||||
buf.append(roman_chars[pos + 2]);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (; f > 0; f--)
|
||||
{
|
||||
buf.append(roman_chars[pos]);
|
||||
}
|
||||
}
|
||||
}
|
||||
return upper ? buf.toString().toUpperCase() : buf.toString();
|
||||
}
|
||||
|
||||
abstract int[] compute(Stylesheet stylesheet, Node context, int pos, int len)
|
||||
throws TransformerException;
|
||||
|
||||
public boolean references(QName var)
|
||||
{
|
||||
if (format.references(var))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return super.references(var);
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
StringBuffer buf = new StringBuffer(getClass().getName());
|
||||
buf.append('[');
|
||||
buf.append("format=");
|
||||
buf.append(format);
|
||||
buf.append(']');
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
/* ApplyImportsNode.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.transform;
|
||||
|
||||
import javax.xml.namespace.QName;
|
||||
import javax.xml.transform.TransformerException;
|
||||
import org.w3c.dom.Node;
|
||||
|
||||
/**
|
||||
* A template node representing an XSLT <code>apply-imports</code> instruction.
|
||||
*
|
||||
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
|
||||
*/
|
||||
final class ApplyImportsNode
|
||||
extends TemplateNode
|
||||
{
|
||||
|
||||
TemplateNode clone(Stylesheet stylesheet)
|
||||
{
|
||||
TemplateNode ret = new ApplyImportsNode();
|
||||
if (children != null)
|
||||
{
|
||||
ret.children = children.clone(stylesheet);
|
||||
}
|
||||
if (next != null)
|
||||
{
|
||||
ret.next = next.clone(stylesheet);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void doApply(Stylesheet stylesheet, QName mode,
|
||||
Node context, int pos, int len,
|
||||
Node parent, Node nextSibling)
|
||||
throws TransformerException
|
||||
{
|
||||
TemplateNode t = stylesheet.getTemplate(mode, context, true);
|
||||
if (t != null)
|
||||
{
|
||||
t.apply(stylesheet, mode, context, pos, len,
|
||||
parent, nextSibling);
|
||||
}
|
||||
if (next != null)
|
||||
{
|
||||
next.apply(stylesheet, mode, context, pos, len,
|
||||
parent, nextSibling);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,235 @@
|
||||
/* ApplyTemplatesNode.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.transform;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import javax.xml.namespace.QName;
|
||||
import javax.xml.transform.TransformerException;
|
||||
import org.w3c.dom.Node;
|
||||
import gnu.xml.xpath.Expr;
|
||||
|
||||
/**
|
||||
* A template node representing the XSL <code>apply-templates</code>
|
||||
* instruction.
|
||||
*
|
||||
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
|
||||
*/
|
||||
final class ApplyTemplatesNode
|
||||
extends TemplateNode
|
||||
{
|
||||
|
||||
final Expr select;
|
||||
final QName mode;
|
||||
final List sortKeys;
|
||||
final List withParams;
|
||||
final boolean isDefault;
|
||||
|
||||
ApplyTemplatesNode(Expr select, QName mode,
|
||||
List sortKeys, List withParams, boolean isDefault)
|
||||
{
|
||||
this.select = select;
|
||||
this.mode = mode;
|
||||
this.sortKeys = sortKeys;
|
||||
this.withParams = withParams;
|
||||
this.isDefault = isDefault;
|
||||
}
|
||||
|
||||
TemplateNode clone(Stylesheet stylesheet)
|
||||
{
|
||||
int len = sortKeys.size();
|
||||
List sortKeys2 = new ArrayList(len);
|
||||
for (int i = 0; i < len; i++)
|
||||
{
|
||||
sortKeys2.add(((Key) sortKeys.get(i)).clone(stylesheet));
|
||||
}
|
||||
len = withParams.size();
|
||||
List withParams2 = new ArrayList(len);
|
||||
for (int i = 0; i < len; i++)
|
||||
{
|
||||
withParams2.add(((WithParam) withParams.get(i)).clone(stylesheet));
|
||||
}
|
||||
TemplateNode ret = new ApplyTemplatesNode(select.clone(stylesheet),
|
||||
mode, sortKeys2, withParams2,
|
||||
isDefault);
|
||||
if (children != null)
|
||||
{
|
||||
ret.children = children.clone(stylesheet);
|
||||
}
|
||||
if (next != null)
|
||||
{
|
||||
ret.next = next.clone(stylesheet);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void doApply(Stylesheet stylesheet, QName mode,
|
||||
Node context, int pos, int len,
|
||||
Node parent, Node nextSibling)
|
||||
throws TransformerException
|
||||
{
|
||||
Object ret = select.evaluate(context, pos, len);
|
||||
if (ret != null && ret instanceof Collection)
|
||||
{
|
||||
if (withParams != null)
|
||||
{
|
||||
// compute the parameter values
|
||||
LinkedList values = new LinkedList();
|
||||
for (Iterator i = withParams.iterator(); i.hasNext(); )
|
||||
{
|
||||
WithParam p = (WithParam) i.next();
|
||||
Object value = p.getValue(stylesheet, mode, context, pos, len);
|
||||
Object[] pair = new Object[2];
|
||||
pair[0] = p.name;
|
||||
pair[1] = value;
|
||||
values.add(pair);
|
||||
}
|
||||
// push the parameter context
|
||||
stylesheet.bindings.push(Bindings.WITH_PARAM);
|
||||
// set the parameters
|
||||
for (Iterator i = values.iterator(); i.hasNext(); )
|
||||
{
|
||||
Object[] pair = (Object[]) i.next();
|
||||
QName name = (QName) pair[0];
|
||||
Object value = pair[1];
|
||||
stylesheet.bindings.set(name, value, Bindings.WITH_PARAM);
|
||||
}
|
||||
}
|
||||
Collection ns = (Collection) ret;
|
||||
List nodes = new ArrayList(ns);
|
||||
if (sortKeys != null)
|
||||
{
|
||||
for (Iterator i = sortKeys.iterator(); i.hasNext(); )
|
||||
{
|
||||
SortKey sortKey = (SortKey) i.next();
|
||||
sortKey.init(stylesheet, mode, context, pos, len, parent,
|
||||
nextSibling);
|
||||
}
|
||||
Collections.sort(nodes, new XSLComparator(sortKeys));
|
||||
}
|
||||
else
|
||||
{
|
||||
Collections.sort(nodes, documentOrderComparator);
|
||||
}
|
||||
int l = nodes.size();
|
||||
QName effectiveMode = isDefault ? mode : this.mode;
|
||||
for (int i = 0; i < l; i++)
|
||||
{
|
||||
Node node = (Node) nodes.get(i);
|
||||
TemplateNode t = stylesheet.getTemplate(effectiveMode, node,
|
||||
false);
|
||||
if (t != null)
|
||||
{
|
||||
stylesheet.current = node;
|
||||
t.apply(stylesheet, effectiveMode, node, i + 1, l,
|
||||
parent, nextSibling);
|
||||
}
|
||||
}
|
||||
if (withParams != null)
|
||||
{
|
||||
// pop the variable context
|
||||
stylesheet.bindings.pop(Bindings.WITH_PARAM);
|
||||
}
|
||||
}
|
||||
// apply-templates doesn't have processable children
|
||||
if (next != null)
|
||||
{
|
||||
next.apply(stylesheet, mode,
|
||||
context, pos, len,
|
||||
parent, nextSibling);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean references(QName var)
|
||||
{
|
||||
if (select != null && select.references(var))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (withParams != null)
|
||||
{
|
||||
for (Iterator i = withParams.iterator(); i.hasNext(); )
|
||||
{
|
||||
if (((WithParam) i.next()).references(var))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (sortKeys != null)
|
||||
{
|
||||
for (Iterator i = sortKeys.iterator(); i.hasNext(); )
|
||||
{
|
||||
if (((SortKey) i.next()).references(var))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return super.references(var);
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
StringBuffer buf = new StringBuffer(getClass().getName());
|
||||
buf.append('[');
|
||||
boolean o = false;
|
||||
if (select != null)
|
||||
{
|
||||
buf.append("select=");
|
||||
buf.append(select);
|
||||
o = true;
|
||||
}
|
||||
if (mode != null)
|
||||
{
|
||||
if (o)
|
||||
{
|
||||
buf.append(',');
|
||||
}
|
||||
buf.append("mode=");
|
||||
buf.append(mode);
|
||||
}
|
||||
buf.append(']');
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,264 @@
|
||||
/* AttributeNode.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.transform;
|
||||
|
||||
import javax.xml.XMLConstants;
|
||||
import javax.xml.namespace.QName;
|
||||
import javax.xml.transform.TransformerException;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.DocumentFragment;
|
||||
import org.w3c.dom.Attr;
|
||||
import org.w3c.dom.NamedNodeMap;
|
||||
import org.w3c.dom.Node;
|
||||
import gnu.xml.xpath.Expr;
|
||||
|
||||
/**
|
||||
* A template node representing an XSL <code>attribute</code> instruction.
|
||||
*
|
||||
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
|
||||
*/
|
||||
final class AttributeNode
|
||||
extends TemplateNode
|
||||
{
|
||||
|
||||
final TemplateNode name;
|
||||
final TemplateNode namespace;
|
||||
final Node source;
|
||||
|
||||
AttributeNode(TemplateNode name,
|
||||
TemplateNode namespace, Node source)
|
||||
{
|
||||
this.name = name;
|
||||
this.namespace = namespace;
|
||||
this.source = source;
|
||||
}
|
||||
|
||||
TemplateNode clone(Stylesheet stylesheet)
|
||||
{
|
||||
TemplateNode ret = new AttributeNode(name.clone(stylesheet),
|
||||
(namespace == null) ? null :
|
||||
namespace.clone(stylesheet),
|
||||
source);
|
||||
if (children != null)
|
||||
{
|
||||
ret.children = children.clone(stylesheet);
|
||||
}
|
||||
if (next != null)
|
||||
{
|
||||
ret.next = next.clone(stylesheet);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void doApply(Stylesheet stylesheet, QName mode,
|
||||
Node context, int pos, int len,
|
||||
Node parent, Node nextSibling)
|
||||
throws TransformerException
|
||||
{
|
||||
Document doc = (parent instanceof Document) ? (Document) parent :
|
||||
parent.getOwnerDocument();
|
||||
// Create a document fragment to hold the name
|
||||
DocumentFragment fragment = doc.createDocumentFragment();
|
||||
// Apply name to the fragment
|
||||
name.apply(stylesheet, mode,
|
||||
context, pos, len,
|
||||
fragment, null);
|
||||
// Use XPath string-value of fragment
|
||||
String nameValue = Expr.stringValue(fragment);
|
||||
|
||||
String namespaceValue = null;
|
||||
if (namespace != null)
|
||||
{
|
||||
// Create a document fragment to hold the namespace
|
||||
fragment = doc.createDocumentFragment();
|
||||
// Apply namespace to the fragment
|
||||
namespace.apply(stylesheet, mode,
|
||||
context, pos, len,
|
||||
fragment, null);
|
||||
// Use XPath string-value of fragment
|
||||
namespaceValue = Expr.stringValue(fragment);
|
||||
if (namespaceValue.length() == 0)
|
||||
{
|
||||
namespaceValue = null;
|
||||
}
|
||||
}
|
||||
|
||||
String prefix = getPrefix(nameValue);
|
||||
if (namespaceValue == null)
|
||||
{
|
||||
if (prefix != null)
|
||||
{
|
||||
if (XMLConstants.XML_NS_PREFIX.equals(prefix))
|
||||
{
|
||||
namespaceValue = XMLConstants.XML_NS_URI;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Resolve namespace for this prefix
|
||||
namespaceValue = source.lookupNamespaceURI(prefix);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (prefix != null)
|
||||
{
|
||||
String ns2 = source.lookupNamespaceURI(prefix);
|
||||
if (ns2 != null && !ns2.equals(namespaceValue))
|
||||
{
|
||||
// prefix clashes, reset it
|
||||
prefix = null;
|
||||
int ci = nameValue.indexOf(':');
|
||||
nameValue = nameValue.substring(ci + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (prefix == null)
|
||||
{
|
||||
// Resolve prefix for this namespace
|
||||
prefix = source.lookupPrefix(namespaceValue);
|
||||
if (prefix != null)
|
||||
{
|
||||
nameValue = prefix + ":" + nameValue;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (namespaceValue != null)
|
||||
{
|
||||
// Must invent a prefix
|
||||
prefix = inventPrefix(parent);
|
||||
nameValue = prefix + ":" + nameValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
NamedNodeMap attrs = parent.getAttributes();
|
||||
boolean insert = true;
|
||||
if (XMLConstants.XMLNS_ATTRIBUTE_NS_URI.equals(namespaceValue) ||
|
||||
XMLConstants.XMLNS_ATTRIBUTE.equals(nameValue) ||
|
||||
nameValue.startsWith("xmlns:"))
|
||||
{
|
||||
// Namespace declaration, do not output
|
||||
insert = false;
|
||||
}
|
||||
if (prefix != null && namespaceValue == null)
|
||||
{
|
||||
// Not a QName
|
||||
insert = false;
|
||||
}
|
||||
if (parent.getNodeType() == Node.ELEMENT_NODE &&
|
||||
parent.getFirstChild() != null)
|
||||
{
|
||||
// XSLT 7.1.3 Adding an attribute to an element after children have
|
||||
// been added to it is an error
|
||||
insert = false;
|
||||
}
|
||||
if (insert)
|
||||
{
|
||||
// Insert attribute
|
||||
Attr attr = (namespaceValue != null) ?
|
||||
doc.createAttributeNS(namespaceValue, nameValue) :
|
||||
doc.createAttribute(nameValue);
|
||||
if (attrs != null)
|
||||
{
|
||||
if (namespace != null)
|
||||
{
|
||||
attrs.setNamedItemNS(attr);
|
||||
}
|
||||
else
|
||||
{
|
||||
attrs.setNamedItem(attr);
|
||||
}
|
||||
}
|
||||
if (children != null)
|
||||
{
|
||||
children.apply(stylesheet, mode,
|
||||
context, pos, len,
|
||||
attr, null);
|
||||
}
|
||||
}
|
||||
if (next != null)
|
||||
{
|
||||
next.apply(stylesheet, mode,
|
||||
context, pos, len,
|
||||
parent, nextSibling);
|
||||
}
|
||||
}
|
||||
|
||||
final String getPrefix(String name)
|
||||
{
|
||||
int ci = name.indexOf(':');
|
||||
return (ci == -1) ? null : name.substring(0, ci);
|
||||
}
|
||||
|
||||
final String inventPrefix(Node parent)
|
||||
{
|
||||
String base = "ns";
|
||||
int count = 0;
|
||||
String ret = base + Integer.toString(count);
|
||||
while (parent.lookupNamespaceURI(ret) != null)
|
||||
{
|
||||
count++;
|
||||
ret = base + Integer.toString(count);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
public boolean references(QName var)
|
||||
{
|
||||
if (name != null && name.references(var))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (namespace != null && namespace.references(var))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return super.references(var);
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
StringBuffer buf = new StringBuffer(getClass().getName());
|
||||
buf.append('[');
|
||||
buf.append("name=");
|
||||
buf.append(name);
|
||||
buf.append(']');
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
/* AttributeSet.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.transform;
|
||||
|
||||
/**
|
||||
* An attribute-set entry in a stylesheet.
|
||||
*
|
||||
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
|
||||
*/
|
||||
final class AttributeSet
|
||||
{
|
||||
|
||||
final TemplateNode children;
|
||||
final String name;
|
||||
final String uas;
|
||||
|
||||
AttributeSet(TemplateNode children, String name, String uas)
|
||||
{
|
||||
this.children = children;
|
||||
this.name = name;
|
||||
this.uas = uas;
|
||||
}
|
||||
|
||||
AttributeSet clone(Stylesheet stylesheet)
|
||||
{
|
||||
return new AttributeSet((children == null) ? null :
|
||||
children.clone(stylesheet),
|
||||
name, uas);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,325 @@
|
||||
/* Bindings.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.transform;
|
||||
|
||||
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.namespace.QName;
|
||||
import javax.xml.xpath.XPathVariableResolver;
|
||||
import org.w3c.dom.Node;
|
||||
|
||||
/**
|
||||
* The set of variable bindings in effect for a stylesheet.
|
||||
*
|
||||
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
|
||||
*/
|
||||
public class Bindings
|
||||
implements XPathVariableResolver, Cloneable
|
||||
{
|
||||
|
||||
static final int VARIABLE = 0;
|
||||
static final int PARAM = 1;
|
||||
static final int WITH_PARAM = 2;
|
||||
|
||||
final Stylesheet stylesheet;
|
||||
|
||||
/**
|
||||
* Global variables.
|
||||
*/
|
||||
final LinkedList variables;
|
||||
|
||||
/**
|
||||
* Parameter value stack.
|
||||
*/
|
||||
final LinkedList parameters;
|
||||
|
||||
/**
|
||||
* Argument (with-param) value stack.
|
||||
*/
|
||||
final LinkedList withParameters;
|
||||
|
||||
Bindings(Stylesheet stylesheet)
|
||||
{
|
||||
this.stylesheet = stylesheet;
|
||||
variables = new LinkedList();
|
||||
parameters = new LinkedList();
|
||||
withParameters = new LinkedList();
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
push(i);
|
||||
}
|
||||
}
|
||||
|
||||
public Object clone()
|
||||
{
|
||||
try
|
||||
{
|
||||
return (Bindings) super.clone();
|
||||
}
|
||||
catch (CloneNotSupportedException e)
|
||||
{
|
||||
throw new Error(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
void push(int type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case VARIABLE:
|
||||
variables.addFirst(new HashMap());
|
||||
break;
|
||||
case PARAM:
|
||||
parameters.addFirst(new HashMap());
|
||||
break;
|
||||
case WITH_PARAM:
|
||||
withParameters.addFirst(new HashMap());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void pop(int type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case VARIABLE:
|
||||
variables.removeFirst();
|
||||
break;
|
||||
case PARAM:
|
||||
parameters.removeFirst();
|
||||
break;
|
||||
case WITH_PARAM:
|
||||
withParameters.removeFirst();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean containsKey(QName name, int type)
|
||||
{
|
||||
Iterator i = null;
|
||||
switch (type)
|
||||
{
|
||||
case VARIABLE:
|
||||
i = variables.iterator();
|
||||
break;
|
||||
case PARAM:
|
||||
i = parameters.iterator();
|
||||
break;
|
||||
case WITH_PARAM:
|
||||
Map ctx = (Map) withParameters.getFirst();
|
||||
return ctx.containsKey(name);
|
||||
}
|
||||
if (i != null)
|
||||
{
|
||||
while (i.hasNext())
|
||||
{
|
||||
Map ctx = (Map) i.next();
|
||||
if (ctx.containsKey(name))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public Object get(QName name, Node context, int pos, int len)
|
||||
{
|
||||
//System.err.println("bindings.get: "+name);
|
||||
//System.err.println("\t"+toString());
|
||||
Object ret = null;
|
||||
//if (parameters.size() > 1 && containsKey(name, PARAM))
|
||||
// check that template defines parameter
|
||||
{
|
||||
Map cwp = (Map) withParameters.getFirst();
|
||||
ret = cwp.get(name);
|
||||
//System.err.println("\twith-param: ret="+ret);
|
||||
}
|
||||
if (ret == null)
|
||||
{
|
||||
for (Iterator i = variables.iterator(); i.hasNext() && ret == null; )
|
||||
{
|
||||
Map vctx = (Map) i.next();
|
||||
ret = vctx.get(name);
|
||||
}
|
||||
//System.err.println("\tvariable: ret="+ret);
|
||||
}
|
||||
if (ret == null)
|
||||
{
|
||||
for (Iterator i = parameters.iterator(); i.hasNext() && ret == null; )
|
||||
{
|
||||
Map pctx = (Map) i.next();
|
||||
ret = pctx.get(name);
|
||||
}
|
||||
//System.err.println("\tparam: ret="+ret);
|
||||
}
|
||||
/*if (ret instanceof Expr && context != null)
|
||||
{
|
||||
Expr expr = (Expr) ret;
|
||||
ret = expr.evaluate(context, 1, 1);
|
||||
}*/
|
||||
if (ret instanceof Node)
|
||||
{
|
||||
ret = Collections.singleton(ret);
|
||||
}
|
||||
if (ret == null)
|
||||
{
|
||||
ret = "";
|
||||
}
|
||||
//System.err.println("\tret="+ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void set(QName name, Object value, int type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case VARIABLE:
|
||||
Map vctx = (Map) variables.getFirst();
|
||||
vctx.put(name, value);
|
||||
break;
|
||||
case PARAM:
|
||||
Map pctx = (Map) parameters.getFirst();
|
||||
pctx.put(name, value);
|
||||
break;
|
||||
case WITH_PARAM:
|
||||
Map wctx = (Map) withParameters.getFirst();
|
||||
wctx.put(name, value);
|
||||
break;
|
||||
}
|
||||
//System.err.println("Set "+name+"="+value);
|
||||
}
|
||||
|
||||
public Object resolveVariable(QName qName)
|
||||
{
|
||||
return get(qName, null, 1, 1);
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
StringBuffer buf = new StringBuffer();
|
||||
boolean next = false;
|
||||
Collection seen = new HashSet();
|
||||
Map wctx = (Map) withParameters.getFirst();
|
||||
buf.append('(');
|
||||
for (Iterator i = wctx.entrySet().iterator(); i.hasNext(); )
|
||||
{
|
||||
if (next)
|
||||
{
|
||||
buf.append(',');
|
||||
}
|
||||
else
|
||||
{
|
||||
next = true;
|
||||
}
|
||||
Map.Entry entry = (Map.Entry) i.next();
|
||||
Object key = entry.getKey();
|
||||
if (!seen.contains(key))
|
||||
{
|
||||
buf.append(key);
|
||||
buf.append('=');
|
||||
buf.append(entry.getValue());
|
||||
seen.add(key);
|
||||
}
|
||||
}
|
||||
buf.append(')');
|
||||
next = false;
|
||||
seen.clear();
|
||||
buf.append('{');
|
||||
for (Iterator i = variables.iterator(); i.hasNext(); )
|
||||
{
|
||||
Map ctx = (Map) i.next();
|
||||
for (Iterator j = ctx.entrySet().iterator(); j.hasNext(); )
|
||||
{
|
||||
if (next)
|
||||
{
|
||||
buf.append(',');
|
||||
}
|
||||
else
|
||||
{
|
||||
next = true;
|
||||
}
|
||||
Map.Entry entry = (Map.Entry) j.next();
|
||||
Object key = entry.getKey();
|
||||
if (!seen.contains(key))
|
||||
{
|
||||
buf.append(key);
|
||||
buf.append('=');
|
||||
buf.append(entry.getValue());
|
||||
seen.add(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
buf.append('}');
|
||||
next = false;
|
||||
seen.clear();
|
||||
buf.append('[');
|
||||
for (Iterator i = parameters.iterator(); i.hasNext(); )
|
||||
{
|
||||
Map ctx = (Map) i.next();
|
||||
for (Iterator j = ctx.entrySet().iterator(); j.hasNext(); )
|
||||
{
|
||||
if (next)
|
||||
{
|
||||
buf.append(',');
|
||||
}
|
||||
else
|
||||
{
|
||||
next = true;
|
||||
}
|
||||
Map.Entry entry = (Map.Entry) j.next();
|
||||
Object key = entry.getKey();
|
||||
if (!seen.contains(key))
|
||||
{
|
||||
buf.append(key);
|
||||
buf.append('=');
|
||||
buf.append(entry.getValue());
|
||||
seen.add(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
buf.append(']');
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,165 @@
|
||||
/* CallTemplateNode.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.transform;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import javax.xml.namespace.QName;
|
||||
import javax.xml.transform.TransformerException;
|
||||
import org.w3c.dom.Node;
|
||||
|
||||
/**
|
||||
* A template node representing the XSL <code>call-template</code>
|
||||
* instruction.
|
||||
*
|
||||
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
|
||||
*/
|
||||
final class CallTemplateNode
|
||||
extends TemplateNode
|
||||
{
|
||||
|
||||
final QName name;
|
||||
final List withParams;
|
||||
|
||||
CallTemplateNode(QName name, List withParams)
|
||||
{
|
||||
this.name = name;
|
||||
this.withParams = withParams;
|
||||
}
|
||||
|
||||
TemplateNode clone(Stylesheet stylesheet)
|
||||
{
|
||||
int len = withParams.size();
|
||||
List withParams2 = new ArrayList(len);
|
||||
for (int i = 0; i < len; i++)
|
||||
{
|
||||
withParams2.add(((WithParam) withParams.get(i)).clone(stylesheet));
|
||||
}
|
||||
TemplateNode ret = new CallTemplateNode(name, withParams2);
|
||||
if (children != null)
|
||||
{
|
||||
ret.children = children.clone(stylesheet);
|
||||
}
|
||||
if (next != null)
|
||||
{
|
||||
ret.next = next.clone(stylesheet);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void doApply(Stylesheet stylesheet, QName mode,
|
||||
Node context, int pos, int len,
|
||||
Node parent, Node nextSibling)
|
||||
throws TransformerException
|
||||
{
|
||||
if (withParams != null)
|
||||
{
|
||||
// compute the parameter values
|
||||
LinkedList values = new LinkedList();
|
||||
for (Iterator i = withParams.iterator(); i.hasNext(); )
|
||||
{
|
||||
WithParam p = (WithParam) i.next();
|
||||
Object value = p.getValue(stylesheet, mode, context, pos, len);
|
||||
Object[] pair = new Object[2];
|
||||
pair[0] = p.name;
|
||||
pair[1] = value;
|
||||
values.add(pair);
|
||||
}
|
||||
// push the parameter context
|
||||
stylesheet.bindings.push(Bindings.WITH_PARAM);
|
||||
// set the parameters
|
||||
for (Iterator i = values.iterator(); i.hasNext(); )
|
||||
{
|
||||
Object[] pair = (Object[]) i.next();
|
||||
QName name = (QName) pair[0];
|
||||
Object value = pair[1];
|
||||
stylesheet.bindings.set(name, value, Bindings.WITH_PARAM);
|
||||
if (stylesheet.debug)
|
||||
{
|
||||
System.err.println("with-param: " + name + " = " + value);
|
||||
}
|
||||
}
|
||||
}
|
||||
TemplateNode t = stylesheet.getTemplate(mode, name);
|
||||
if (t != null)
|
||||
{
|
||||
t.apply(stylesheet, mode, context, pos, len,
|
||||
parent, nextSibling);
|
||||
}
|
||||
if (withParams != null)
|
||||
{
|
||||
// pop the variable context
|
||||
stylesheet.bindings.pop(Bindings.WITH_PARAM);
|
||||
}
|
||||
// call-template doesn't have processable children
|
||||
if (next != null)
|
||||
{
|
||||
next.apply(stylesheet, mode,
|
||||
context, pos, len,
|
||||
parent, nextSibling);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean references(QName var)
|
||||
{
|
||||
if (withParams != null)
|
||||
{
|
||||
for (Iterator i = withParams.iterator(); i.hasNext(); )
|
||||
{
|
||||
if (((WithParam) i.next()).references(var))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return super.references(var);
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
StringBuffer buf = new StringBuffer(getClass().getName());
|
||||
buf.append('[');
|
||||
buf.append("name=");
|
||||
buf.append(name);
|
||||
buf.append(']');
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
/* ChooseNode.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.transform;
|
||||
|
||||
import javax.xml.namespace.QName;
|
||||
import javax.xml.transform.TransformerException;
|
||||
import org.w3c.dom.Node;
|
||||
|
||||
/**
|
||||
* A template node representing an XSL <code>choose</code> instruction.
|
||||
*
|
||||
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
|
||||
*/
|
||||
final class ChooseNode
|
||||
extends TemplateNode
|
||||
{
|
||||
|
||||
TemplateNode clone(Stylesheet stylesheet)
|
||||
{
|
||||
TemplateNode ret = new ChooseNode();
|
||||
if (children != null)
|
||||
{
|
||||
ret.children = children.clone(stylesheet);
|
||||
}
|
||||
if (next != null)
|
||||
{
|
||||
ret.next = next.clone(stylesheet);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void doApply(Stylesheet stylesheet, QName mode,
|
||||
Node context, int pos, int len,
|
||||
Node parent, Node nextSibling)
|
||||
throws TransformerException
|
||||
{
|
||||
if (children != null)
|
||||
{
|
||||
children.apply(stylesheet, mode,
|
||||
context, pos, len,
|
||||
parent, nextSibling);
|
||||
}
|
||||
if (next != null)
|
||||
{
|
||||
next.apply(stylesheet, mode,
|
||||
context, pos, len,
|
||||
parent, nextSibling);
|
||||
}
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
StringBuffer buf = new StringBuffer(getClass().getName());
|
||||
buf.append('[');
|
||||
buf.append(']');
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
/* CommentNode.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.transform;
|
||||
|
||||
import javax.xml.namespace.QName;
|
||||
import javax.xml.transform.TransformerException;
|
||||
import org.w3c.dom.Comment;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.DocumentFragment;
|
||||
import org.w3c.dom.Node;
|
||||
import gnu.xml.xpath.Expr;
|
||||
|
||||
/**
|
||||
* A template node representing the XSL <code>comment</code> instruction.
|
||||
*
|
||||
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
|
||||
*/
|
||||
final class CommentNode
|
||||
extends TemplateNode
|
||||
{
|
||||
|
||||
TemplateNode clone(Stylesheet stylesheet)
|
||||
{
|
||||
TemplateNode ret = new CommentNode();
|
||||
if (children != null)
|
||||
{
|
||||
ret.children = children.clone(stylesheet);
|
||||
}
|
||||
if (next != null)
|
||||
{
|
||||
ret.next = next.clone(stylesheet);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void doApply(Stylesheet stylesheet, QName mode,
|
||||
Node context, int pos, int len,
|
||||
Node parent, Node nextSibling)
|
||||
throws TransformerException
|
||||
{
|
||||
String value = "";
|
||||
Document doc = (parent instanceof Document) ? (Document) parent :
|
||||
parent.getOwnerDocument();
|
||||
if (children != null)
|
||||
{
|
||||
// Create a document fragment to hold the text
|
||||
DocumentFragment fragment = doc.createDocumentFragment();
|
||||
// Apply children to the fragment
|
||||
children.apply(stylesheet, mode,
|
||||
context, pos, len,
|
||||
fragment, null);
|
||||
// Use XPath string-value of fragment
|
||||
value = Expr.stringValue(fragment);
|
||||
}
|
||||
Comment comment = doc.createComment(value);
|
||||
// Insert into result tree
|
||||
if (nextSibling != null)
|
||||
{
|
||||
parent.insertBefore(comment, nextSibling);
|
||||
}
|
||||
else
|
||||
{
|
||||
parent.appendChild(comment);
|
||||
}
|
||||
if (next != null)
|
||||
{
|
||||
next.apply(stylesheet, mode,
|
||||
context, pos, len,
|
||||
parent, nextSibling);
|
||||
}
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
StringBuffer buf = new StringBuffer(getClass().getName());
|
||||
buf.append('[');
|
||||
buf.append(']');
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,183 @@
|
||||
/* CopyNode.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.transform;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.StringTokenizer;
|
||||
import javax.xml.namespace.QName;
|
||||
import javax.xml.transform.TransformerException;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.NamedNodeMap;
|
||||
import org.w3c.dom.Node;
|
||||
|
||||
/**
|
||||
* A template node representing the XSL <code>copy</code> instruction.
|
||||
*
|
||||
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
|
||||
*/
|
||||
final class CopyNode
|
||||
extends TemplateNode
|
||||
{
|
||||
|
||||
final String uas;
|
||||
|
||||
CopyNode(String uas)
|
||||
{
|
||||
this.uas = uas;
|
||||
}
|
||||
|
||||
TemplateNode clone(Stylesheet stylesheet)
|
||||
{
|
||||
TemplateNode ret = new CopyNode(uas);
|
||||
if (children != null)
|
||||
{
|
||||
ret.children = children.clone(stylesheet);
|
||||
}
|
||||
if (next != null)
|
||||
{
|
||||
ret.next = next.clone(stylesheet);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void doApply(Stylesheet stylesheet, QName mode,
|
||||
Node context, int pos, int len,
|
||||
Node parent, Node nextSibling)
|
||||
throws TransformerException
|
||||
{
|
||||
Node copy = parent;
|
||||
switch (context.getNodeType())
|
||||
{
|
||||
case Node.TEXT_NODE:
|
||||
case Node.ATTRIBUTE_NODE:
|
||||
case Node.ELEMENT_NODE:
|
||||
case Node.PROCESSING_INSTRUCTION_NODE:
|
||||
case Node.COMMENT_NODE:
|
||||
Document doc = (parent instanceof Document) ? (Document) parent :
|
||||
parent.getOwnerDocument();
|
||||
copy = context.cloneNode(false);
|
||||
copy = doc.adoptNode(copy);
|
||||
if (copy.getNodeType() == Node.ATTRIBUTE_NODE)
|
||||
{
|
||||
if (parent.getFirstChild() != null)
|
||||
{
|
||||
// Ignore attempt to add attribute after children
|
||||
}
|
||||
else
|
||||
{
|
||||
NamedNodeMap attrs = parent.getAttributes();
|
||||
if (attrs != null)
|
||||
{
|
||||
attrs.setNamedItemNS(copy);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (nextSibling != null)
|
||||
{
|
||||
parent.insertBefore(copy, nextSibling);
|
||||
}
|
||||
else
|
||||
{
|
||||
parent.appendChild(copy);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (uas != null)
|
||||
{
|
||||
StringTokenizer st = new StringTokenizer(uas, " ");
|
||||
while (st.hasMoreTokens())
|
||||
{
|
||||
addAttributeSet(stylesheet, mode, context, pos, len,
|
||||
copy, null, st.nextToken());
|
||||
}
|
||||
}
|
||||
if (children != null)
|
||||
{
|
||||
children.apply(stylesheet, mode,
|
||||
context, pos, len,
|
||||
copy, null);
|
||||
}
|
||||
if (next != null)
|
||||
{
|
||||
next.apply(stylesheet, mode,
|
||||
context, pos, len,
|
||||
parent, nextSibling);
|
||||
}
|
||||
}
|
||||
|
||||
void addAttributeSet(Stylesheet stylesheet, QName mode,
|
||||
Node context, int pos, int len,
|
||||
Node parent, Node nextSibling, String attributeSet)
|
||||
throws TransformerException
|
||||
{
|
||||
for (Iterator i = stylesheet.attributeSets.iterator(); i.hasNext(); )
|
||||
{
|
||||
AttributeSet as = (AttributeSet) i.next();
|
||||
if (!as.name.equals(attributeSet))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (as.uas != null)
|
||||
{
|
||||
StringTokenizer st = new StringTokenizer(as.uas, " ");
|
||||
while (st.hasMoreTokens())
|
||||
{
|
||||
addAttributeSet(stylesheet, mode, context, pos, len,
|
||||
parent, nextSibling, st.nextToken());
|
||||
}
|
||||
}
|
||||
if (as.children != null)
|
||||
{
|
||||
as.children.apply(stylesheet, mode,
|
||||
context, pos, len,
|
||||
parent, nextSibling);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
StringBuffer buf = new StringBuffer(getClass().getName());
|
||||
buf.append('[');
|
||||
buf.append(']');
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,192 @@
|
||||
/* CopyOfNode.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.transform;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import javax.xml.namespace.QName;
|
||||
import javax.xml.transform.TransformerException;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.NamedNodeMap;
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.Text;
|
||||
import gnu.xml.xpath.Expr;
|
||||
|
||||
/**
|
||||
* A template node representing an XSLT <code>copy-of</code> instruction.
|
||||
*
|
||||
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
|
||||
*/
|
||||
final class CopyOfNode
|
||||
extends TemplateNode
|
||||
{
|
||||
|
||||
final Expr select;
|
||||
|
||||
CopyOfNode(Expr select)
|
||||
{
|
||||
this.select = select;
|
||||
}
|
||||
|
||||
TemplateNode clone(Stylesheet stylesheet)
|
||||
{
|
||||
TemplateNode ret = new CopyOfNode(select.clone(stylesheet));
|
||||
if (children != null)
|
||||
{
|
||||
ret.children = children.clone(stylesheet);
|
||||
}
|
||||
if (next != null)
|
||||
{
|
||||
ret.next = next.clone(stylesheet);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void doApply(Stylesheet stylesheet, QName mode,
|
||||
Node context, int pos, int len,
|
||||
Node parent, Node nextSibling)
|
||||
throws TransformerException
|
||||
{
|
||||
Object ret = select.evaluate(context, pos, len);
|
||||
Document doc = (parent instanceof Document) ? (Document) parent :
|
||||
parent.getOwnerDocument();
|
||||
if (ret instanceof Collection)
|
||||
{
|
||||
Collection ns = (Collection) ret;
|
||||
List list = new ArrayList(ns);
|
||||
Collections.sort(list, documentOrderComparator);
|
||||
for (Iterator i = list.iterator(); i.hasNext(); )
|
||||
{
|
||||
Node src = (Node) i.next();
|
||||
short nodeType = src.getNodeType();
|
||||
if (nodeType == Node.DOCUMENT_NODE)
|
||||
{
|
||||
// Use document element
|
||||
src = ((Document) src).getDocumentElement();
|
||||
if (src == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
nodeType = Node.ELEMENT_NODE;
|
||||
}
|
||||
else if (nodeType == Node.ATTRIBUTE_NODE)
|
||||
{
|
||||
if (parent.getFirstChild() != null)
|
||||
{
|
||||
// Ignore attempt to add attribute after children
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (parent.getNodeType() == Node.ATTRIBUTE_NODE &&
|
||||
nodeType != Node.TEXT_NODE &&
|
||||
nodeType != Node.ENTITY_REFERENCE_NODE)
|
||||
{
|
||||
// Ignore
|
||||
continue;
|
||||
}
|
||||
Node node = src.cloneNode(true);
|
||||
node = doc.adoptNode(node);
|
||||
if (nodeType == Node.ATTRIBUTE_NODE)
|
||||
{
|
||||
NamedNodeMap attrs = parent.getAttributes();
|
||||
if (attrs != null)
|
||||
{
|
||||
attrs.setNamedItemNS(node);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (nextSibling != null)
|
||||
{
|
||||
parent.insertBefore(node, nextSibling);
|
||||
}
|
||||
else
|
||||
{
|
||||
parent.appendChild(node);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
String value = Expr._string(context, ret);
|
||||
if (value != null && value.length() > 0)
|
||||
{
|
||||
Text textNode = doc.createTextNode(value);
|
||||
if (nextSibling != null)
|
||||
{
|
||||
parent.insertBefore(textNode, nextSibling);
|
||||
}
|
||||
else
|
||||
{
|
||||
parent.appendChild(textNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
// copy-of doesn't process children
|
||||
if (next != null)
|
||||
{
|
||||
next.apply(stylesheet, mode,
|
||||
context, pos, len,
|
||||
parent, nextSibling);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean references(QName var)
|
||||
{
|
||||
if (select != null && select.references(var))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return super.references(var);
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
StringBuffer buf = new StringBuffer(getClass().getName());
|
||||
buf.append('[');
|
||||
buf.append("select=");
|
||||
buf.append(select);
|
||||
buf.append(']');
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
/* CurrentFunction.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.transform;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import javax.xml.namespace.QName;
|
||||
import javax.xml.xpath.XPathFunction;
|
||||
import javax.xml.xpath.XPathFunctionException;
|
||||
import org.w3c.dom.Node;
|
||||
import gnu.xml.xpath.Expr;
|
||||
import gnu.xml.xpath.Function;
|
||||
|
||||
/**
|
||||
* The XSLT <code>current()</code>function.
|
||||
*
|
||||
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
|
||||
*/
|
||||
final class CurrentFunction
|
||||
extends Expr
|
||||
implements Function, XPathFunction
|
||||
{
|
||||
|
||||
final Stylesheet stylesheet;
|
||||
|
||||
CurrentFunction(Stylesheet stylesheet)
|
||||
{
|
||||
this.stylesheet = stylesheet;
|
||||
}
|
||||
|
||||
public Object evaluate(List args)
|
||||
throws XPathFunctionException
|
||||
{
|
||||
// We can't do anything useful here.
|
||||
// So much for the JAXP API...
|
||||
return Collections.EMPTY_SET;
|
||||
}
|
||||
|
||||
public void setArguments(List args)
|
||||
{
|
||||
}
|
||||
|
||||
public Object evaluate(Node context, int pos, int len)
|
||||
{
|
||||
return Collections.singleton(stylesheet.current);
|
||||
}
|
||||
|
||||
public Expr clone(Object context)
|
||||
{
|
||||
Stylesheet s = stylesheet;
|
||||
if (context instanceof Stylesheet)
|
||||
{
|
||||
s = (Stylesheet) context;
|
||||
}
|
||||
return new CurrentFunction(s);
|
||||
}
|
||||
|
||||
public boolean references(QName var)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
return "current()";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,84 @@
|
||||
/* DOMSourceLocator.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.transform;
|
||||
|
||||
import javax.xml.transform.dom.DOMLocator;
|
||||
import org.w3c.dom.Node;
|
||||
|
||||
/**
|
||||
* Simple DOMLocator implementation.
|
||||
*
|
||||
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
|
||||
*/
|
||||
class DOMSourceLocator
|
||||
implements DOMLocator
|
||||
{
|
||||
|
||||
final Node node;
|
||||
|
||||
DOMSourceLocator(Node node)
|
||||
{
|
||||
this.node = node;
|
||||
}
|
||||
|
||||
public Node getOriginatingNode()
|
||||
{
|
||||
return node;
|
||||
}
|
||||
|
||||
public String getPublicId()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public String getSystemId()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public int getLineNumber()
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
public int getColumnNumber()
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,256 @@
|
||||
/* DocumentFunction.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.transform;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.TreeSet;
|
||||
import javax.xml.namespace.QName;
|
||||
import javax.xml.transform.TransformerException;
|
||||
import javax.xml.transform.dom.DOMSource;
|
||||
import javax.xml.xpath.XPathFunction;
|
||||
import javax.xml.xpath.XPathFunctionException;
|
||||
import org.w3c.dom.Node;
|
||||
import gnu.xml.xpath.Constant;
|
||||
import gnu.xml.xpath.Expr;
|
||||
import gnu.xml.xpath.Function;
|
||||
import gnu.xml.xpath.IdFunction;
|
||||
|
||||
/**
|
||||
* The XSLT <code>document()</code>function.
|
||||
*
|
||||
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
|
||||
*/
|
||||
final class DocumentFunction
|
||||
extends Expr
|
||||
implements Function, XPathFunction
|
||||
{
|
||||
|
||||
final Stylesheet stylesheet;
|
||||
final Node base;
|
||||
List args;
|
||||
List values;
|
||||
|
||||
DocumentFunction(Stylesheet stylesheet, Node base)
|
||||
{
|
||||
this.stylesheet = stylesheet;
|
||||
this.base = base;
|
||||
}
|
||||
|
||||
public Object evaluate(List args)
|
||||
throws XPathFunctionException
|
||||
{
|
||||
values = args;
|
||||
return evaluate(null, 1, 1);
|
||||
}
|
||||
|
||||
public void setArguments(List args)
|
||||
{
|
||||
this.args = args;
|
||||
}
|
||||
|
||||
public Object evaluate(Node context, int pos, int len)
|
||||
{
|
||||
int arity = args.size();
|
||||
if (values == null)
|
||||
{
|
||||
values = new ArrayList(arity);
|
||||
for (int i = 0; i < arity; i++)
|
||||
{
|
||||
Expr arg = (Expr) args.get(i);
|
||||
values.add(arg.evaluate(context, pos, len));
|
||||
}
|
||||
}
|
||||
Object ret;
|
||||
switch (arity)
|
||||
{
|
||||
case 1:
|
||||
Object arg = values.get(0);
|
||||
if (arg instanceof Collection)
|
||||
{
|
||||
Collection ns = (Collection) arg;
|
||||
Collection acc = new TreeSet();
|
||||
for (Iterator i = ns.iterator(); i.hasNext(); )
|
||||
{
|
||||
Node node = (Node) i.next();
|
||||
String s = Expr.stringValue(node);
|
||||
acc.addAll(document(s, node.getBaseURI()));
|
||||
}
|
||||
ret = acc;
|
||||
}
|
||||
else
|
||||
{
|
||||
String s = Expr._string(context, arg);
|
||||
ret = document(s, base.getBaseURI());
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
Object arg1 = values.get(0);
|
||||
Object arg2 = values.get(1);
|
||||
if (!(arg2 instanceof Collection))
|
||||
{
|
||||
throw new RuntimeException("second argument is not a node-set");
|
||||
}
|
||||
Collection arg2ns = (Collection) arg2;
|
||||
String base2 = arg2ns.isEmpty() ? null :
|
||||
((Node) arg2ns.iterator().next()).getBaseURI();
|
||||
if (arg1 instanceof Collection)
|
||||
{
|
||||
Collection arg1ns = (Collection) arg1;
|
||||
Collection acc = new TreeSet();
|
||||
for (Iterator i = arg1ns.iterator(); i.hasNext(); )
|
||||
{
|
||||
Node node = (Node) i.next();
|
||||
String s = Expr.stringValue(node);
|
||||
acc.addAll(document(s, base2));
|
||||
}
|
||||
ret = acc;
|
||||
}
|
||||
else
|
||||
{
|
||||
String s = Expr._string(context, arg1);
|
||||
ret = document(s, base2);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw new RuntimeException("invalid arity");
|
||||
}
|
||||
values = null;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* The XSL <code>document</code> function.
|
||||
* @see XSLT 12.1
|
||||
* @param uri the URI from which to retrieve nodes
|
||||
* @param base the base URI for relative URIs
|
||||
*/
|
||||
Collection document(String uri, String base)
|
||||
{
|
||||
if ("".equals(uri) || uri == null)
|
||||
{
|
||||
uri = this.base.getBaseURI();
|
||||
}
|
||||
|
||||
// Get fragment
|
||||
Expr fragment = null;
|
||||
int hi = uri.indexOf('#');
|
||||
if (hi != -1)
|
||||
{
|
||||
String f = uri.substring(hi + 1);
|
||||
uri = uri.substring(0, hi);
|
||||
// TODO handle xpointer() here
|
||||
// this only handles IDs
|
||||
fragment = new IdFunction(new Constant(f));
|
||||
}
|
||||
|
||||
// Get document source
|
||||
try
|
||||
{
|
||||
DOMSource source;
|
||||
XSLURIResolver resolver = stylesheet.factory.resolver;
|
||||
synchronized (resolver)
|
||||
{
|
||||
if (stylesheet.transformer != null)
|
||||
{
|
||||
resolver.setUserResolver(stylesheet.transformer.uriResolver);
|
||||
resolver.setUserListener(stylesheet.transformer.errorListener);
|
||||
}
|
||||
source = resolver.resolveDOM(null, base, uri);
|
||||
}
|
||||
Node node = source.getNode();
|
||||
if (fragment == null)
|
||||
{
|
||||
return Collections.singleton(node);
|
||||
}
|
||||
else
|
||||
{
|
||||
Object ret = fragment.evaluate(node, 1, 1);
|
||||
if (!(ret instanceof Collection))
|
||||
{
|
||||
// XXX Report error?
|
||||
return Collections.EMPTY_SET;
|
||||
}
|
||||
return (Collection) ret;
|
||||
}
|
||||
}
|
||||
catch (TransformerException e)
|
||||
{
|
||||
String msg = "can't open " + uri;
|
||||
if (base != null)
|
||||
{
|
||||
msg += " with base " + base;
|
||||
}
|
||||
throw new RuntimeException(msg);
|
||||
}
|
||||
}
|
||||
|
||||
public Expr clone(Object context)
|
||||
{
|
||||
Stylesheet s = stylesheet;
|
||||
if (context instanceof Stylesheet)
|
||||
{
|
||||
s = (Stylesheet) context;
|
||||
}
|
||||
DocumentFunction f = new DocumentFunction(s, base);
|
||||
int len = args.size();
|
||||
List args2 = new ArrayList(len);
|
||||
for (int i = 0; i < len; i++)
|
||||
{
|
||||
args2.add(((Expr) args.get(i)).clone(context));
|
||||
}
|
||||
f.setArguments(args2);
|
||||
return f;
|
||||
}
|
||||
|
||||
public boolean references(QName var)
|
||||
{
|
||||
for (Iterator i = args.iterator(); i.hasNext(); )
|
||||
{
|
||||
if (((Expr) i.next()).references(var))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,183 @@
|
||||
/* ElementAvailableFunction.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.transform;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.TreeSet;
|
||||
import javax.xml.namespace.QName;
|
||||
import javax.xml.namespace.NamespaceContext;
|
||||
import javax.xml.xpath.XPathFunction;
|
||||
import javax.xml.xpath.XPathFunctionException;
|
||||
import org.w3c.dom.Node;
|
||||
import gnu.xml.xpath.Expr;
|
||||
import gnu.xml.xpath.Function;
|
||||
|
||||
/**
|
||||
* The XSLT <code>element-available</code> function.
|
||||
*
|
||||
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
|
||||
*/
|
||||
class ElementAvailableFunction
|
||||
extends Expr
|
||||
implements Function, XPathFunction
|
||||
{
|
||||
|
||||
static final Collection elements;
|
||||
static
|
||||
{
|
||||
TreeSet acc = new TreeSet();
|
||||
acc.add("stylesheet");
|
||||
acc.add("template");
|
||||
acc.add("param");
|
||||
acc.add("variable");
|
||||
acc.add("include");
|
||||
acc.add("import");
|
||||
acc.add("output");
|
||||
acc.add("preserve-space");
|
||||
acc.add("strip-space");
|
||||
acc.add("key");
|
||||
acc.add("decimal-format");
|
||||
acc.add("namespace-alias");
|
||||
acc.add("attribute-set");
|
||||
acc.add("apply-templates");
|
||||
acc.add("call-template");
|
||||
acc.add("value-of");
|
||||
acc.add("for-each");
|
||||
acc.add("if");
|
||||
acc.add("choose");
|
||||
acc.add("when");
|
||||
acc.add("otherwise");
|
||||
acc.add("element");
|
||||
acc.add("attribute");
|
||||
acc.add("text");
|
||||
acc.add("copy");
|
||||
acc.add("processing-instruction");
|
||||
acc.add("comment");
|
||||
acc.add("number");
|
||||
acc.add("copy-of");
|
||||
acc.add("message");
|
||||
acc.add("sort");
|
||||
acc.add("with-param");
|
||||
acc.add("fallback");
|
||||
acc.add("apply-imports");
|
||||
elements = Collections.unmodifiableSet(acc);
|
||||
}
|
||||
|
||||
final NamespaceContext nsctx;
|
||||
List args;
|
||||
|
||||
ElementAvailableFunction(NamespaceContext nsctx)
|
||||
{
|
||||
this.nsctx = nsctx;
|
||||
}
|
||||
|
||||
public Object evaluate(List args)
|
||||
throws XPathFunctionException
|
||||
{
|
||||
// Useless...
|
||||
return Collections.EMPTY_SET;
|
||||
}
|
||||
|
||||
public void setArguments(List args)
|
||||
{
|
||||
this.args = args;
|
||||
}
|
||||
|
||||
public Object evaluate(Node context, int pos, int len)
|
||||
{
|
||||
Expr arg = (Expr) args.get(0);
|
||||
Object val = arg.evaluate(context, pos, len);
|
||||
String name = _string(context, val);
|
||||
String prefix, localName, uri;
|
||||
int ci = name.indexOf(':');
|
||||
if (ci == -1)
|
||||
{
|
||||
prefix = null;
|
||||
localName = name;
|
||||
}
|
||||
else
|
||||
{
|
||||
prefix = name.substring(0, ci);
|
||||
localName = name.substring(ci + 1);
|
||||
}
|
||||
uri = nsctx.getNamespaceURI(prefix);
|
||||
if (Stylesheet.XSL_NS.equals(uri))
|
||||
{
|
||||
return elements.contains(localName) ?
|
||||
Boolean.TRUE : Boolean.FALSE;
|
||||
// TODO extension elements
|
||||
}
|
||||
return Boolean.FALSE;
|
||||
}
|
||||
|
||||
public Expr clone(Object context)
|
||||
{
|
||||
NamespaceContext n = nsctx;
|
||||
if (context instanceof NamespaceContext)
|
||||
{
|
||||
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));
|
||||
}
|
||||
f.setArguments(args2);
|
||||
return f;
|
||||
}
|
||||
|
||||
public boolean references(QName var)
|
||||
{
|
||||
for (Iterator i = args.iterator(); i.hasNext(); )
|
||||
{
|
||||
if (((Expr) i.next()).references(var))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,296 @@
|
||||
/* ElementNode.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.transform;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.StringTokenizer;
|
||||
import javax.xml.XMLConstants;
|
||||
import javax.xml.namespace.QName;
|
||||
import javax.xml.transform.TransformerException;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.DocumentFragment;
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.NamedNodeMap;
|
||||
import org.w3c.dom.Node;
|
||||
import gnu.xml.xpath.Expr;
|
||||
|
||||
/**
|
||||
* A template node representing an XSL <code>element</code> instruction.
|
||||
*
|
||||
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
|
||||
*/
|
||||
final class ElementNode
|
||||
extends TemplateNode
|
||||
{
|
||||
|
||||
final TemplateNode name;
|
||||
final TemplateNode namespace;
|
||||
final String uas;
|
||||
final Node source;
|
||||
final Collection elementExcludeResultPrefixes;
|
||||
|
||||
ElementNode(TemplateNode name,
|
||||
TemplateNode namespace, String uas, Node source)
|
||||
{
|
||||
this.name = name;
|
||||
this.namespace = namespace;
|
||||
this.uas = uas;
|
||||
this.source = source;
|
||||
NamedNodeMap attrs = source.getAttributes();
|
||||
Node attr = attrs.getNamedItemNS(Stylesheet.XSL_NS,
|
||||
"exclude-result-prefixes");
|
||||
if (attr != null)
|
||||
{
|
||||
elementExcludeResultPrefixes = new HashSet();
|
||||
StringTokenizer st = new StringTokenizer(attr.getNodeValue());
|
||||
while (st.hasMoreTokens())
|
||||
{
|
||||
elementExcludeResultPrefixes.add(st.nextToken());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
elementExcludeResultPrefixes = Collections.EMPTY_SET;
|
||||
}
|
||||
}
|
||||
|
||||
TemplateNode clone(Stylesheet stylesheet)
|
||||
{
|
||||
TemplateNode ret = new ElementNode(name.clone(stylesheet),
|
||||
(namespace == null) ? null :
|
||||
namespace.clone(stylesheet),
|
||||
uas, source);
|
||||
if (children != null)
|
||||
{
|
||||
ret.children = children.clone(stylesheet);
|
||||
}
|
||||
if (next != null)
|
||||
{
|
||||
ret.next = next.clone(stylesheet);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void doApply(Stylesheet stylesheet, QName mode,
|
||||
Node context, int pos, int len,
|
||||
Node parent, Node nextSibling)
|
||||
throws TransformerException
|
||||
{
|
||||
Document doc = (parent instanceof Document) ? (Document) parent :
|
||||
parent.getOwnerDocument();
|
||||
// Create a document fragment to hold the name
|
||||
DocumentFragment fragment = doc.createDocumentFragment();
|
||||
// Apply name to the fragment
|
||||
name.apply(stylesheet, mode,
|
||||
context, pos, len,
|
||||
fragment, null);
|
||||
// Use XPath string-value of fragment
|
||||
String nameValue = Expr.stringValue(fragment);
|
||||
|
||||
String namespaceValue = null;
|
||||
if (namespace != null)
|
||||
{
|
||||
// Create a document fragment to hold the namespace
|
||||
fragment = doc.createDocumentFragment();
|
||||
// Apply namespace to the fragment
|
||||
namespace.apply(stylesheet, mode,
|
||||
context, pos, len,
|
||||
fragment, null);
|
||||
// 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);
|
||||
}
|
||||
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")
|
||||
{
|
||||
prefix = null;
|
||||
}
|
||||
// Look up ordinary namespace for this prefix
|
||||
if (namespaceValue == null)
|
||||
{
|
||||
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);
|
||||
if (nextSibling != null)
|
||||
{
|
||||
parent.insertBefore(element, nextSibling);
|
||||
}
|
||||
else
|
||||
{
|
||||
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());
|
||||
}
|
||||
}
|
||||
if (children != null)
|
||||
{
|
||||
children.apply(stylesheet, mode,
|
||||
context, pos, len,
|
||||
element, null);
|
||||
}
|
||||
if (next != null)
|
||||
{
|
||||
next.apply(stylesheet, mode,
|
||||
context, pos, len,
|
||||
parent, nextSibling);
|
||||
}
|
||||
}
|
||||
|
||||
final String getPrefix(String name)
|
||||
{
|
||||
int ci = name.indexOf(':');
|
||||
return (ci == -1) ? null : name.substring(0, ci);
|
||||
}
|
||||
|
||||
void addAttributeSet(Stylesheet stylesheet, QName mode,
|
||||
Node context, int pos, int len,
|
||||
Node parent, Node nextSibling, String attributeSet)
|
||||
throws TransformerException
|
||||
{
|
||||
for (Iterator i = stylesheet.attributeSets.iterator(); i.hasNext(); )
|
||||
{
|
||||
AttributeSet as = (AttributeSet) i.next();
|
||||
if (!as.name.equals(attributeSet))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (as.uas != null)
|
||||
{
|
||||
StringTokenizer st = new StringTokenizer(as.uas, " ");
|
||||
while (st.hasMoreTokens())
|
||||
{
|
||||
addAttributeSet(stylesheet, mode, context, pos, len,
|
||||
parent, nextSibling, st.nextToken());
|
||||
}
|
||||
}
|
||||
if (as.children != null)
|
||||
{
|
||||
as.children.apply(stylesheet, mode,
|
||||
context, pos, len,
|
||||
parent, nextSibling);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean references(QName var)
|
||||
{
|
||||
if (name != null && name.references(var))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (namespace != null && namespace.references(var))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return super.references(var);
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
StringBuffer buf = new StringBuffer(getClass().getName());
|
||||
buf.append('[');
|
||||
buf.append("name=");
|
||||
buf.append(name);
|
||||
if (uas != null)
|
||||
{
|
||||
buf.append(",uas=");
|
||||
buf.append(uas);
|
||||
}
|
||||
buf.append(']');
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
/* ErrorListenerErrorHandler.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.transform;
|
||||
|
||||
import javax.xml.transform.ErrorListener;
|
||||
import javax.xml.transform.TransformerException;
|
||||
import org.xml.sax.ErrorHandler;
|
||||
import org.xml.sax.SAXException;
|
||||
import org.xml.sax.SAXParseException;
|
||||
|
||||
/**
|
||||
* An ErrorHandler that wraps an ErrorListener.
|
||||
*
|
||||
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
|
||||
*/
|
||||
class ErrorListenerErrorHandler
|
||||
implements ErrorHandler
|
||||
{
|
||||
|
||||
final ErrorListener listener;
|
||||
|
||||
ErrorListenerErrorHandler(ErrorListener listener)
|
||||
{
|
||||
this.listener = listener;
|
||||
}
|
||||
|
||||
public void warning(SAXParseException e)
|
||||
throws SAXException
|
||||
{
|
||||
try
|
||||
{
|
||||
listener.warning(new TransformerException(e));
|
||||
}
|
||||
catch (TransformerException e2)
|
||||
{
|
||||
throw new SAXException(e2);
|
||||
}
|
||||
}
|
||||
|
||||
public void error(SAXParseException e)
|
||||
throws SAXException
|
||||
{
|
||||
try
|
||||
{
|
||||
listener.error(new TransformerException(e));
|
||||
}
|
||||
catch (TransformerException e2)
|
||||
{
|
||||
throw new SAXException(e2);
|
||||
}
|
||||
}
|
||||
|
||||
public void fatalError(SAXParseException e)
|
||||
throws SAXException
|
||||
{
|
||||
try
|
||||
{
|
||||
listener.fatalError(new TransformerException(e));
|
||||
}
|
||||
catch (TransformerException e2)
|
||||
{
|
||||
throw new SAXException(e2);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,171 @@
|
||||
/* ForEachNode.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.transform;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import javax.xml.namespace.QName;
|
||||
import javax.xml.transform.TransformerException;
|
||||
import org.w3c.dom.Node;
|
||||
import gnu.xml.xpath.Expr;
|
||||
|
||||
/**
|
||||
* A template node representing an XSLT <code>for-each</code> instruction.
|
||||
*
|
||||
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
|
||||
*/
|
||||
final class ForEachNode
|
||||
extends TemplateNode
|
||||
{
|
||||
|
||||
final Expr select;
|
||||
final List sortKeys;
|
||||
|
||||
ForEachNode(Expr select, List sortKeys)
|
||||
{
|
||||
this.select = select;
|
||||
this.sortKeys = sortKeys;
|
||||
}
|
||||
|
||||
TemplateNode clone(Stylesheet stylesheet)
|
||||
{
|
||||
int len = sortKeys.size();
|
||||
List sortKeys2 = new ArrayList(len);
|
||||
for (int i = 0; i < len; i++)
|
||||
{
|
||||
sortKeys2.add(((Key) sortKeys.get(i)).clone(stylesheet));
|
||||
}
|
||||
TemplateNode ret = new ForEachNode(select.clone(stylesheet),
|
||||
sortKeys2);
|
||||
if (children != null)
|
||||
{
|
||||
ret.children = children.clone(stylesheet);
|
||||
}
|
||||
if (next != null)
|
||||
{
|
||||
ret.next = next.clone(stylesheet);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void doApply(Stylesheet stylesheet, QName mode,
|
||||
Node context, int pos, int len,
|
||||
Node parent, Node nextSibling)
|
||||
throws TransformerException
|
||||
{
|
||||
if (children != null)
|
||||
{
|
||||
// Set current template to null
|
||||
Template saved = stylesheet.currentTemplate;
|
||||
stylesheet.currentTemplate = null;
|
||||
Object ret = select.evaluate(context, pos, len);
|
||||
//System.err.println(toString() + ": " + context+" -> "+ret);
|
||||
if (ret instanceof Collection)
|
||||
{
|
||||
Collection ns = (Collection) ret;
|
||||
List list = new ArrayList(ns);
|
||||
if (sortKeys != null)
|
||||
{
|
||||
for (Iterator i = sortKeys.iterator(); i.hasNext(); )
|
||||
{
|
||||
SortKey sortKey = (SortKey) i.next();
|
||||
sortKey.init(stylesheet, mode, context, pos, len, parent,
|
||||
nextSibling);
|
||||
}
|
||||
Collections.sort(list, new XSLComparator(sortKeys));
|
||||
}
|
||||
else
|
||||
{
|
||||
Collections.sort(list, documentOrderComparator);
|
||||
}
|
||||
// Perform children for each node
|
||||
int l = list.size();
|
||||
int p = 1;
|
||||
for (Iterator i = list.iterator(); i.hasNext(); )
|
||||
{
|
||||
Node node = (Node) i.next();
|
||||
stylesheet.current = node;
|
||||
children.apply(stylesheet, mode,
|
||||
node, p++, l,
|
||||
parent, nextSibling);
|
||||
}
|
||||
}
|
||||
// Restore current template
|
||||
stylesheet.currentTemplate = saved;
|
||||
}
|
||||
if (next != null)
|
||||
{
|
||||
next.apply(stylesheet, mode,
|
||||
context, pos, len,
|
||||
parent, nextSibling);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean references(QName var)
|
||||
{
|
||||
if (select != null && select.references(var))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (sortKeys != null)
|
||||
{
|
||||
for (Iterator i = sortKeys.iterator(); i.hasNext(); )
|
||||
{
|
||||
if (((SortKey) i.next()).references(var))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return super.references(var);
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
StringBuffer buf = new StringBuffer(getClass().getName());
|
||||
buf.append('[');
|
||||
buf.append("select=");
|
||||
buf.append(select);
|
||||
buf.append(']');
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,146 @@
|
||||
/* FormatNumberFunction.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.transform;
|
||||
|
||||
import java.text.DecimalFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import javax.xml.namespace.QName;
|
||||
import javax.xml.xpath.XPathFunction;
|
||||
import javax.xml.xpath.XPathFunctionException;
|
||||
import org.w3c.dom.Node;
|
||||
import gnu.xml.xpath.Expr;
|
||||
import gnu.xml.xpath.Function;
|
||||
|
||||
/**
|
||||
* The XSLT <code>format-number()</code>function.
|
||||
*
|
||||
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
|
||||
*/
|
||||
final class FormatNumberFunction
|
||||
extends Expr
|
||||
implements XPathFunction, Function
|
||||
{
|
||||
|
||||
final Stylesheet stylesheet;
|
||||
List args;
|
||||
|
||||
FormatNumberFunction(Stylesheet stylesheet)
|
||||
{
|
||||
this.stylesheet = stylesheet;
|
||||
}
|
||||
|
||||
public Object evaluate(List args)
|
||||
throws XPathFunctionException
|
||||
{
|
||||
// Useless...
|
||||
return Collections.EMPTY_SET;
|
||||
}
|
||||
|
||||
public void setArguments(List args)
|
||||
{
|
||||
this.args = args;
|
||||
}
|
||||
|
||||
public Object evaluate(Node context, int pos, int len)
|
||||
{
|
||||
int arity = args.size();
|
||||
List values = new ArrayList(arity);
|
||||
for (int i = 0; i < arity; i++)
|
||||
{
|
||||
Expr arg = (Expr) args.get(i);
|
||||
values.add(arg.evaluate(context, pos, len));
|
||||
}
|
||||
double number = _number(context, values.get(0));
|
||||
String pattern = _string(context, values.get(1));
|
||||
// Currency symbol ¤ is not supposed to be present
|
||||
if (pattern.indexOf('\u00a4') != -1)
|
||||
{
|
||||
// Replace with $ (Xalan does this)
|
||||
pattern = pattern.replace('\u00a4', '$');
|
||||
}
|
||||
String dfName = null;
|
||||
if (arity > 2)
|
||||
{
|
||||
dfName = _string(context, values.get(2));
|
||||
// otherwise the default decimal-format will be used
|
||||
}
|
||||
DecimalFormat df = (DecimalFormat) stylesheet.decimalFormats.get(dfName);
|
||||
if (df == null)
|
||||
{
|
||||
throw new IllegalArgumentException("No such decimal-format: " +
|
||||
dfName);
|
||||
}
|
||||
df.applyLocalizedPattern(pattern);
|
||||
return df.format(number);
|
||||
}
|
||||
|
||||
public Expr clone(Object context)
|
||||
{
|
||||
Stylesheet s = stylesheet;
|
||||
if (context instanceof Stylesheet)
|
||||
{
|
||||
s = (Stylesheet) context;
|
||||
}
|
||||
FormatNumberFunction f = new FormatNumberFunction(s);
|
||||
int len = args.size();
|
||||
List args2 = new ArrayList(len);
|
||||
for (int i = 0; i < len; i++)
|
||||
{
|
||||
args2.add(((Expr) args.get(i)).clone(context));
|
||||
}
|
||||
f.setArguments(args2);
|
||||
return f;
|
||||
}
|
||||
|
||||
public boolean references(QName var)
|
||||
{
|
||||
for (Iterator i = args.iterator(); i.hasNext(); )
|
||||
{
|
||||
if (((Expr) i.next()).references(var))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,189 @@
|
||||
/* FunctionAvailableFunction.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.transform;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.TreeSet;
|
||||
import javax.xml.namespace.NamespaceContext;
|
||||
import javax.xml.namespace.QName;
|
||||
import javax.xml.xpath.XPathFunction;
|
||||
import javax.xml.xpath.XPathFunctionException;
|
||||
import org.w3c.dom.Node;
|
||||
import gnu.xml.xpath.Expr;
|
||||
import gnu.xml.xpath.Function;
|
||||
|
||||
/**
|
||||
* The XSLT <code>function-available</code> function.
|
||||
*
|
||||
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
|
||||
*/
|
||||
class FunctionAvailableFunction
|
||||
extends Expr
|
||||
implements Function, XPathFunction
|
||||
{
|
||||
|
||||
static final Collection xsltFunctions;
|
||||
static final Collection xpathFunctions;
|
||||
static
|
||||
{
|
||||
TreeSet acc = new TreeSet();
|
||||
acc.add("document");
|
||||
acc.add("key");
|
||||
acc.add("format-number");
|
||||
acc.add("current");
|
||||
acc.add("unparsed-entity-uri");
|
||||
acc.add("generate-id");
|
||||
acc.add("system-property");
|
||||
acc.add("element-available");
|
||||
acc.add("function-available");
|
||||
xsltFunctions = Collections.unmodifiableSet(acc);
|
||||
acc = new TreeSet();
|
||||
acc.add("boolean");
|
||||
acc.add("ceiling");
|
||||
acc.add("concat");
|
||||
acc.add("contains");
|
||||
acc.add("count");
|
||||
acc.add("false");
|
||||
acc.add("floor");
|
||||
acc.add("id");
|
||||
acc.add("lang");
|
||||
acc.add("last");
|
||||
acc.add("local-name");
|
||||
acc.add("name");
|
||||
acc.add("namespace-uri");
|
||||
acc.add("normalize-space");
|
||||
acc.add("not");
|
||||
acc.add("number");
|
||||
acc.add("position");
|
||||
acc.add("round");
|
||||
acc.add("starts-with");
|
||||
acc.add("string");
|
||||
acc.add("string-length");
|
||||
acc.add("substring-after");
|
||||
acc.add("substring-before");
|
||||
acc.add("substring");
|
||||
acc.add("sum");
|
||||
acc.add("translate");
|
||||
acc.add("true");
|
||||
xpathFunctions = Collections.unmodifiableSet(acc);
|
||||
}
|
||||
|
||||
final NamespaceContext nsctx;
|
||||
List args;
|
||||
|
||||
FunctionAvailableFunction(NamespaceContext nsctx)
|
||||
{
|
||||
this.nsctx = nsctx;
|
||||
}
|
||||
|
||||
public Object evaluate(List args)
|
||||
throws XPathFunctionException
|
||||
{
|
||||
// Useless...
|
||||
return Collections.EMPTY_SET;
|
||||
}
|
||||
|
||||
public void setArguments(List args)
|
||||
{
|
||||
this.args = args;
|
||||
}
|
||||
|
||||
public Object evaluate(Node context, int pos, int len)
|
||||
{
|
||||
Expr arg = (Expr) args.get(0);
|
||||
Object val = arg.evaluate(context, pos, len);
|
||||
String name = _string(context, val);
|
||||
String prefix, localName, uri;
|
||||
int ci = name.indexOf(':');
|
||||
if (ci == -1)
|
||||
{
|
||||
prefix = null;
|
||||
localName = name;
|
||||
}
|
||||
else
|
||||
{
|
||||
prefix = name.substring(0, ci);
|
||||
localName = name.substring(ci + 1);
|
||||
}
|
||||
uri = nsctx.getNamespaceURI(prefix);
|
||||
if (uri == null)
|
||||
{
|
||||
return xsltFunctions.contains(localName) ||
|
||||
xpathFunctions.contains(localName) ?
|
||||
Boolean.TRUE : Boolean.FALSE;
|
||||
// TODO extension functions
|
||||
}
|
||||
return Boolean.FALSE;
|
||||
}
|
||||
|
||||
public Expr clone(Object context)
|
||||
{
|
||||
NamespaceContext n = nsctx;
|
||||
if (context instanceof NamespaceContext)
|
||||
{
|
||||
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));
|
||||
}
|
||||
f.setArguments(args2);
|
||||
return f;
|
||||
}
|
||||
|
||||
public boolean references(QName var)
|
||||
{
|
||||
for (Iterator i = args.iterator(); i.hasNext(); )
|
||||
{
|
||||
if (((Expr) i.next()).references(var))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,140 @@
|
||||
/* GenerateIdFunction.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.transform;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import javax.xml.namespace.QName;
|
||||
import javax.xml.xpath.XPathFunction;
|
||||
import javax.xml.xpath.XPathFunctionException;
|
||||
import org.w3c.dom.Node;
|
||||
import gnu.xml.xpath.Expr;
|
||||
import gnu.xml.xpath.Function;
|
||||
|
||||
/**
|
||||
* The XSLT <code>generate-id()</code>function.
|
||||
*
|
||||
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
|
||||
*/
|
||||
final class GenerateIdFunction
|
||||
extends Expr
|
||||
implements XPathFunction, Function
|
||||
{
|
||||
|
||||
List args;
|
||||
|
||||
public Object evaluate(List args)
|
||||
throws XPathFunctionException
|
||||
{
|
||||
// Useless...
|
||||
return Collections.EMPTY_SET;
|
||||
}
|
||||
|
||||
public void setArguments(List args)
|
||||
{
|
||||
this.args = args;
|
||||
}
|
||||
|
||||
public Object evaluate(Node context, int pos, int len)
|
||||
{
|
||||
int arity = args.size();
|
||||
List values = new ArrayList(arity);
|
||||
for (int i = 0; i < arity; i++)
|
||||
{
|
||||
Expr arg = (Expr) args.get(i);
|
||||
values.add(arg.evaluate(context, pos, len));
|
||||
}
|
||||
Node node;
|
||||
Collection ns = (arity == 0) ? Collections.EMPTY_SET :
|
||||
(Collection) values.get(0);
|
||||
if (ns.isEmpty())
|
||||
{
|
||||
node = context;
|
||||
}
|
||||
else
|
||||
{
|
||||
List list = new ArrayList(ns);
|
||||
Collections.sort(list, documentOrderComparator);
|
||||
node = (Node) list.get(0);
|
||||
}
|
||||
|
||||
String name = node.getNodeName();
|
||||
int index = 0, depth = 0;
|
||||
for (Node ctx = node.getPreviousSibling(); ctx != null;
|
||||
ctx = ctx.getPreviousSibling())
|
||||
{
|
||||
index++;
|
||||
}
|
||||
for (Node ctx = node.getParentNode(); ctx != null;
|
||||
ctx = ctx.getParentNode())
|
||||
{
|
||||
depth++;
|
||||
}
|
||||
return name + "-" + index + "-" + depth;
|
||||
}
|
||||
|
||||
public Expr clone(Object context)
|
||||
{
|
||||
GenerateIdFunction f = new GenerateIdFunction();
|
||||
int len = args.size();
|
||||
List args2 = new ArrayList(len);
|
||||
for (int i = 0; i < len; i++)
|
||||
{
|
||||
args2.add(((Expr) args.get(i)).clone(context));
|
||||
}
|
||||
f.setArguments(args2);
|
||||
return f;
|
||||
}
|
||||
|
||||
public boolean references(QName var)
|
||||
{
|
||||
for (Iterator i = args.iterator(); i.hasNext(); )
|
||||
{
|
||||
if (((Expr) i.next()).references(var))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,120 @@
|
||||
/* IfNode.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.transform;
|
||||
|
||||
import javax.xml.namespace.QName;
|
||||
import javax.xml.transform.TransformerException;
|
||||
import org.w3c.dom.Node;
|
||||
import gnu.xml.xpath.Expr;
|
||||
|
||||
/**
|
||||
* A template node representing an XSL <code>if</code> instruction.
|
||||
*
|
||||
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
|
||||
*/
|
||||
final class IfNode
|
||||
extends TemplateNode
|
||||
{
|
||||
|
||||
final Expr test;
|
||||
|
||||
IfNode(Expr test)
|
||||
{
|
||||
this.test = test;
|
||||
}
|
||||
|
||||
TemplateNode clone(Stylesheet stylesheet)
|
||||
{
|
||||
TemplateNode ret = new IfNode(test.clone(stylesheet));
|
||||
if (children != null)
|
||||
{
|
||||
ret.children = children.clone(stylesheet);
|
||||
}
|
||||
if (next != null)
|
||||
{
|
||||
ret.next = next.clone(stylesheet);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void doApply(Stylesheet stylesheet, QName mode,
|
||||
Node context, int pos, int len,
|
||||
Node parent, Node nextSibling)
|
||||
throws TransformerException
|
||||
{
|
||||
Object ret = test.evaluate(context, pos, len);
|
||||
boolean success = (ret instanceof Boolean) ?
|
||||
((Boolean) ret).booleanValue() :
|
||||
Expr._boolean(context, ret);
|
||||
if (success)
|
||||
{
|
||||
if (children != null)
|
||||
{
|
||||
children.apply(stylesheet, mode,
|
||||
context, pos, len,
|
||||
parent, nextSibling);
|
||||
}
|
||||
}
|
||||
if (next != null)
|
||||
{
|
||||
next.apply(stylesheet, mode,
|
||||
context, pos, len,
|
||||
parent, nextSibling);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean references(QName var)
|
||||
{
|
||||
if (test != null && test.references(var))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return super.references(var);
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
StringBuffer buf = new StringBuffer(getClass().getName());
|
||||
buf.append('[');
|
||||
buf.append("test=");
|
||||
buf.append(test);
|
||||
buf.append(']');
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
/* Key.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.transform;
|
||||
|
||||
import javax.xml.namespace.QName;
|
||||
import gnu.xml.xpath.Expr;
|
||||
import gnu.xml.xpath.Pattern;
|
||||
|
||||
/**
|
||||
* An XSL key.
|
||||
*
|
||||
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
|
||||
*/
|
||||
class Key
|
||||
{
|
||||
|
||||
final QName name;
|
||||
final Pattern match;
|
||||
final Expr use;
|
||||
|
||||
Key(QName name, Pattern match, Expr use)
|
||||
{
|
||||
this.name = name;
|
||||
this.match = match;
|
||||
this.use = use;
|
||||
}
|
||||
|
||||
Key clone(Stylesheet stylesheet)
|
||||
{
|
||||
return new Key(name,
|
||||
(Pattern) match.clone(stylesheet),
|
||||
use.clone(stylesheet));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,228 @@
|
||||
/* KeyFunction.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.transform;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import javax.xml.namespace.QName;
|
||||
import javax.xml.xpath.XPathFunction;
|
||||
import javax.xml.xpath.XPathFunctionException;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Node;
|
||||
import gnu.xml.xpath.Expr;
|
||||
import gnu.xml.xpath.Function;
|
||||
import gnu.xml.xpath.Pattern;
|
||||
|
||||
/**
|
||||
* The XSLT <code>key()</code>function.
|
||||
*
|
||||
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
|
||||
*/
|
||||
final class KeyFunction
|
||||
extends Pattern
|
||||
implements XPathFunction, Function
|
||||
{
|
||||
|
||||
final Stylesheet stylesheet;
|
||||
List args;
|
||||
|
||||
KeyFunction(Stylesheet stylesheet)
|
||||
{
|
||||
this.stylesheet = stylesheet;
|
||||
}
|
||||
|
||||
public Object evaluate(List args)
|
||||
throws XPathFunctionException
|
||||
{
|
||||
// Useless...
|
||||
return Collections.EMPTY_SET;
|
||||
}
|
||||
|
||||
public void setArguments(List args)
|
||||
{
|
||||
this.args = args;
|
||||
}
|
||||
|
||||
public boolean matches(Node context)
|
||||
{
|
||||
Object ret = evaluate(context, 1, 1);
|
||||
return !((Collection) ret).isEmpty();
|
||||
}
|
||||
|
||||
public Object evaluate(Node context, int pos, int len)
|
||||
{
|
||||
// Evaluate arguments
|
||||
int arity = args.size();
|
||||
List values = new ArrayList(arity);
|
||||
for (int i = 0; i < arity; i++)
|
||||
{
|
||||
Expr arg = (Expr) args.get(i);
|
||||
values.add(arg.evaluate(context, pos, len));
|
||||
}
|
||||
// Get key name
|
||||
QName keyName = QName.valueOf(_string(context, values.get(0)));
|
||||
// Expand qualified name
|
||||
String uri = keyName.getNamespaceURI();
|
||||
String prefix = keyName.getPrefix();
|
||||
if ((uri == null || uri.length() == 0) &&
|
||||
(prefix != null && prefix.length() > 0))
|
||||
{
|
||||
uri = stylesheet.getNamespaceURI(prefix);
|
||||
if (uri != null && uri.length() > 0)
|
||||
{
|
||||
String localName = keyName.getLocalPart();
|
||||
keyName = new QName(uri, localName, prefix);
|
||||
}
|
||||
}
|
||||
// Compute matching key set
|
||||
Collection keySet = new LinkedList();
|
||||
for (Iterator i = stylesheet.keys.iterator(); i.hasNext(); )
|
||||
{
|
||||
Key key = (Key) i.next();
|
||||
if (key.name.equals(keyName))
|
||||
{
|
||||
keySet.add(key);
|
||||
}
|
||||
}
|
||||
// Get target
|
||||
Object target = values.get(1);
|
||||
Collection acc = new LinkedHashSet();
|
||||
Document doc = (context instanceof Document) ? (Document) context :
|
||||
context.getOwnerDocument();
|
||||
if (target instanceof Collection)
|
||||
{
|
||||
for (Iterator i = ((Collection) target).iterator(); i.hasNext(); )
|
||||
{
|
||||
String val = Expr.stringValue((Node) i.next());
|
||||
addKeyNodes(doc, keySet, val, acc);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
String val = Expr._string(context, target);
|
||||
addKeyNodes(doc, keySet, val, acc);
|
||||
}
|
||||
List ret = new ArrayList(acc);
|
||||
Collections.sort(ret, documentOrderComparator);
|
||||
return ret;
|
||||
}
|
||||
|
||||
final void addKeyNodes(Node node, Collection keySet,
|
||||
String value, Collection acc)
|
||||
{
|
||||
addKeyNodeIfMatch(node, keySet, value, acc);
|
||||
// Apply children
|
||||
for (Node ctx = node.getFirstChild(); ctx != null;
|
||||
ctx = ctx.getNextSibling())
|
||||
{
|
||||
addKeyNodes(ctx, keySet, value, acc);
|
||||
}
|
||||
}
|
||||
|
||||
final void addKeyNodeIfMatch(Node node, Collection keySet,
|
||||
String value, Collection acc)
|
||||
{
|
||||
for (Iterator i = keySet.iterator(); i.hasNext(); )
|
||||
{
|
||||
Key key = (Key) i.next();
|
||||
if (key.match.matches(node))
|
||||
{
|
||||
Object eval = key.use.evaluate(node, 1, 1);
|
||||
if (eval instanceof Collection)
|
||||
{
|
||||
for (Iterator j = ((Collection) eval).iterator();
|
||||
j.hasNext(); )
|
||||
{
|
||||
String keyValue = Expr.stringValue((Node) j.next());
|
||||
if (value.equals(keyValue))
|
||||
{
|
||||
acc.add(node);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
String keyValue = Expr._string(node, eval);
|
||||
if (value.equals(keyValue))
|
||||
{
|
||||
acc.add(node);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Expr clone(Object context)
|
||||
{
|
||||
Stylesheet s = stylesheet;
|
||||
if (context instanceof Stylesheet)
|
||||
{
|
||||
s = (Stylesheet) context;
|
||||
}
|
||||
KeyFunction f = new KeyFunction(s);
|
||||
int len = args.size();
|
||||
List args2 = new ArrayList(len);
|
||||
for (int i = 0; i < len; i++)
|
||||
{
|
||||
args2.add(((Expr) args.get(i)).clone(context));
|
||||
}
|
||||
f.setArguments(args2);
|
||||
return f;
|
||||
}
|
||||
|
||||
public boolean references(QName var)
|
||||
{
|
||||
for (Iterator i = args.iterator(); i.hasNext(); )
|
||||
{
|
||||
if (((Expr) i.next()).references(var))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,231 @@
|
||||
/* LiteralNode.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.transform;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.StringTokenizer;
|
||||
import javax.xml.namespace.QName;
|
||||
import javax.xml.transform.TransformerException;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.NamedNodeMap;
|
||||
import org.w3c.dom.Node;
|
||||
|
||||
/**
|
||||
* A template node that copies a DOM node in the template to the result
|
||||
* tree.
|
||||
*
|
||||
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
|
||||
*/
|
||||
final class LiteralNode
|
||||
extends TemplateNode
|
||||
{
|
||||
|
||||
/**
|
||||
* The source node in the XSL template.
|
||||
*/
|
||||
final Node source;
|
||||
|
||||
final Collection elementExcludeResultPrefixes;
|
||||
|
||||
LiteralNode(Node source)
|
||||
{
|
||||
this.source = source;
|
||||
if (source.getNodeType() == Node.ELEMENT_NODE)
|
||||
{
|
||||
NamedNodeMap attrs = source.getAttributes();
|
||||
Node attr = attrs.getNamedItemNS(Stylesheet.XSL_NS,
|
||||
"exclude-result-prefixes");
|
||||
if (attr != null)
|
||||
{
|
||||
elementExcludeResultPrefixes = new HashSet();
|
||||
StringTokenizer st = new StringTokenizer(attr.getNodeValue());
|
||||
while (st.hasMoreTokens())
|
||||
{
|
||||
elementExcludeResultPrefixes.add(st.nextToken());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
elementExcludeResultPrefixes = Collections.EMPTY_SET;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
elementExcludeResultPrefixes = null;
|
||||
}
|
||||
}
|
||||
|
||||
TemplateNode clone(Stylesheet stylesheet)
|
||||
{
|
||||
TemplateNode ret = new LiteralNode(source);
|
||||
if (children != null)
|
||||
{
|
||||
ret.children = children.clone(stylesheet);
|
||||
}
|
||||
if (next != null)
|
||||
{
|
||||
ret.next = next.clone(stylesheet);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void doApply(Stylesheet stylesheet, QName mode,
|
||||
Node context, int pos, int len,
|
||||
Node parent, Node nextSibling)
|
||||
throws TransformerException
|
||||
{
|
||||
Node result = null;
|
||||
Document doc = (parent instanceof Document) ? (Document) parent :
|
||||
parent.getOwnerDocument();
|
||||
short nodeType = source.getNodeType();
|
||||
if (nodeType == Node.ATTRIBUTE_NODE &&
|
||||
parent.getFirstChild() != null)
|
||||
{
|
||||
// Ignore attributes added after child elements
|
||||
}
|
||||
else
|
||||
{
|
||||
// Namespace aliasing
|
||||
if (nodeType == Node.ELEMENT_NODE)
|
||||
{
|
||||
String prefix = source.getPrefix();
|
||||
if (prefix == null)
|
||||
{
|
||||
prefix = "#default";
|
||||
}
|
||||
String resultPrefix =
|
||||
(String) stylesheet.namespaceAliases.get(prefix);
|
||||
if (resultPrefix != null)
|
||||
{
|
||||
if ("#default".equals(resultPrefix))
|
||||
{
|
||||
resultPrefix = null;
|
||||
}
|
||||
String uri = source.lookupNamespaceURI(resultPrefix);
|
||||
String name = source.getNodeName();
|
||||
// Create a new element node in the result document
|
||||
result = doc.createElementNS(uri, name);
|
||||
// copy attributes
|
||||
NamedNodeMap srcAttrs = source.getAttributes();
|
||||
NamedNodeMap dstAttrs = result.getAttributes();
|
||||
int l = srcAttrs.getLength();
|
||||
for (int i = 0; i < l; i++)
|
||||
{
|
||||
Node attr = srcAttrs.item(i);
|
||||
if (!Stylesheet.XSL_NS.equals(attr.getNamespaceURI()))
|
||||
{
|
||||
attr = attr.cloneNode(true);
|
||||
attr = doc.adoptNode(attr);
|
||||
dstAttrs.setNamedItemNS(attr);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (result == null)
|
||||
{
|
||||
// Create result node
|
||||
result = source.cloneNode(false);
|
||||
// Remove any XSL attributes
|
||||
NamedNodeMap attrs = result.getAttributes();
|
||||
if (attrs != null)
|
||||
{
|
||||
int l = attrs.getLength();
|
||||
for (int i = 0; i < l; i++)
|
||||
{
|
||||
Node attr = attrs.item(i);
|
||||
if (Stylesheet.XSL_NS.equals(attr.getNamespaceURI()))
|
||||
{
|
||||
attrs.removeNamedItem(attr.getNodeName());
|
||||
i--;
|
||||
l--;
|
||||
}
|
||||
}
|
||||
}
|
||||
Node result2 = doc.adoptNode(result);
|
||||
if (result2 == null)
|
||||
{
|
||||
String msg = "Error adopting node to result tree: " +
|
||||
result + " (" + result.getClass().getName() + ")";
|
||||
DOMSourceLocator l = new DOMSourceLocator(context);
|
||||
throw new TransformerException(msg, l);
|
||||
}
|
||||
result = result2;
|
||||
}
|
||||
if (nextSibling != null)
|
||||
{
|
||||
parent.insertBefore(result, nextSibling);
|
||||
}
|
||||
else
|
||||
{
|
||||
parent.appendChild(result);
|
||||
}
|
||||
if (nodeType == Node.ELEMENT_NODE)
|
||||
{
|
||||
stylesheet.addNamespaceNodes(source, result, doc,
|
||||
elementExcludeResultPrefixes);
|
||||
}
|
||||
// children
|
||||
if (children != null)
|
||||
{
|
||||
children.apply(stylesheet, mode,
|
||||
context, pos, len,
|
||||
result, null);
|
||||
}
|
||||
}
|
||||
// next sibling
|
||||
if (next != null)
|
||||
{
|
||||
next.apply(stylesheet, mode,
|
||||
context, pos, len,
|
||||
parent, nextSibling);
|
||||
}
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
StringBuffer buf = new StringBuffer(getClass().getName());
|
||||
buf.append('[');
|
||||
buf.append("source=");
|
||||
buf.append(source);
|
||||
buf.append(']');
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
/* MessageNode.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.transform;
|
||||
|
||||
import javax.xml.namespace.QName;
|
||||
import javax.xml.transform.TransformerException;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.DocumentFragment;
|
||||
import org.w3c.dom.Node;
|
||||
import gnu.xml.xpath.Expr;
|
||||
|
||||
/**
|
||||
* An XSL <code>message</code> instruction.
|
||||
*
|
||||
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
|
||||
*/
|
||||
final class MessageNode
|
||||
extends TemplateNode
|
||||
{
|
||||
|
||||
final boolean terminate;
|
||||
|
||||
MessageNode(boolean terminate)
|
||||
{
|
||||
this.terminate = terminate;
|
||||
}
|
||||
|
||||
TemplateNode clone(Stylesheet stylesheet)
|
||||
{
|
||||
TemplateNode ret = new MessageNode(terminate);
|
||||
if (children != null)
|
||||
{
|
||||
ret.children = children.clone(stylesheet);
|
||||
}
|
||||
if (next != null)
|
||||
{
|
||||
ret.next = next.clone(stylesheet);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void doApply(Stylesheet stylesheet, QName mode,
|
||||
Node context, int pos, int len,
|
||||
Node parent, Node nextSibling)
|
||||
throws TransformerException
|
||||
{
|
||||
if (children != null)
|
||||
{
|
||||
Document doc = (parent instanceof Document) ? (Document) parent :
|
||||
parent.getOwnerDocument();
|
||||
DocumentFragment fragment = doc.createDocumentFragment();
|
||||
children.apply(stylesheet, mode, context, pos, len, fragment, null);
|
||||
String message = Expr.stringValue(fragment);
|
||||
System.err.println(message);
|
||||
if (terminate)
|
||||
{
|
||||
stylesheet.terminated = true;
|
||||
}
|
||||
}
|
||||
if (next != null && !terminate)
|
||||
{
|
||||
next.apply(stylesheet, mode, context, pos, len, parent, nextSibling);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,269 @@
|
||||
/* NodeNumberNode.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.transform;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import javax.xml.transform.TransformerException;
|
||||
import org.w3c.dom.Node;
|
||||
import gnu.xml.xpath.Expr;
|
||||
import gnu.xml.xpath.Pattern;
|
||||
import gnu.xml.xpath.Selector;
|
||||
import gnu.xml.xpath.UnionExpr;
|
||||
|
||||
/**
|
||||
* A template node representing the XSL <code>number</code> instruction
|
||||
* with no <code>value</code> expression, i.e. the value is computed from
|
||||
* the document position of the context node.
|
||||
*
|
||||
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
|
||||
*/
|
||||
final class NodeNumberNode
|
||||
extends AbstractNumberNode
|
||||
{
|
||||
|
||||
static final int SINGLE = 0;
|
||||
static final int MULTIPLE = 1;
|
||||
static final int ANY = 2;
|
||||
|
||||
final int level;
|
||||
final Pattern count;
|
||||
final Pattern from;
|
||||
|
||||
NodeNumberNode(int level, Pattern count, Pattern from,
|
||||
TemplateNode format, String lang,
|
||||
int letterValue, String groupingSeparator, int groupingSize)
|
||||
{
|
||||
super(format, lang, letterValue, groupingSeparator, groupingSize);
|
||||
this.level = level;
|
||||
this.count = count;
|
||||
this.from = from;
|
||||
}
|
||||
|
||||
TemplateNode clone(Stylesheet stylesheet)
|
||||
{
|
||||
TemplateNode ret = new NodeNumberNode(level,
|
||||
(count == null) ? null :
|
||||
(Pattern) count.clone(stylesheet),
|
||||
(from == null) ? from :
|
||||
(Pattern) from.clone(stylesheet),
|
||||
format, lang, letterValue,
|
||||
groupingSeparator, groupingSize);
|
||||
if (children != null)
|
||||
{
|
||||
ret.children = children.clone(stylesheet);
|
||||
}
|
||||
if (next != null)
|
||||
{
|
||||
ret.next = next.clone(stylesheet);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int[] compute(Stylesheet stylesheet, Node context, int pos, int len)
|
||||
throws TransformerException
|
||||
{
|
||||
/*if (from != null)
|
||||
{
|
||||
Object ret = from.evaluate(context, pos, len);
|
||||
if (ret instanceof Collection)
|
||||
{
|
||||
Collection ns = (Collection) ret;
|
||||
if (ns.size() > 0)
|
||||
{
|
||||
List list = new ArrayList(ns);
|
||||
Collections.sort(list, documentOrderComparator);
|
||||
context = (Node) list.get(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
return new int[0];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return new int[0];
|
||||
}
|
||||
}*/
|
||||
Node current = context;
|
||||
switch (level)
|
||||
{
|
||||
case SINGLE:
|
||||
if (from == null)
|
||||
{
|
||||
while (context != null && !countMatches(current, context))
|
||||
{
|
||||
context = context.getParentNode();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
while (context != null && !countMatches(current, context) &&
|
||||
!fromMatches(context))
|
||||
{
|
||||
context = context.getParentNode();
|
||||
}
|
||||
}
|
||||
return (context == null) ? new int[0] :
|
||||
new int[] { (context == current) ? pos : getIndex(current, context) };
|
||||
case MULTIPLE:
|
||||
List ancestors = new ArrayList();
|
||||
while (context != null)
|
||||
{
|
||||
if (countMatches(current, context))
|
||||
{
|
||||
if (from == null || fromMatches(context))
|
||||
{
|
||||
ancestors.add(context);
|
||||
}
|
||||
}
|
||||
context = context.getParentNode();
|
||||
}
|
||||
Collections.sort(ancestors, documentOrderComparator);
|
||||
int[] ret = new int[ancestors.size()];
|
||||
for (int i = 0; i < ret.length; i++)
|
||||
{
|
||||
ret[i] = getIndex(current, (Node) ancestors.get(i));
|
||||
}
|
||||
return ret;
|
||||
case ANY:
|
||||
Expr preceding = new Selector(Selector.PRECEDING,
|
||||
Collections.EMPTY_LIST);
|
||||
Expr ancestorOrSelf = new Selector(Selector.ANCESTOR_OR_SELF,
|
||||
Collections.EMPTY_LIST);
|
||||
Expr any = new UnionExpr(preceding, ancestorOrSelf);
|
||||
Object eval = any.evaluate(context, pos, len);
|
||||
if (eval instanceof Collection)
|
||||
{
|
||||
Collection ns = (Collection) eval;
|
||||
List candidates = new ArrayList();
|
||||
for (Iterator i = ns.iterator(); i.hasNext(); )
|
||||
{
|
||||
Node candidate = (Node) i.next();
|
||||
if (countMatches(current, candidate))
|
||||
{
|
||||
candidates.add(candidate);
|
||||
if (from != null && from.matches(candidate))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return new int[] { candidates.size() };
|
||||
}
|
||||
return new int[0];
|
||||
default:
|
||||
throw new TransformerException("invalid level");
|
||||
}
|
||||
}
|
||||
|
||||
boolean countMatches(Node current, Node node)
|
||||
{
|
||||
if (count == null)
|
||||
{
|
||||
int cnt = current.getNodeType();
|
||||
int nnt = node.getNodeType();
|
||||
if (cnt != nnt)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (nnt == Node.ELEMENT_NODE || nnt == Node.ATTRIBUTE_NODE)
|
||||
{
|
||||
String curi = current.getNamespaceURI();
|
||||
String nuri = node.getNamespaceURI();
|
||||
if ((curi == null && nuri != null) ||
|
||||
(curi != null && !curi.equals(nuri)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
String cn = current.getLocalName();
|
||||
if (cn == null)
|
||||
{
|
||||
cn = current.getNodeName();
|
||||
}
|
||||
String nn = node.getLocalName();
|
||||
if (nn == null)
|
||||
{
|
||||
nn = node.getNodeName();
|
||||
}
|
||||
if (!cn.equals(nn))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return count.matches(node);
|
||||
}
|
||||
}
|
||||
|
||||
boolean fromMatches(Node node)
|
||||
{
|
||||
for (Node ctx = node.getParentNode(); ctx != null;
|
||||
ctx = ctx.getParentNode())
|
||||
{
|
||||
if (from.matches(ctx))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int getIndex(Node current, Node node)
|
||||
{
|
||||
int index = 0;
|
||||
do
|
||||
{
|
||||
do
|
||||
{
|
||||
node = node.getPreviousSibling();
|
||||
}
|
||||
while (node != null && !countMatches(current, node));
|
||||
index++;
|
||||
}
|
||||
while (node != null);
|
||||
return index;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
/* NumberNode.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.transform;
|
||||
|
||||
import javax.xml.transform.TransformerException;
|
||||
import org.w3c.dom.Node;
|
||||
import gnu.xml.xpath.Expr;
|
||||
|
||||
/**
|
||||
* A template node representing the XSL <code>number</code> instruction
|
||||
* with a <code>value</code> expression.
|
||||
*
|
||||
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
|
||||
*/
|
||||
final class NumberNode
|
||||
extends AbstractNumberNode
|
||||
{
|
||||
|
||||
final Expr value;
|
||||
|
||||
NumberNode(Expr value, TemplateNode format, String lang,
|
||||
int letterValue, String groupingSeparator, int groupingSize)
|
||||
{
|
||||
super(format, lang, letterValue, groupingSeparator, groupingSize);
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
TemplateNode clone(Stylesheet stylesheet)
|
||||
{
|
||||
TemplateNode ret = new NumberNode(value.clone(stylesheet),
|
||||
format, lang, letterValue,
|
||||
groupingSeparator, groupingSize);
|
||||
if (children != null)
|
||||
{
|
||||
ret.children = children.clone(stylesheet);
|
||||
}
|
||||
if (next != null)
|
||||
{
|
||||
ret.next = next.clone(stylesheet);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int[] compute(Stylesheet stylesheet, Node context, int pos, int len)
|
||||
throws TransformerException
|
||||
{
|
||||
Object ret = value.evaluate(context, pos, len);
|
||||
Double d = (ret instanceof Double) ? ((Double) ret) :
|
||||
new Double(Expr._number(context, ret));
|
||||
return new int[] { d.intValue() };
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
/* OtherwiseNode.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.transform;
|
||||
|
||||
import javax.xml.namespace.QName;
|
||||
import javax.xml.transform.TransformerException;
|
||||
import org.w3c.dom.Node;
|
||||
|
||||
/**
|
||||
* A template node representing an XSL <code>otherwise</code> instruction.
|
||||
*
|
||||
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
|
||||
*/
|
||||
final class OtherwiseNode
|
||||
extends TemplateNode
|
||||
{
|
||||
|
||||
TemplateNode clone(Stylesheet stylesheet)
|
||||
{
|
||||
TemplateNode ret = new OtherwiseNode();
|
||||
if (children != null)
|
||||
{
|
||||
ret.children = children.clone(stylesheet);
|
||||
}
|
||||
if (next != null)
|
||||
{
|
||||
ret.next = next.clone(stylesheet);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void doApply(Stylesheet stylesheet, QName mode,
|
||||
Node context, int pos, int len,
|
||||
Node parent, Node nextSibling)
|
||||
throws TransformerException
|
||||
{
|
||||
if (children != null)
|
||||
{
|
||||
children.apply(stylesheet, mode,
|
||||
context, pos, len,
|
||||
parent, nextSibling);
|
||||
}
|
||||
if (next != null)
|
||||
{
|
||||
next.apply(stylesheet, mode,
|
||||
context, pos, len,
|
||||
parent, nextSibling);
|
||||
}
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
StringBuffer buf = new StringBuffer(getClass().getName());
|
||||
buf.append('[');
|
||||
buf.append(']');
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,198 @@
|
||||
/* ParameterNode.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.transform;
|
||||
|
||||
import java.util.Collections;
|
||||
import javax.xml.namespace.QName;
|
||||
import javax.xml.transform.TransformerException;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.DocumentFragment;
|
||||
import org.w3c.dom.Node;
|
||||
import gnu.xml.xpath.Expr;
|
||||
|
||||
/**
|
||||
* A template node that sets a variable or parameter during template
|
||||
* processing.
|
||||
*
|
||||
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
|
||||
*/
|
||||
final class ParameterNode
|
||||
extends TemplateNode
|
||||
implements Comparable
|
||||
{
|
||||
|
||||
final QName name;
|
||||
final Expr select;
|
||||
final int type;
|
||||
|
||||
ParameterNode(QName name, Expr select, int type)
|
||||
{
|
||||
this.name = name;
|
||||
this.select = select;
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
TemplateNode clone(Stylesheet stylesheet)
|
||||
{
|
||||
TemplateNode ret = new ParameterNode(name,
|
||||
select.clone(stylesheet),
|
||||
type);
|
||||
if (children != null)
|
||||
{
|
||||
ret.children = children.clone(stylesheet);
|
||||
}
|
||||
if (next != null)
|
||||
{
|
||||
ret.next = next.clone(stylesheet);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void doApply(Stylesheet stylesheet, QName mode,
|
||||
Node context, int pos, int len,
|
||||
Node parent, Node nextSibling)
|
||||
throws TransformerException
|
||||
{
|
||||
// push the variable context
|
||||
stylesheet.bindings.push(type);
|
||||
// set the variable
|
||||
Object value = getValue(stylesheet, mode, context, pos, len);
|
||||
if (value != null)
|
||||
{
|
||||
stylesheet.bindings.set(name, value, type);
|
||||
if (stylesheet.debug)
|
||||
{
|
||||
System.err.println(this + ": set to " + value);
|
||||
}
|
||||
}
|
||||
// variable and param don't process children as such
|
||||
// all subsequent instructions are processed with that variable context
|
||||
if (next != null)
|
||||
{
|
||||
next.apply(stylesheet, mode,
|
||||
context, pos, len,
|
||||
parent, nextSibling);
|
||||
}
|
||||
// pop the variable context
|
||||
stylesheet.bindings.pop(type);
|
||||
}
|
||||
|
||||
Object getValue(Stylesheet stylesheet, QName mode,
|
||||
Node context, int pos, int len)
|
||||
throws TransformerException
|
||||
{
|
||||
if (select != null)
|
||||
{
|
||||
return select.evaluate(context, pos, len);
|
||||
}
|
||||
else if (children != null)
|
||||
{
|
||||
Document doc = (context instanceof Document) ? (Document) context :
|
||||
context.getOwnerDocument();
|
||||
DocumentFragment fragment = doc.createDocumentFragment();
|
||||
children.apply(stylesheet, mode, context, pos, len, fragment, null);
|
||||
return Collections.singleton(fragment);
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean references(QName var)
|
||||
{
|
||||
if (select != null && select.references(var))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return super.references(var);
|
||||
}
|
||||
|
||||
public int compareTo(Object other)
|
||||
{
|
||||
if (other instanceof ParameterNode)
|
||||
{
|
||||
ParameterNode pn = (ParameterNode) other;
|
||||
boolean r1 = references(pn.name);
|
||||
boolean r2 = pn.references(name);
|
||||
if (r1 && r2)
|
||||
{
|
||||
throw new IllegalArgumentException("circular definitions");
|
||||
}
|
||||
if (r1)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
if (r2)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
StringBuffer buf = new StringBuffer(getClass().getName());
|
||||
buf.append('[');
|
||||
buf.append("name=");
|
||||
buf.append(name);
|
||||
if (select != null)
|
||||
{
|
||||
buf.append(",select=");
|
||||
buf.append(select);
|
||||
}
|
||||
buf.append(",type=");
|
||||
switch (type)
|
||||
{
|
||||
case Bindings.VARIABLE:
|
||||
buf.append("variable");
|
||||
break;
|
||||
case Bindings.PARAM:
|
||||
buf.append("param");
|
||||
break;
|
||||
case Bindings.WITH_PARAM:
|
||||
buf.append("with-param");
|
||||
break;
|
||||
}
|
||||
buf.append(']');
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,126 @@
|
||||
/* ProcessingInstructionNode.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.transform;
|
||||
|
||||
import javax.xml.namespace.QName;
|
||||
import javax.xml.transform.TransformerException;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.DocumentFragment;
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.ProcessingInstruction;
|
||||
import gnu.xml.xpath.Expr;
|
||||
|
||||
/**
|
||||
* A template node representing the XSL <code>processing-instruction</code>
|
||||
* instruction.
|
||||
*
|
||||
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
|
||||
*/
|
||||
final class ProcessingInstructionNode
|
||||
extends TemplateNode
|
||||
{
|
||||
|
||||
final String name;
|
||||
|
||||
ProcessingInstructionNode(String name)
|
||||
{
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
TemplateNode clone(Stylesheet stylesheet)
|
||||
{
|
||||
TemplateNode ret = new ProcessingInstructionNode(name);
|
||||
if (children != null)
|
||||
{
|
||||
ret.children = children.clone(stylesheet);
|
||||
}
|
||||
if (next != null)
|
||||
{
|
||||
ret.next = next.clone(stylesheet);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void doApply(Stylesheet stylesheet, QName mode,
|
||||
Node context, int pos, int len,
|
||||
Node parent, Node nextSibling)
|
||||
throws TransformerException
|
||||
{
|
||||
String data = null;
|
||||
Document doc = (parent instanceof Document) ? (Document) parent :
|
||||
parent.getOwnerDocument();
|
||||
if (children != null)
|
||||
{
|
||||
// Create a document fragment to hold the text
|
||||
DocumentFragment fragment = doc.createDocumentFragment();
|
||||
// Apply children to the fragment
|
||||
children.apply(stylesheet, mode,
|
||||
context, pos, len,
|
||||
fragment, null);
|
||||
// Use XPath string-value of fragment
|
||||
data = Expr.stringValue(fragment);
|
||||
}
|
||||
ProcessingInstruction pi = doc.createProcessingInstruction(name, data);
|
||||
// Insert into result tree
|
||||
if (nextSibling != null)
|
||||
{
|
||||
parent.insertBefore(pi, nextSibling);
|
||||
}
|
||||
else
|
||||
{
|
||||
parent.appendChild(pi);
|
||||
}
|
||||
if (next != null)
|
||||
{
|
||||
next.apply(stylesheet, mode,
|
||||
context, pos, len,
|
||||
parent, nextSibling);
|
||||
}
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
StringBuffer buf = new StringBuffer(getClass().getName());
|
||||
buf.append('[');
|
||||
buf.append("name=");
|
||||
buf.append(name);
|
||||
buf.append(']');
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,305 @@
|
||||
/* SAXSerializer.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.transform;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import org.w3c.dom.Attr;
|
||||
import org.w3c.dom.DocumentType;
|
||||
import org.w3c.dom.NamedNodeMap;
|
||||
import org.w3c.dom.Node;
|
||||
import org.xml.sax.Attributes;
|
||||
import org.xml.sax.ContentHandler;
|
||||
import org.xml.sax.SAXException;
|
||||
import org.xml.sax.ext.LexicalHandler;
|
||||
|
||||
/**
|
||||
* Serializes a DOM node to a sequence of SAX events.
|
||||
*
|
||||
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
|
||||
*/
|
||||
class SAXSerializer
|
||||
implements Attributes
|
||||
{
|
||||
|
||||
transient NamedNodeMap attrs;
|
||||
transient LinkedList namespaces = new LinkedList();
|
||||
|
||||
boolean isDefined(String prefix, String uri)
|
||||
{
|
||||
for (Iterator i = namespaces.iterator(); i.hasNext(); )
|
||||
{
|
||||
HashMap ctx = (HashMap) i.next();
|
||||
if (uri.equals(ctx.get(prefix)))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void define(String prefix, String uri)
|
||||
{
|
||||
for (Iterator i = namespaces.iterator(); i.hasNext(); )
|
||||
{
|
||||
HashMap ctx = (HashMap) i.next();
|
||||
if (ctx.containsKey(prefix))
|
||||
{
|
||||
HashMap newCtx = new HashMap();
|
||||
newCtx.put(prefix, uri);
|
||||
namespaces.addFirst(newCtx);
|
||||
return;
|
||||
}
|
||||
}
|
||||
HashMap ctx;
|
||||
if (namespaces.isEmpty())
|
||||
{
|
||||
ctx = new HashMap();
|
||||
namespaces.add(ctx);
|
||||
}
|
||||
else
|
||||
{
|
||||
ctx = (HashMap) namespaces.getFirst();
|
||||
}
|
||||
ctx.put(prefix, uri);
|
||||
}
|
||||
|
||||
void undefine(String prefix, String uri)
|
||||
{
|
||||
for (Iterator i = namespaces.iterator(); i.hasNext(); )
|
||||
{
|
||||
HashMap ctx = (HashMap) i.next();
|
||||
if (uri.equals(ctx.get(prefix)))
|
||||
{
|
||||
ctx.remove(prefix);
|
||||
if (ctx.isEmpty())
|
||||
{
|
||||
namespaces.remove(ctx);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int getLength()
|
||||
{
|
||||
return attrs.getLength();
|
||||
}
|
||||
|
||||
public String getURI(int index)
|
||||
{
|
||||
return attrs.item(index).getNamespaceURI();
|
||||
}
|
||||
|
||||
public String getLocalName(int index)
|
||||
{
|
||||
return attrs.item(index).getLocalName();
|
||||
}
|
||||
|
||||
public String getQName(int index)
|
||||
{
|
||||
return attrs.item(index).getNodeName();
|
||||
}
|
||||
|
||||
public String getType(int index)
|
||||
{
|
||||
Attr attr = (Attr) attrs.item(index);
|
||||
return attr.isId() ? "ID" : "CDATA";
|
||||
}
|
||||
|
||||
public String getValue(int index)
|
||||
{
|
||||
return attrs.item(index).getNodeValue();
|
||||
}
|
||||
|
||||
public int getIndex(String uri, String localName)
|
||||
{
|
||||
int len = attrs.getLength();
|
||||
for (int i = 0; i < len; i++)
|
||||
{
|
||||
Node attr = attrs.item(i);
|
||||
String a_uri = attr.getNamespaceURI();
|
||||
String a_localName = attr.getLocalName();
|
||||
if (((a_uri == null && uri == null) ||
|
||||
(a_uri != null && a_uri.equals(uri))) &&
|
||||
a_localName.equals(localName))
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
public int getIndex(String qName)
|
||||
{
|
||||
int len = attrs.getLength();
|
||||
for (int i = 0; i < len; i++)
|
||||
{
|
||||
Node attr = attrs.item(i);
|
||||
String a_name = attr.getNodeName();
|
||||
if (a_name.equals(qName))
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
public String getType(String uri, String localName)
|
||||
{
|
||||
Attr attr = (Attr) attrs.getNamedItemNS(uri, localName);
|
||||
return attr.isId() ? "ID" : "CDATA";
|
||||
}
|
||||
|
||||
public String getType(String qName)
|
||||
{
|
||||
Attr attr = (Attr) attrs.getNamedItem(qName);
|
||||
return attr.isId() ? "ID" : "CDATA";
|
||||
}
|
||||
|
||||
public String getValue(String uri, String localName)
|
||||
{
|
||||
return attrs.getNamedItemNS(uri, localName).getNodeValue();
|
||||
}
|
||||
|
||||
public String getValue(String qName)
|
||||
{
|
||||
return attrs.getNamedItem(qName).getNodeValue();
|
||||
}
|
||||
|
||||
void serialize(Node node, ContentHandler ch, LexicalHandler lh)
|
||||
throws SAXException
|
||||
{
|
||||
attrs = node.getAttributes();
|
||||
Node children;
|
||||
Node next = node.getNextSibling();
|
||||
switch (node.getNodeType())
|
||||
{
|
||||
case Node.ELEMENT_NODE:
|
||||
String uri = node.getNamespaceURI();
|
||||
String prefix = node.getPrefix();
|
||||
boolean defined = isDefined(prefix, uri);
|
||||
if (!defined)
|
||||
{
|
||||
define(prefix, uri);
|
||||
ch.startPrefixMapping(prefix, uri);
|
||||
}
|
||||
String localName = node.getLocalName();
|
||||
String qName = node.getNodeName();
|
||||
ch.startElement(uri, localName, qName, this);
|
||||
children = node.getFirstChild();
|
||||
if (children != null)
|
||||
{
|
||||
serialize(children, ch, lh);
|
||||
}
|
||||
ch.endElement(uri, localName, qName);
|
||||
if (!defined)
|
||||
{
|
||||
ch.endPrefixMapping(prefix);
|
||||
undefine(prefix, uri);
|
||||
}
|
||||
break;
|
||||
case Node.TEXT_NODE:
|
||||
char[] chars = node.getNodeValue().toCharArray();
|
||||
ch.characters(chars, 0, chars.length);
|
||||
break;
|
||||
case Node.CDATA_SECTION_NODE:
|
||||
char[] cdata = node.getNodeValue().toCharArray();
|
||||
if (lh != null)
|
||||
{
|
||||
lh.startCDATA();
|
||||
ch.characters(cdata, 0, cdata.length);
|
||||
lh.endCDATA();
|
||||
}
|
||||
else
|
||||
{
|
||||
ch.characters(cdata, 0, cdata.length);
|
||||
}
|
||||
break;
|
||||
case Node.COMMENT_NODE:
|
||||
if (lh != null)
|
||||
{
|
||||
char[] comment = node.getNodeValue().toCharArray();
|
||||
lh.comment(comment, 0, comment.length);
|
||||
}
|
||||
break;
|
||||
case Node.DOCUMENT_NODE:
|
||||
case Node.DOCUMENT_FRAGMENT_NODE:
|
||||
ch.startDocument();
|
||||
children = node.getFirstChild();
|
||||
if (children != null)
|
||||
{
|
||||
serialize(children, ch, lh);
|
||||
}
|
||||
ch.endDocument();
|
||||
break;
|
||||
case Node.DOCUMENT_TYPE_NODE:
|
||||
if (lh != null)
|
||||
{
|
||||
DocumentType doctype = (DocumentType) node;
|
||||
String publicId = doctype.getPublicId();
|
||||
String systemId = doctype.getSystemId();
|
||||
lh.startDTD(node.getNodeName(), publicId, systemId);
|
||||
NamedNodeMap entities = doctype.getEntities();
|
||||
int len = entities.getLength();
|
||||
for (int i = 0; i < len; i++)
|
||||
{
|
||||
Node entity = entities.item(i);
|
||||
String entityName = entity.getNodeName();
|
||||
lh.startEntity(entityName);
|
||||
lh.endEntity(entityName);
|
||||
}
|
||||
lh.endDTD();
|
||||
}
|
||||
break;
|
||||
case Node.PROCESSING_INSTRUCTION_NODE:
|
||||
ch.processingInstruction(node.getNodeName(), node.getNodeValue());
|
||||
break;
|
||||
case Node.ENTITY_REFERENCE_NODE:
|
||||
ch.skippedEntity(node.getNodeName());
|
||||
break;
|
||||
}
|
||||
attrs = null;
|
||||
if (next != null)
|
||||
{
|
||||
serialize(next, ch, lh);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,179 @@
|
||||
/* SortKey.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.transform;
|
||||
|
||||
import javax.xml.namespace.QName;
|
||||
import javax.xml.transform.TransformerException;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.DocumentFragment;
|
||||
import org.w3c.dom.Node;
|
||||
import gnu.xml.xpath.Expr;
|
||||
|
||||
/**
|
||||
* An XSL sort key.
|
||||
*
|
||||
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
|
||||
*/
|
||||
final class SortKey
|
||||
{
|
||||
|
||||
static final int DEFAULT = 0;
|
||||
static final int UPPER_FIRST = 1;
|
||||
static final int LOWER_FIRST = 2;
|
||||
|
||||
final Expr select;
|
||||
final TemplateNode langTemplate;
|
||||
final TemplateNode dataTypeTemplate;
|
||||
final TemplateNode orderTemplate;
|
||||
final TemplateNode caseOrderTemplate;
|
||||
|
||||
transient String lang;
|
||||
transient String dataType;
|
||||
transient boolean descending;
|
||||
transient int caseOrder;
|
||||
|
||||
SortKey(Expr select, TemplateNode lang, TemplateNode dataType,
|
||||
TemplateNode order, TemplateNode caseOrder)
|
||||
{
|
||||
this.select = select;
|
||||
this.langTemplate = lang;
|
||||
this.dataTypeTemplate = dataType;
|
||||
this.orderTemplate = order;
|
||||
this.caseOrderTemplate = caseOrder;
|
||||
}
|
||||
|
||||
String key(Node node)
|
||||
{
|
||||
Object ret = select.evaluate(node, 1, 1);
|
||||
if (ret instanceof String)
|
||||
{
|
||||
return (String) ret;
|
||||
}
|
||||
else
|
||||
{
|
||||
return Expr._string(node, ret);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare for a sort.
|
||||
* This sets all transient variables from their AVTs.
|
||||
*/
|
||||
void init(Stylesheet stylesheet, QName mode,
|
||||
Node context, int pos, int len,
|
||||
Node parent, Node nextSibling)
|
||||
throws TransformerException
|
||||
{
|
||||
Document doc = (context instanceof Document) ? (Document) context :
|
||||
context.getOwnerDocument();
|
||||
if (langTemplate == null)
|
||||
{
|
||||
lang = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
DocumentFragment fragment = doc.createDocumentFragment();
|
||||
langTemplate.apply(stylesheet, mode, context, pos, len,
|
||||
fragment, null);
|
||||
lang = Expr.stringValue(fragment);
|
||||
}
|
||||
if (dataTypeTemplate == null)
|
||||
{
|
||||
dataType = "text";
|
||||
}
|
||||
else
|
||||
{
|
||||
DocumentFragment fragment = doc.createDocumentFragment();
|
||||
dataTypeTemplate.apply(stylesheet, mode, context, pos, len,
|
||||
fragment, null);
|
||||
dataType = Expr.stringValue(fragment);
|
||||
}
|
||||
if (orderTemplate == null)
|
||||
{
|
||||
descending = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
DocumentFragment fragment = doc.createDocumentFragment();
|
||||
orderTemplate.apply(stylesheet, mode, context, pos, len,
|
||||
fragment, null);
|
||||
String order = Expr.stringValue(fragment);
|
||||
descending = "descending".equals(order);
|
||||
}
|
||||
if (caseOrderTemplate == null)
|
||||
{
|
||||
caseOrder = DEFAULT;
|
||||
}
|
||||
else
|
||||
{
|
||||
DocumentFragment fragment = doc.createDocumentFragment();
|
||||
caseOrderTemplate.apply(stylesheet, mode, context, pos, len,
|
||||
fragment, null);
|
||||
String co = Expr.stringValue(fragment);
|
||||
caseOrder = "upper-first".equals(co) ? UPPER_FIRST :
|
||||
"lower-first".equals(co) ? LOWER_FIRST :
|
||||
DEFAULT;
|
||||
}
|
||||
}
|
||||
|
||||
boolean references(QName var)
|
||||
{
|
||||
if (select != null && select.references(var))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (langTemplate != null && langTemplate.references(var))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (dataTypeTemplate != null && dataTypeTemplate.references(var))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (orderTemplate != null && orderTemplate.references(var))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (caseOrderTemplate != null && caseOrderTemplate.references(var))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,762 @@
|
||||
/* StreamSerializer.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.transform;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.CharBuffer;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.charset.CharsetEncoder;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import javax.xml.XMLConstants;
|
||||
import org.w3c.dom.Attr;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.DocumentType;
|
||||
import org.w3c.dom.NamedNodeMap;
|
||||
import org.w3c.dom.Node;
|
||||
|
||||
/**
|
||||
* Serializes a DOM node to an output stream.
|
||||
*
|
||||
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
|
||||
*/
|
||||
public class StreamSerializer
|
||||
{
|
||||
|
||||
static final int SPACE = 0x20;
|
||||
static final int BANG = 0x21; // !
|
||||
static final int APOS = 0x27; // '
|
||||
static final int SLASH = 0x2f; // /
|
||||
static final int BRA = 0x3c; // <
|
||||
static final int KET = 0x3e; // >
|
||||
static final int EQ = 0x3d; // =
|
||||
|
||||
/**
|
||||
* HTML 4.01 boolean attributes
|
||||
*/
|
||||
static final Map HTML_BOOLEAN_ATTRIBUTES = new HashMap();
|
||||
static
|
||||
{
|
||||
HashSet set;
|
||||
|
||||
set = new HashSet();
|
||||
set.add("nohref");
|
||||
HTML_BOOLEAN_ATTRIBUTES.put("area", set);
|
||||
|
||||
set = new HashSet();
|
||||
set.add("ismap");
|
||||
HTML_BOOLEAN_ATTRIBUTES.put("img", set);
|
||||
|
||||
set = new HashSet();
|
||||
set.add("declare");
|
||||
HTML_BOOLEAN_ATTRIBUTES.put("object", set);
|
||||
|
||||
set = new HashSet();
|
||||
set.add("noshade");
|
||||
HTML_BOOLEAN_ATTRIBUTES.put("hr", set);
|
||||
|
||||
set = new HashSet();
|
||||
set.add("compact");
|
||||
HTML_BOOLEAN_ATTRIBUTES.put("dl", set);
|
||||
HTML_BOOLEAN_ATTRIBUTES.put("ol", set);
|
||||
HTML_BOOLEAN_ATTRIBUTES.put("ul", set);
|
||||
HTML_BOOLEAN_ATTRIBUTES.put("dir", set);
|
||||
HTML_BOOLEAN_ATTRIBUTES.put("menu", set);
|
||||
|
||||
set = new HashSet();
|
||||
set.add("checked");
|
||||
set.add("disabled");
|
||||
set.add("readonly");
|
||||
set.add("ismap");
|
||||
HTML_BOOLEAN_ATTRIBUTES.put("input", set);
|
||||
|
||||
set = new HashSet();
|
||||
set.add("multiple");
|
||||
set.add("disabled");
|
||||
HTML_BOOLEAN_ATTRIBUTES.put("select", set);
|
||||
|
||||
set = new HashSet();
|
||||
set.add("disabled");
|
||||
HTML_BOOLEAN_ATTRIBUTES.put("optgroup", set);
|
||||
|
||||
set = new HashSet();
|
||||
set.add("selected");
|
||||
set.add("disabled");
|
||||
HTML_BOOLEAN_ATTRIBUTES.put("option", set);
|
||||
|
||||
set = new HashSet();
|
||||
set.add("disabled");
|
||||
set.add("readonly");
|
||||
HTML_BOOLEAN_ATTRIBUTES.put("textarea", set);
|
||||
|
||||
set = new HashSet();
|
||||
set.add("disabled");
|
||||
HTML_BOOLEAN_ATTRIBUTES.put("button", set);
|
||||
|
||||
set = new HashSet();
|
||||
set.add("nowrap");
|
||||
HTML_BOOLEAN_ATTRIBUTES.put("th", set);
|
||||
HTML_BOOLEAN_ATTRIBUTES.put("td", set);
|
||||
|
||||
set = new HashSet();
|
||||
set.add("noresize");
|
||||
HTML_BOOLEAN_ATTRIBUTES.put("frame", set);
|
||||
|
||||
set = new HashSet();
|
||||
set.add("defer");
|
||||
HTML_BOOLEAN_ATTRIBUTES.put("script", set);
|
||||
}
|
||||
|
||||
protected final String encoding;
|
||||
final Charset charset;
|
||||
final CharsetEncoder encoder;
|
||||
final int mode;
|
||||
final Map namespaces;
|
||||
protected String eol;
|
||||
Collection cdataSectionElements = Collections.EMPTY_SET;
|
||||
|
||||
protected boolean discardDefaultContent;
|
||||
protected boolean xmlDeclaration = true;
|
||||
|
||||
public StreamSerializer()
|
||||
{
|
||||
this(Stylesheet.OUTPUT_XML, null, null);
|
||||
}
|
||||
|
||||
public StreamSerializer(String encoding)
|
||||
{
|
||||
this(Stylesheet.OUTPUT_XML, encoding, null);
|
||||
}
|
||||
|
||||
public StreamSerializer(int mode, String encoding, String eol)
|
||||
{
|
||||
this.mode = mode;
|
||||
if (encoding == null)
|
||||
{
|
||||
encoding = "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();
|
||||
}
|
||||
|
||||
void setCdataSectionElements(Collection c)
|
||||
{
|
||||
cdataSectionElements = c;
|
||||
}
|
||||
|
||||
public void serialize(final Node node, final OutputStream out)
|
||||
throws IOException
|
||||
{
|
||||
serialize(node, out, false);
|
||||
}
|
||||
|
||||
void serialize(Node node, final OutputStream out,
|
||||
boolean convertToCdata)
|
||||
throws IOException
|
||||
{
|
||||
while (node != null)
|
||||
{
|
||||
Node next = node.getNextSibling();
|
||||
doSerialize(node, out, convertToCdata);
|
||||
node = next;
|
||||
}
|
||||
}
|
||||
|
||||
private void doSerialize(final Node node, final OutputStream out,
|
||||
boolean convertToCdata)
|
||||
throws IOException
|
||||
{
|
||||
if (out == null)
|
||||
{
|
||||
throw new NullPointerException("no output stream");
|
||||
}
|
||||
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;
|
||||
}
|
||||
switch (nt)
|
||||
{
|
||||
case Node.ATTRIBUTE_NODE:
|
||||
prefix = node.getPrefix();
|
||||
if (XMLConstants.XMLNS_ATTRIBUTE_NS_URI.equals(uri) ||
|
||||
XMLConstants.XMLNS_ATTRIBUTE.equals(prefix) ||
|
||||
(prefix != null && prefix.startsWith("xmlns:")))
|
||||
{
|
||||
String nsuri = node.getNodeValue();
|
||||
if (isDefined(nsuri))
|
||||
{
|
||||
break;
|
||||
}
|
||||
String name = node.getLocalName();
|
||||
if (name == null)
|
||||
{
|
||||
name = node.getNodeName();
|
||||
}
|
||||
define(nsuri, name);
|
||||
}
|
||||
else if (uri != null && !isDefined(uri))
|
||||
{
|
||||
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) + "'";
|
||||
out.write(nsvalue.getBytes(encoding));
|
||||
defined = true;
|
||||
}
|
||||
out.write(SPACE);
|
||||
String a_nodeName = node.getNodeName();
|
||||
out.write(encodeText(a_nodeName));
|
||||
String a_nodeValue = node.getNodeValue();
|
||||
if (mode == Stylesheet.OUTPUT_HTML &&
|
||||
a_nodeName.equals(a_nodeValue) &&
|
||||
isHTMLBoolean((Attr) node, a_nodeName))
|
||||
{
|
||||
break;
|
||||
}
|
||||
out.write(EQ);
|
||||
value = "'" + encode(a_nodeValue, true, true) + "'";
|
||||
out.write(encodeText(value));
|
||||
break;
|
||||
case Node.ELEMENT_NODE:
|
||||
value = node.getNodeName();
|
||||
out.write(BRA);
|
||||
out.write(encodeText(value));
|
||||
if (uri != null && !isDefined(uri))
|
||||
{
|
||||
prefix = define(uri, node.getPrefix());
|
||||
String nsname = (prefix == null) ? "xmlns" : "xmlns:" + prefix;
|
||||
out.write(SPACE);
|
||||
out.write(encodeText(nsname));
|
||||
out.write(EQ);
|
||||
String nsvalue = "'" + encode(uri, true, true) + "'";
|
||||
out.write(encodeText(nsvalue));
|
||||
defined = true;
|
||||
}
|
||||
NamedNodeMap attrs = node.getAttributes();
|
||||
if (attrs != null)
|
||||
{
|
||||
int len = attrs.getLength();
|
||||
for (int i = 0; i < len; i++)
|
||||
{
|
||||
Attr attr = (Attr) attrs.item(i);
|
||||
if (discardDefaultContent && !attr.getSpecified())
|
||||
{
|
||||
// NOOP
|
||||
}
|
||||
else
|
||||
{
|
||||
serialize(attr, out, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
convertToCdata = cdataSectionElements.contains(value);
|
||||
children = node.getFirstChild();
|
||||
if (children == null)
|
||||
{
|
||||
out.write(SLASH);
|
||||
out.write(KET);
|
||||
}
|
||||
else
|
||||
{
|
||||
out.write(KET);
|
||||
serialize(children, out, convertToCdata);
|
||||
out.write(BRA);
|
||||
out.write(SLASH);
|
||||
out.write(encodeText(value));
|
||||
out.write(KET);
|
||||
}
|
||||
break;
|
||||
case Node.TEXT_NODE:
|
||||
value = node.getNodeValue();
|
||||
if (!"yes".equals(node.getUserData("disable-output-escaping")))
|
||||
{
|
||||
value = encode(value, false, false);
|
||||
}
|
||||
out.write(encodeText(value));
|
||||
break;
|
||||
case Node.CDATA_SECTION_NODE:
|
||||
value = "<![CDATA[" + node.getNodeValue() + "]]>";
|
||||
out.write(encodeText(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));
|
||||
}
|
||||
break;
|
||||
case Node.DOCUMENT_NODE:
|
||||
case Node.DOCUMENT_FRAGMENT_NODE:
|
||||
if (mode == Stylesheet.OUTPUT_XML)
|
||||
{
|
||||
if ("UTF-16".equalsIgnoreCase(encoding))
|
||||
{
|
||||
out.write(0xfe);
|
||||
out.write(0xff);
|
||||
}
|
||||
if (!"yes".equals(node.getUserData("omit-xml-declaration")) &&
|
||||
xmlDeclaration)
|
||||
{
|
||||
Document doc = (node instanceof Document) ?
|
||||
(Document) node : null;
|
||||
String version = (doc != null) ? doc.getXmlVersion() : null;
|
||||
if (version == null)
|
||||
{
|
||||
version = (String) node.getUserData("version");
|
||||
}
|
||||
if (version == null)
|
||||
{
|
||||
version = "1.0";
|
||||
}
|
||||
out.write(BRA);
|
||||
out.write(0x3f);
|
||||
out.write("xml version='".getBytes("US-ASCII"));
|
||||
out.write(version.getBytes("US-ASCII"));
|
||||
out.write(APOS);
|
||||
if (!("UTF-8".equalsIgnoreCase(encoding)))
|
||||
{
|
||||
out.write(" encoding='".getBytes("US-ASCII"));
|
||||
out.write(encoding.getBytes("US-ASCII"));
|
||||
out.write(APOS);
|
||||
}
|
||||
if ((doc != null && doc.getXmlStandalone()) ||
|
||||
"yes".equals(node.getUserData("standalone")))
|
||||
{
|
||||
out.write(" standalone='yes'".getBytes("US-ASCII"));
|
||||
}
|
||||
out.write(0x3f);
|
||||
out.write(KET);
|
||||
out.write(encodeText(eol));
|
||||
}
|
||||
// TODO warn if not outputting the declaration would be a
|
||||
// problem
|
||||
}
|
||||
else if (mode == Stylesheet.OUTPUT_HTML)
|
||||
{
|
||||
// Ensure that encoding is accessible
|
||||
String mediaType = (String) node.getUserData("media-type");
|
||||
if (mediaType == null)
|
||||
{
|
||||
mediaType = "text/html";
|
||||
}
|
||||
String contentType = mediaType + "; charset=" +
|
||||
((encoding.indexOf(' ') != -1) ?
|
||||
"\"" + encoding + "\"" :
|
||||
encoding);
|
||||
Document doc = (node instanceof Document) ? (Document) node :
|
||||
node.getOwnerDocument();
|
||||
Node html = null;
|
||||
for (Node ctx = node.getFirstChild(); ctx != null;
|
||||
ctx = ctx.getNextSibling())
|
||||
{
|
||||
if (ctx.getNodeType() == Node.ELEMENT_NODE)
|
||||
{
|
||||
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 (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;
|
||||
for (Node ctx = html.getFirstChild(); ctx != null;
|
||||
ctx = ctx.getNextSibling())
|
||||
{
|
||||
if (ctx.getNodeType() == Node.ELEMENT_NODE)
|
||||
{
|
||||
c1 = 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)
|
||||
{
|
||||
String name = ctx.getLocalName();
|
||||
if (name == null)
|
||||
{
|
||||
name = ctx.getNodeName();
|
||||
}
|
||||
if ("meta".equalsIgnoreCase(name))
|
||||
{
|
||||
NamedNodeMap metaAttrs = ctx.getAttributes();
|
||||
int len = metaAttrs.getLength();
|
||||
String httpEquiv = null;
|
||||
Node content = null;
|
||||
for (int i = 0; i < len; i++)
|
||||
{
|
||||
Node attr = metaAttrs.item(i);
|
||||
String attrName = attr.getNodeName();
|
||||
if ("http-equiv".equalsIgnoreCase(attrName))
|
||||
{
|
||||
httpEquiv = attr.getNodeValue();
|
||||
}
|
||||
else if ("content".equalsIgnoreCase(attrName))
|
||||
{
|
||||
content = attr;
|
||||
}
|
||||
}
|
||||
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);
|
||||
// phew
|
||||
}
|
||||
children = node.getFirstChild();
|
||||
if (children != null)
|
||||
{
|
||||
serialize(children, out, convertToCdata);
|
||||
}
|
||||
break;
|
||||
case Node.DOCUMENT_TYPE_NODE:
|
||||
DocumentType doctype = (DocumentType) node;
|
||||
out.write(BRA);
|
||||
out.write(BANG);
|
||||
out.write(encodeText("DOCTYPE "));
|
||||
value = doctype.getNodeName();
|
||||
out.write(encodeText(value));
|
||||
String publicId = doctype.getPublicId();
|
||||
if (publicId != null)
|
||||
{
|
||||
out.write(encodeText(" PUBLIC "));
|
||||
out.write(APOS);
|
||||
out.write(encodeText(publicId));
|
||||
out.write(APOS);
|
||||
}
|
||||
String systemId = doctype.getSystemId();
|
||||
if (systemId != null)
|
||||
{
|
||||
out.write(encodeText(" SYSTEM "));
|
||||
out.write(APOS);
|
||||
out.write(encodeText(systemId));
|
||||
out.write(APOS);
|
||||
}
|
||||
String internalSubset = doctype.getInternalSubset();
|
||||
if (internalSubset != null)
|
||||
{
|
||||
out.write(encodeText(internalSubset));
|
||||
}
|
||||
out.write(KET);
|
||||
out.write(eol.getBytes(encoding));
|
||||
break;
|
||||
case Node.ENTITY_REFERENCE_NODE:
|
||||
value = "&" + node.getNodeValue() + ";";
|
||||
out.write(encodeText(value));
|
||||
break;
|
||||
case Node.PROCESSING_INSTRUCTION_NODE:
|
||||
value = "<?" + node.getNodeName() + " " + node.getNodeValue() + "?>";
|
||||
out.write(encodeText(value));
|
||||
Node pp = node.getParentNode();
|
||||
if (pp != null && pp.getNodeType() == Node.DOCUMENT_NODE)
|
||||
{
|
||||
out.write(encodeText(eol));
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (defined)
|
||||
{
|
||||
undefine(uri);
|
||||
}
|
||||
}
|
||||
|
||||
boolean isDefined(String uri)
|
||||
{
|
||||
return XMLConstants.XML_NS_URI.equals(uri) ||
|
||||
XMLConstants.XMLNS_ATTRIBUTE_NS_URI.equals(uri) ||
|
||||
namespaces.containsKey(uri);
|
||||
}
|
||||
|
||||
String define(String uri, String prefix)
|
||||
{
|
||||
while (namespaces.containsValue(prefix))
|
||||
{
|
||||
// Fabricate new prefix
|
||||
prefix = prefix + "_";
|
||||
}
|
||||
namespaces.put(uri, prefix);
|
||||
return prefix;
|
||||
}
|
||||
|
||||
void undefine(String uri)
|
||||
{
|
||||
namespaces.remove(uri);
|
||||
}
|
||||
|
||||
final byte[] encodeText(String text)
|
||||
throws IOException
|
||||
{
|
||||
encoder.reset();
|
||||
if (!encoder.canEncode(text))
|
||||
{
|
||||
// Check each character
|
||||
StringBuffer buf = new StringBuffer();
|
||||
int len = text.length();
|
||||
for (int i = 0; i < len; i++)
|
||||
{
|
||||
char c = text.charAt(i);
|
||||
if (encoder.canEncode(c))
|
||||
{
|
||||
buf.append(c);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Replace with character entity reference
|
||||
String hex = Integer.toHexString((int) c);
|
||||
buf.append("&#x");
|
||||
buf.append(hex);
|
||||
buf.append(';');
|
||||
}
|
||||
}
|
||||
text = buf.toString();
|
||||
}
|
||||
ByteBuffer encoded = encoder.encode(CharBuffer.wrap(text));
|
||||
int len = encoded.limit() - encoded.position();
|
||||
if (encoded.hasArray())
|
||||
{
|
||||
byte[] ret = encoded.array();
|
||||
if (ret.length > len)
|
||||
{
|
||||
// Why?
|
||||
byte[] ret2 = new byte[len];
|
||||
System.arraycopy(ret, 0, ret2, 0, len);
|
||||
ret = ret2;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
encoded.flip();
|
||||
byte[] ret = new byte[len];
|
||||
encoded.get(ret, 0, len);
|
||||
return ret;
|
||||
}
|
||||
|
||||
String encode(String text, boolean encodeCtl, boolean inAttr)
|
||||
{
|
||||
int len = text.length();
|
||||
StringBuffer buf = null;
|
||||
for (int i = 0; i < len; i++)
|
||||
{
|
||||
char c = text.charAt(i);
|
||||
if (c == '<')
|
||||
{
|
||||
if (buf == null)
|
||||
{
|
||||
buf = new StringBuffer(text.substring(0, i));
|
||||
}
|
||||
buf.append("<");
|
||||
}
|
||||
else if (c == '>')
|
||||
{
|
||||
if (buf == null)
|
||||
{
|
||||
buf = new StringBuffer(text.substring(0, i));
|
||||
}
|
||||
buf.append(">");
|
||||
}
|
||||
else if (c == '&')
|
||||
{
|
||||
if (mode == Stylesheet.OUTPUT_HTML && (i + 1) < len &&
|
||||
text.charAt(i + 1) == '{')
|
||||
{
|
||||
if (buf != null)
|
||||
{
|
||||
buf.append(c);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (buf == null)
|
||||
{
|
||||
buf = new StringBuffer(text.substring(0, i));
|
||||
}
|
||||
buf.append("&");
|
||||
}
|
||||
}
|
||||
else if (c == '\'' && inAttr)
|
||||
{
|
||||
if (buf == null)
|
||||
{
|
||||
buf = new StringBuffer(text.substring(0, i));
|
||||
}
|
||||
buf.append("'");
|
||||
}
|
||||
else if (c == '"' && inAttr)
|
||||
{
|
||||
if (buf == null)
|
||||
{
|
||||
buf = new StringBuffer(text.substring(0, i));
|
||||
}
|
||||
buf.append(""");
|
||||
}
|
||||
else if (encodeCtl)
|
||||
{
|
||||
if (c < 0x20)
|
||||
{
|
||||
if (buf == null)
|
||||
{
|
||||
buf = new StringBuffer(text.substring(0, i));
|
||||
}
|
||||
buf.append('&');
|
||||
buf.append('#');
|
||||
buf.append((int) c);
|
||||
buf.append(';');
|
||||
}
|
||||
else if (buf != null)
|
||||
{
|
||||
buf.append(c);
|
||||
}
|
||||
}
|
||||
else if (buf != null)
|
||||
{
|
||||
buf.append(c);
|
||||
}
|
||||
}
|
||||
return (buf == null) ? text : buf.toString();
|
||||
}
|
||||
|
||||
String toString(Node node)
|
||||
{
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
try
|
||||
{
|
||||
serialize(node, out);
|
||||
return new String(out.toByteArray(), encoding);
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
throw new RuntimeException(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
boolean isHTMLBoolean(Attr attr, String attrName)
|
||||
{
|
||||
attrName = attrName.toLowerCase();
|
||||
Node element = attr.getOwnerElement();
|
||||
String elementName = element.getLocalName();
|
||||
if (elementName == null)
|
||||
{
|
||||
elementName = element.getNodeName();
|
||||
}
|
||||
elementName = elementName.toLowerCase();
|
||||
Collection attributes =
|
||||
(Collection) HTML_BOOLEAN_ATTRIBUTES.get(elementName);
|
||||
return (attributes != null && attributes.contains(attrName));
|
||||
}
|
||||
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,141 @@
|
||||
/* SystemPropertyFunction.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.transform;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import javax.xml.namespace.QName;
|
||||
import javax.xml.xpath.XPathFunction;
|
||||
import javax.xml.xpath.XPathFunctionException;
|
||||
import org.w3c.dom.Node;
|
||||
import gnu.xml.xpath.Expr;
|
||||
import gnu.xml.xpath.Function;
|
||||
|
||||
/**
|
||||
* The XSLT <code>system-property()</code>function.
|
||||
*
|
||||
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
|
||||
*/
|
||||
final class SystemPropertyFunction
|
||||
extends Expr
|
||||
implements XPathFunction, Function
|
||||
{
|
||||
|
||||
List args;
|
||||
|
||||
public Object evaluate(List args)
|
||||
throws XPathFunctionException
|
||||
{
|
||||
String name = (String) args.get(0);
|
||||
return systemProperty(QName.valueOf(name));
|
||||
}
|
||||
|
||||
public void setArguments(List args)
|
||||
{
|
||||
this.args = args;
|
||||
}
|
||||
|
||||
public Object evaluate(Node context, int pos, int len)
|
||||
{
|
||||
int arity = args.size();
|
||||
List values = new ArrayList(arity);
|
||||
for (int i = 0; i < arity; i++)
|
||||
{
|
||||
Expr arg = (Expr) args.get(i);
|
||||
values.add(arg.evaluate(context, pos, len));
|
||||
}
|
||||
String name = _string(context, values.get(0));
|
||||
return systemProperty(QName.valueOf(name));
|
||||
}
|
||||
|
||||
Object systemProperty(QName name)
|
||||
{
|
||||
String localName = name.getLocalPart();
|
||||
String prefix = name.getPrefix();
|
||||
String uri = name.getNamespaceURI();
|
||||
if (Stylesheet.XSL_NS.equals(uri) ||
|
||||
"xsl".equals(prefix))
|
||||
{
|
||||
if ("version".equals(localName))
|
||||
{
|
||||
return new Double(1.0d);
|
||||
}
|
||||
else if ("vendor".equals(localName))
|
||||
{
|
||||
return "The Free Software Foundation";
|
||||
}
|
||||
else if ("vendor-url".equals(localName))
|
||||
{
|
||||
return "http://www.gnu.org/";
|
||||
}
|
||||
else
|
||||
{
|
||||
return "";
|
||||
}
|
||||
}
|
||||
return System.getProperty(localName);
|
||||
}
|
||||
|
||||
public Expr clone(Object context)
|
||||
{
|
||||
SystemPropertyFunction f = new SystemPropertyFunction();
|
||||
int len = args.size();
|
||||
List args2 = new ArrayList(len);
|
||||
for (int i = 0; i < len; i++)
|
||||
{
|
||||
args2.add(((Expr) args.get(i)).clone(context));
|
||||
}
|
||||
f.setArguments(args2);
|
||||
return f;
|
||||
}
|
||||
|
||||
public boolean references(QName var)
|
||||
{
|
||||
for (Iterator i = args.iterator(); i.hasNext(); )
|
||||
{
|
||||
if (((Expr) i.next()).references(var))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,252 @@
|
||||
/* Template.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.transform;
|
||||
|
||||
import java.io.PrintStream;
|
||||
import javax.xml.namespace.QName;
|
||||
import javax.xml.transform.TransformerException;
|
||||
import org.w3c.dom.Node;
|
||||
import gnu.xml.xpath.Expr;
|
||||
import gnu.xml.xpath.NameTest;
|
||||
import gnu.xml.xpath.NodeTypeTest;
|
||||
import gnu.xml.xpath.Pattern;
|
||||
import gnu.xml.xpath.Selector;
|
||||
import gnu.xml.xpath.Test;
|
||||
|
||||
/**
|
||||
* A template in an XSL stylesheet.
|
||||
*
|
||||
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
|
||||
*/
|
||||
class Template
|
||||
implements Comparable
|
||||
{
|
||||
|
||||
static final double DEFAULT_PRIORITY = 0.5d;
|
||||
|
||||
final Stylesheet stylesheet;
|
||||
final QName name;
|
||||
final Pattern match;
|
||||
final TemplateNode node;
|
||||
final double priority;
|
||||
final int precedence;
|
||||
final QName mode;
|
||||
|
||||
Template(Stylesheet stylesheet,
|
||||
QName name, Pattern match, TemplateNode node,
|
||||
int precedence, double priority, QName mode)
|
||||
{
|
||||
this.stylesheet = stylesheet;
|
||||
this.name = name;
|
||||
this.match = match;
|
||||
this.node = node;
|
||||
// adjust priority if necessary
|
||||
// see XSLT section 5.5
|
||||
Test test = getNodeTest(match);
|
||||
if (test != null)
|
||||
{
|
||||
if (test instanceof NameTest)
|
||||
{
|
||||
NameTest nameTest = (NameTest) test;
|
||||
if (nameTest.matchesAny() ||
|
||||
nameTest.matchesAnyLocalName())
|
||||
{
|
||||
priority = -0.25d;
|
||||
}
|
||||
else
|
||||
{
|
||||
priority = 0.0d;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
NodeTypeTest nodeTypeTest = (NodeTypeTest) test;
|
||||
if (nodeTypeTest.getNodeType() ==
|
||||
Node.PROCESSING_INSTRUCTION_NODE &&
|
||||
nodeTypeTest.getData() != null)
|
||||
{
|
||||
priority = 0.0d;
|
||||
}
|
||||
else
|
||||
{
|
||||
priority = -0.5d;
|
||||
}
|
||||
}
|
||||
}
|
||||
this.precedence = precedence;
|
||||
this.priority = priority;
|
||||
this.mode = mode;
|
||||
}
|
||||
|
||||
Template clone(Stylesheet stylesheet)
|
||||
{
|
||||
// FIXME by cloning we lose the imports() functionality, so
|
||||
// apply-imports will be broken.
|
||||
return new Template(stylesheet,
|
||||
name,
|
||||
(match == null) ? null :
|
||||
(Pattern) match.clone(stylesheet),
|
||||
(node == null) ? null : node.clone(stylesheet),
|
||||
precedence,
|
||||
priority,
|
||||
mode);
|
||||
}
|
||||
|
||||
public int compareTo(Object other)
|
||||
{
|
||||
if (other instanceof Template)
|
||||
{
|
||||
Template t = (Template) other;
|
||||
int d = t.precedence - precedence;
|
||||
if (d != 0)
|
||||
{
|
||||
return d;
|
||||
}
|
||||
double d2 = t.priority - priority;
|
||||
if (d2 != 0.0d)
|
||||
{
|
||||
return (int) Math.round(d2 * 1000.0d);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
Test getNodeTest(Expr expr)
|
||||
{
|
||||
if (expr instanceof Selector)
|
||||
{
|
||||
Selector selector = (Selector) expr;
|
||||
Test[] tests = selector.getTests();
|
||||
if (tests.length > 0)
|
||||
{
|
||||
return tests[0];
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
boolean matches(QName mode, Node node)
|
||||
{
|
||||
if ((mode == null && this.mode != null) ||
|
||||
(mode != null && !mode.equals(this.mode)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (match == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return match.matches(node);
|
||||
}
|
||||
|
||||
boolean matches(QName name)
|
||||
{
|
||||
return name.equals(this.name);
|
||||
}
|
||||
|
||||
boolean imports(Template other)
|
||||
{
|
||||
for (Stylesheet ctx = other.stylesheet.parent;
|
||||
ctx != null;
|
||||
ctx = ctx.parent)
|
||||
{
|
||||
if (ctx == stylesheet)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param stylesheet the stylesheet
|
||||
* @param parent the parent of result nodes
|
||||
* @param context the context node in the source document
|
||||
* @param pos the context position
|
||||
* @param len the context size
|
||||
* @param nextSibling if non-null, add result nodes before this node
|
||||
*/
|
||||
void apply(Stylesheet stylesheet, QName mode,
|
||||
Node context, int pos, int len,
|
||||
Node parent, Node nextSibling)
|
||||
throws TransformerException
|
||||
{
|
||||
System.err.println("...applying " + toString() + " to " + context);
|
||||
if (node != null)
|
||||
{
|
||||
node.apply(stylesheet, mode,
|
||||
context, pos, len,
|
||||
parent, nextSibling);
|
||||
}
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
StringBuffer buf = new StringBuffer(getClass().getName());
|
||||
buf.append('[');
|
||||
if (name != null)
|
||||
{
|
||||
buf.append("name=");
|
||||
buf.append(name);
|
||||
}
|
||||
else if (match != null)
|
||||
{
|
||||
buf.append("match=");
|
||||
buf.append(match);
|
||||
}
|
||||
if (mode != null)
|
||||
{
|
||||
buf.append(",mode=");
|
||||
buf.append(mode);
|
||||
}
|
||||
buf.append(']');
|
||||
return buf.toString();
|
||||
|
||||
//return (name != null) ? name.toString() : match.toString();
|
||||
}
|
||||
|
||||
void list(PrintStream out)
|
||||
{
|
||||
out.println(toString());
|
||||
if (node != null)
|
||||
{
|
||||
node.list(1, out, true);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,124 @@
|
||||
/* TemplateNode.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.transform;
|
||||
|
||||
import java.io.PrintStream;
|
||||
import java.util.Comparator;
|
||||
import javax.xml.namespace.QName;
|
||||
import javax.xml.transform.TransformerException;
|
||||
import org.w3c.dom.Node;
|
||||
import gnu.xml.xpath.DocumentOrderComparator;
|
||||
|
||||
/**
|
||||
* Wrapper for a source node in a template.
|
||||
*
|
||||
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
|
||||
*/
|
||||
abstract class TemplateNode
|
||||
{
|
||||
|
||||
static final Comparator documentOrderComparator =
|
||||
new DocumentOrderComparator();
|
||||
|
||||
TemplateNode children;
|
||||
TemplateNode next;
|
||||
|
||||
final void apply(Stylesheet stylesheet, QName mode,
|
||||
Node context, int pos, int len,
|
||||
Node parent, Node nextSibling)
|
||||
throws TransformerException
|
||||
{
|
||||
if (stylesheet.terminated)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (Thread.currentThread().isInterrupted())
|
||||
{
|
||||
// Try to head off any infinite loops at the pass
|
||||
return;
|
||||
}
|
||||
if (stylesheet.debug)
|
||||
{
|
||||
System.err.println("Applying " + toString());
|
||||
System.err.println("\twith context=" + context + ", pos=" + pos +
|
||||
", len=" + len);
|
||||
}
|
||||
doApply(stylesheet, mode, context, pos, len, parent, nextSibling);
|
||||
}
|
||||
|
||||
abstract void doApply(Stylesheet stylesheet, QName mode,
|
||||
Node context, int pos, int len,
|
||||
Node parent, Node nextSibling)
|
||||
throws TransformerException;
|
||||
|
||||
abstract TemplateNode clone(Stylesheet stylesheet);
|
||||
|
||||
public boolean references(QName var)
|
||||
{
|
||||
if (children != null && children.references(var))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (next != null && next.references(var))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Debugging
|
||||
*/
|
||||
void list(int depth, PrintStream out, boolean listNext)
|
||||
{
|
||||
for (int i = 0; i < depth; i++)
|
||||
{
|
||||
out.print(" ");
|
||||
}
|
||||
out.println(toString());
|
||||
if (children != null)
|
||||
{
|
||||
children.list(depth + 1, out, true);
|
||||
}
|
||||
if (listNext && next != null)
|
||||
{
|
||||
next.list(depth, out, listNext);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
/* TemplatesImpl.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.transform;
|
||||
|
||||
import java.util.Properties;
|
||||
import javax.xml.transform.Templates;
|
||||
import javax.xml.transform.Transformer;
|
||||
import javax.xml.transform.TransformerConfigurationException;
|
||||
|
||||
/**
|
||||
* GNU precompiled stylesheet implementation.
|
||||
*
|
||||
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
|
||||
*/
|
||||
class TemplatesImpl
|
||||
implements Templates
|
||||
{
|
||||
|
||||
final TransformerFactoryImpl factory;
|
||||
final Stylesheet stylesheet;
|
||||
final Properties outputProperties;
|
||||
|
||||
TemplatesImpl(TransformerFactoryImpl factory, Stylesheet stylesheet)
|
||||
{
|
||||
this.factory = factory;
|
||||
this.stylesheet = stylesheet;
|
||||
outputProperties = new TransformerOutputProperties(stylesheet);
|
||||
}
|
||||
|
||||
public Transformer newTransformer()
|
||||
throws TransformerConfigurationException
|
||||
{
|
||||
Stylesheet stylesheet = (Stylesheet) this.stylesheet.clone();
|
||||
TransformerImpl transformer =
|
||||
new TransformerImpl(factory, stylesheet, outputProperties);
|
||||
stylesheet.transformer = transformer;
|
||||
return transformer;
|
||||
}
|
||||
|
||||
public Properties getOutputProperties()
|
||||
{
|
||||
return (Properties) outputProperties.clone();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,119 @@
|
||||
/* TextNode.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.transform;
|
||||
|
||||
import javax.xml.namespace.QName;
|
||||
import javax.xml.transform.TransformerException;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.DocumentFragment;
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.Text;
|
||||
import gnu.xml.xpath.Expr;
|
||||
|
||||
/**
|
||||
* A template node representing the XSL <code>text</code> instruction.
|
||||
*
|
||||
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
|
||||
*/
|
||||
final class TextNode
|
||||
extends TemplateNode
|
||||
{
|
||||
|
||||
final boolean disableOutputEscaping;
|
||||
|
||||
TextNode(boolean disableOutputEscaping)
|
||||
{
|
||||
this.disableOutputEscaping = disableOutputEscaping;
|
||||
}
|
||||
|
||||
TemplateNode clone(Stylesheet stylesheet)
|
||||
{
|
||||
TemplateNode ret = new TextNode(disableOutputEscaping);
|
||||
if (children != null)
|
||||
{
|
||||
ret.children = children.clone(stylesheet);
|
||||
}
|
||||
if (next != null)
|
||||
{
|
||||
ret.next = next.clone(stylesheet);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void doApply(Stylesheet stylesheet, QName mode,
|
||||
Node context, int pos, int len,
|
||||
Node parent, Node nextSibling)
|
||||
throws TransformerException
|
||||
{
|
||||
String value = "";
|
||||
Document doc = (parent instanceof Document) ? (Document) parent :
|
||||
parent.getOwnerDocument();
|
||||
if (children != null)
|
||||
{
|
||||
// Create a document fragment to hold the text
|
||||
DocumentFragment fragment = doc.createDocumentFragment();
|
||||
// Apply children to the fragment
|
||||
children.apply(stylesheet, mode,
|
||||
context, pos, len,
|
||||
fragment, null);
|
||||
// Use XPath string-value of fragment
|
||||
value = Expr.stringValue(fragment);
|
||||
}
|
||||
Text text = doc.createTextNode(value);
|
||||
if (disableOutputEscaping)
|
||||
{
|
||||
text.setUserData("disable-output-escaping", "yes", stylesheet);
|
||||
}
|
||||
// Insert into result tree
|
||||
if (nextSibling != null)
|
||||
{
|
||||
parent.insertBefore(text, nextSibling);
|
||||
}
|
||||
else
|
||||
{
|
||||
parent.appendChild(text);
|
||||
}
|
||||
if (next != null)
|
||||
{
|
||||
next.apply(stylesheet, mode,
|
||||
context, pos, len,
|
||||
parent, nextSibling);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,345 @@
|
||||
/* TransformerFactoryImpl.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.transform;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import javax.xml.transform.ErrorListener;
|
||||
import javax.xml.transform.Source;
|
||||
import javax.xml.transform.Templates;
|
||||
import javax.xml.transform.Transformer;
|
||||
import javax.xml.transform.TransformerConfigurationException;
|
||||
import javax.xml.transform.TransformerException;
|
||||
import javax.xml.transform.TransformerFactory;
|
||||
import javax.xml.transform.URIResolver;
|
||||
import javax.xml.transform.dom.DOMResult;
|
||||
import javax.xml.transform.dom.DOMSource;
|
||||
import javax.xml.transform.sax.SAXResult;
|
||||
import javax.xml.transform.sax.SAXSource;
|
||||
import javax.xml.transform.stream.StreamResult;
|
||||
import javax.xml.transform.stream.StreamSource;
|
||||
import javax.xml.xpath.XPathFactory;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Node;
|
||||
import gnu.xml.dom.DomDocument;
|
||||
|
||||
/**
|
||||
* GNU transformer factory implementation.
|
||||
*
|
||||
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
|
||||
*/
|
||||
public class TransformerFactoryImpl
|
||||
extends TransformerFactory
|
||||
{
|
||||
|
||||
final XPathFactory xpathFactory;
|
||||
final XSLURIResolver resolver;
|
||||
ErrorListener userListener;
|
||||
URIResolver userResolver;
|
||||
|
||||
public TransformerFactoryImpl()
|
||||
{
|
||||
xpathFactory = new gnu.xml.xpath.XPathFactoryImpl();
|
||||
resolver = new XSLURIResolver();
|
||||
}
|
||||
|
||||
public Transformer newTransformer(Source source)
|
||||
throws TransformerConfigurationException
|
||||
{
|
||||
Stylesheet stylesheet = newStylesheet(source, 0, null);
|
||||
Properties outputProperties =
|
||||
new TransformerOutputProperties(stylesheet);
|
||||
TransformerImpl transformer =
|
||||
new TransformerImpl(this, stylesheet, outputProperties);
|
||||
stylesheet.transformer = transformer;
|
||||
return transformer;
|
||||
}
|
||||
|
||||
public Transformer newTransformer()
|
||||
throws TransformerConfigurationException
|
||||
{
|
||||
return new TransformerImpl(this, null, new Properties());
|
||||
}
|
||||
|
||||
public Templates newTemplates(Source source)
|
||||
throws TransformerConfigurationException
|
||||
{
|
||||
Stylesheet stylesheet = newStylesheet(source, 0, null);
|
||||
return new TemplatesImpl(this, stylesheet);
|
||||
}
|
||||
|
||||
Stylesheet newStylesheet(Source source, int precedence, Stylesheet parent)
|
||||
throws TransformerConfigurationException
|
||||
{
|
||||
Document doc = null;
|
||||
String systemId = null;
|
||||
if (source != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
DOMSource ds;
|
||||
synchronized (resolver)
|
||||
{
|
||||
resolver.setUserResolver(userResolver);
|
||||
resolver.setUserListener(userListener);
|
||||
ds = resolver.resolveDOM(source, null, null);
|
||||
}
|
||||
Node node = ds.getNode();
|
||||
if (node == null)
|
||||
{
|
||||
throw new TransformerConfigurationException("no source document");
|
||||
}
|
||||
doc = (node instanceof Document) ? (Document) node :
|
||||
node.getOwnerDocument();
|
||||
systemId = ds.getSystemId();
|
||||
}
|
||||
catch (TransformerException e)
|
||||
{
|
||||
throw new TransformerConfigurationException(e);
|
||||
}
|
||||
}
|
||||
return new Stylesheet(this, parent, doc, systemId, precedence);
|
||||
}
|
||||
|
||||
public Source getAssociatedStylesheet(Source source,
|
||||
String media,
|
||||
String title,
|
||||
String charset)
|
||||
throws TransformerConfigurationException
|
||||
{
|
||||
try
|
||||
{
|
||||
DOMSource ds;
|
||||
synchronized (resolver)
|
||||
{
|
||||
resolver.setUserResolver(userResolver);
|
||||
resolver.setUserListener(userListener);
|
||||
ds = resolver.resolveDOM(source, null, null);
|
||||
}
|
||||
Node node = ds.getNode();
|
||||
if (node == null)
|
||||
{
|
||||
throw new TransformerConfigurationException("no source document");
|
||||
}
|
||||
Document doc = (node instanceof Document) ? (Document) node :
|
||||
node.getOwnerDocument();
|
||||
LinkedList matches = new LinkedList();
|
||||
for (node = doc.getFirstChild();
|
||||
node != null;
|
||||
node = node.getNextSibling())
|
||||
{
|
||||
if (node.getNodeType() == Node.PROCESSING_INSTRUCTION_NODE &&
|
||||
"xml-stylesheet".equals(node.getNodeName()))
|
||||
{
|
||||
Map params = parseParameters(node.getNodeValue());
|
||||
if (media != null && !media.equals(params.get("media")))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (title != null && !title.equals(params.get("title")))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (charset != null && !charset.equals(params.get("charset")))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
String href = (String) params.get("href");
|
||||
URL url = resolver.resolveURL(null, node.getBaseURI(), href);
|
||||
matches.add(url);
|
||||
}
|
||||
}
|
||||
switch (matches.size())
|
||||
{
|
||||
case 0:
|
||||
return null;
|
||||
case 1:
|
||||
return new StreamSource(((URL) matches.getFirst()).toString());
|
||||
default:
|
||||
// Create a source representing a stylesheet with a list of
|
||||
// imports
|
||||
DomDocument ssDoc = new DomDocument();
|
||||
ssDoc.setBuilding(true);
|
||||
// Create document element
|
||||
Node root =
|
||||
ssDoc.createElementNS(Stylesheet.XSL_NS, "stylesheet");
|
||||
Node version =
|
||||
ssDoc.createAttributeNS(null, "version");
|
||||
version.setNodeValue("1.0");
|
||||
root.getAttributes().setNamedItemNS(version);
|
||||
ssDoc.appendChild(root);
|
||||
// Create xsl:import for each URL
|
||||
for (Iterator i = matches.iterator(); i.hasNext(); )
|
||||
{
|
||||
URL url = (URL) i.next();
|
||||
Node imp =
|
||||
ssDoc.createElementNS(Stylesheet.XSL_NS, "import");
|
||||
Node href =
|
||||
ssDoc.createAttributeNS(null, "href");
|
||||
href.setNodeValue(url.toString());
|
||||
imp.getAttributes().setNamedItemNS(href);
|
||||
root.appendChild(imp);
|
||||
}
|
||||
ssDoc.setBuilding(false);
|
||||
return new DOMSource(ssDoc);
|
||||
}
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
throw new TransformerConfigurationException(e);
|
||||
}
|
||||
catch (TransformerException e)
|
||||
{
|
||||
throw new TransformerConfigurationException(e);
|
||||
}
|
||||
}
|
||||
|
||||
Map parseParameters(String data)
|
||||
{
|
||||
Map ret = new LinkedHashMap();
|
||||
int len = data.length();
|
||||
String key = null;
|
||||
int start = 0;
|
||||
char quoteChar = '\u0000';
|
||||
for (int i = 0; i < len; i++)
|
||||
{
|
||||
char c = data.charAt(i);
|
||||
if (quoteChar == '\u0000' && c == ' ')
|
||||
{
|
||||
if (key == null && start < i)
|
||||
{
|
||||
key = data.substring(start, i);
|
||||
}
|
||||
else
|
||||
{
|
||||
String val = unquote(data.substring(start, i).trim());
|
||||
ret.put(key, val);
|
||||
key = null;
|
||||
}
|
||||
start = i + 1;
|
||||
}
|
||||
else if (c == '"')
|
||||
{
|
||||
quoteChar = (quoteChar == c) ? '\u0000' : c;
|
||||
}
|
||||
else if (c == '\'')
|
||||
{
|
||||
quoteChar = (quoteChar == c) ? '\u0000' : c;
|
||||
}
|
||||
}
|
||||
if (start < len && key != null)
|
||||
{
|
||||
String val = unquote(data.substring(start, len).trim());
|
||||
ret.put(key, val);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
String unquote(String text)
|
||||
{
|
||||
int end = text.length() - 1;
|
||||
if (text.charAt(0) == '\'' && text.charAt(end) == '\'')
|
||||
{
|
||||
return text.substring(1, end);
|
||||
}
|
||||
if (text.charAt(0) == '"' && text.charAt(end) == '"')
|
||||
{
|
||||
return text.substring(1, end);
|
||||
}
|
||||
return text;
|
||||
}
|
||||
|
||||
public void setURIResolver(URIResolver resolver)
|
||||
{
|
||||
userResolver = resolver;
|
||||
}
|
||||
|
||||
public URIResolver getURIResolver()
|
||||
{
|
||||
return userResolver;
|
||||
}
|
||||
|
||||
public void setFeature(String name, boolean value)
|
||||
throws TransformerConfigurationException
|
||||
{
|
||||
throw new TransformerConfigurationException("not supported");
|
||||
}
|
||||
|
||||
public boolean getFeature(String name)
|
||||
{
|
||||
if (SAXSource.FEATURE.equals(name) ||
|
||||
SAXResult.FEATURE.equals(name) ||
|
||||
StreamSource.FEATURE.equals(name) ||
|
||||
StreamResult.FEATURE.equals(name) ||
|
||||
DOMSource.FEATURE.equals(name) ||
|
||||
DOMResult.FEATURE.equals(name))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void setAttribute(String name, Object value)
|
||||
throws IllegalArgumentException
|
||||
{
|
||||
throw new IllegalArgumentException("not supported");
|
||||
}
|
||||
|
||||
public Object getAttribute(String name)
|
||||
throws IllegalArgumentException
|
||||
{
|
||||
throw new IllegalArgumentException("not supported");
|
||||
}
|
||||
|
||||
public void setErrorListener(ErrorListener listener)
|
||||
throws IllegalArgumentException
|
||||
{
|
||||
userListener = listener;
|
||||
}
|
||||
|
||||
public ErrorListener getErrorListener()
|
||||
{
|
||||
return userListener;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,769 @@
|
||||
/* TransformerImpl.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.transform;
|
||||
|
||||
import java.io.BufferedOutputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.io.Writer;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.UnknownServiceException;
|
||||
import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
import java.util.StringTokenizer;
|
||||
import javax.xml.namespace.QName;
|
||||
import javax.xml.transform.ErrorListener;
|
||||
import javax.xml.transform.OutputKeys;
|
||||
import javax.xml.transform.Result;
|
||||
import javax.xml.transform.Source;
|
||||
import javax.xml.transform.Transformer;
|
||||
import javax.xml.transform.TransformerConfigurationException;
|
||||
import javax.xml.transform.TransformerException;
|
||||
import javax.xml.transform.URIResolver;
|
||||
import javax.xml.transform.dom.DOMSource;
|
||||
import javax.xml.transform.dom.DOMResult;
|
||||
import javax.xml.transform.sax.SAXResult;
|
||||
import javax.xml.transform.stream.StreamResult;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.DocumentType;
|
||||
import org.w3c.dom.DOMImplementation;
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.Text;
|
||||
import org.xml.sax.ContentHandler;
|
||||
import org.xml.sax.SAXException;
|
||||
import org.xml.sax.ext.LexicalHandler;
|
||||
import gnu.xml.dom.DomDoctype;
|
||||
import gnu.xml.dom.DomDocument;
|
||||
import gnu.xml.dom.ls.WriterOutputStream;
|
||||
|
||||
/**
|
||||
* The transformation process for a given stylesheet.
|
||||
*
|
||||
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
|
||||
*/
|
||||
class TransformerImpl
|
||||
extends Transformer
|
||||
{
|
||||
|
||||
final TransformerFactoryImpl factory;
|
||||
final Stylesheet stylesheet;
|
||||
URIResolver uriResolver;
|
||||
ErrorListener errorListener;
|
||||
Properties outputProperties;
|
||||
|
||||
TransformerImpl(TransformerFactoryImpl factory,
|
||||
Stylesheet stylesheet,
|
||||
Properties outputProperties)
|
||||
throws TransformerConfigurationException
|
||||
{
|
||||
this.factory = factory;
|
||||
uriResolver = factory.userResolver;
|
||||
errorListener = factory.userListener;
|
||||
this.stylesheet = stylesheet;
|
||||
this.outputProperties = outputProperties;
|
||||
if (stylesheet != null)
|
||||
{
|
||||
// Set up parameter context for this transformer
|
||||
stylesheet.bindings.push(Bindings.PARAM);
|
||||
}
|
||||
}
|
||||
|
||||
public void transform(Source xmlSource, Result outputTarget)
|
||||
throws TransformerException
|
||||
{
|
||||
// Get the source tree
|
||||
DOMSource source;
|
||||
synchronized (factory.resolver)
|
||||
{
|
||||
factory.resolver.setUserResolver(uriResolver);
|
||||
factory.resolver.setUserListener(errorListener);
|
||||
source = factory.resolver.resolveDOM(xmlSource, null, null);
|
||||
}
|
||||
Node context = source.getNode();
|
||||
Document doc = (context instanceof Document) ? (Document) context :
|
||||
context.getOwnerDocument();
|
||||
if (doc instanceof DomDocument)
|
||||
{
|
||||
// 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;
|
||||
if (outputTarget instanceof DOMResult)
|
||||
{
|
||||
DOMResult dr = (DOMResult) outputTarget;
|
||||
parent = dr.getNode();
|
||||
nextSibling = dr.getNextSibling();
|
||||
|
||||
Document rdoc = (parent instanceof Document) ? (Document) parent :
|
||||
parent.getOwnerDocument();
|
||||
if (rdoc instanceof DomDocument)
|
||||
{
|
||||
// Suppress mutation events and allow multiple root elements
|
||||
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;
|
||||
// Transformation
|
||||
if (stylesheet != null)
|
||||
{
|
||||
if (parent == null)
|
||||
{
|
||||
// Create a new document to hold the result
|
||||
DomDocument resultDoc = new DomDocument();
|
||||
resultDoc.setBuilding(true);
|
||||
resultDoc.setCheckWellformedness(false);
|
||||
parent = resultDoc;
|
||||
created = true;
|
||||
}
|
||||
// Make a copy of the source node, and strip it
|
||||
context = context.cloneNode(true);
|
||||
strip(context);
|
||||
// XSLT transformation
|
||||
try
|
||||
{
|
||||
// Set output properties in the underlying stylesheet
|
||||
((TransformerOutputProperties) outputProperties).apply();
|
||||
stylesheet.initTopLevelVariables(context);
|
||||
TemplateNode t = stylesheet.getTemplate(null, context, false);
|
||||
if (t != null)
|
||||
{
|
||||
stylesheet.current = context;
|
||||
t.apply(stylesheet, null, context, 1, 1, parent, nextSibling);
|
||||
}
|
||||
}
|
||||
catch (TransformerException e)
|
||||
{
|
||||
// Done transforming, reset document
|
||||
if (doc instanceof DomDocument)
|
||||
{
|
||||
((DomDocument) doc).setBuilding(false);
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Identity transform
|
||||
Node clone = context.cloneNode(true);
|
||||
if (context.getNodeType() != Node.DOCUMENT_NODE)
|
||||
{
|
||||
Document resultDoc;
|
||||
if (parent == null)
|
||||
{
|
||||
// Create a new document to hold the result
|
||||
DomDocument rd = new DomDocument();
|
||||
rd.setBuilding(true);
|
||||
rd.setCheckWellformedness(false);
|
||||
parent = resultDoc = rd;
|
||||
created = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
resultDoc = (parent instanceof Document) ?
|
||||
(Document) parent :
|
||||
parent.getOwnerDocument();
|
||||
}
|
||||
Document sourceDoc = context.getOwnerDocument();
|
||||
if (sourceDoc != resultDoc)
|
||||
{
|
||||
clone = resultDoc.adoptNode(clone);
|
||||
}
|
||||
if (nextSibling != null)
|
||||
{
|
||||
parent.insertBefore(clone, nextSibling);
|
||||
}
|
||||
else
|
||||
{
|
||||
parent.appendChild(clone);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Cannot append document to another tree
|
||||
parent = clone;
|
||||
created = true;
|
||||
}
|
||||
}
|
||||
String method = outputProperties.getProperty(OutputKeys.METHOD);
|
||||
int outputMethod = "html".equals(method) ? Stylesheet.OUTPUT_HTML :
|
||||
"text".equals(method) ? Stylesheet.OUTPUT_TEXT :
|
||||
Stylesheet.OUTPUT_XML;
|
||||
String encoding = outputProperties.getProperty(OutputKeys.ENCODING);
|
||||
String publicId = outputProperties.getProperty(OutputKeys.DOCTYPE_PUBLIC);
|
||||
String systemId = outputProperties.getProperty(OutputKeys.DOCTYPE_SYSTEM);
|
||||
String version = outputProperties.getProperty(OutputKeys.VERSION);
|
||||
boolean omitXmlDeclaration =
|
||||
"yes".equals(outputProperties.getProperty(OutputKeys.OMIT_XML_DECLARATION));
|
||||
boolean standalone =
|
||||
"yes".equals(outputProperties.getProperty(OutputKeys.STANDALONE));
|
||||
String mediaType = outputProperties.getProperty(OutputKeys.MEDIA_TYPE);
|
||||
String cdataSectionElements =
|
||||
outputProperties.getProperty(OutputKeys.CDATA_SECTION_ELEMENTS);
|
||||
boolean indent =
|
||||
"yes".equals(outputProperties.getProperty(OutputKeys.INDENT));
|
||||
if (created)
|
||||
{
|
||||
// Discover document element
|
||||
DomDocument resultDoc = (DomDocument) parent;
|
||||
Node root = resultDoc.getDocumentElement();
|
||||
// Add doctype if specified
|
||||
if ((publicId != null || systemId != null) &&
|
||||
root != null)
|
||||
{
|
||||
// We must know the name of the root element to
|
||||
// create the document type
|
||||
resultDoc.appendChild(new DomDoctype(resultDoc,
|
||||
root.getNodeName(),
|
||||
publicId,
|
||||
systemId));
|
||||
}
|
||||
resultDoc.setBuilding(false);
|
||||
resultDoc.setCheckWellformedness(true);
|
||||
}
|
||||
else if (publicId != null || systemId != null)
|
||||
{
|
||||
switch (parent.getNodeType())
|
||||
{
|
||||
case Node.DOCUMENT_NODE:
|
||||
case Node.DOCUMENT_FRAGMENT_NODE:
|
||||
Document resultDoc = (parent instanceof Document) ?
|
||||
(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())
|
||||
{
|
||||
}
|
||||
if (ctx != null)
|
||||
{
|
||||
parent.insertBefore(doctype, ctx);
|
||||
}
|
||||
else
|
||||
{
|
||||
parent.appendChild(doctype);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (version != null)
|
||||
{
|
||||
parent.setUserData("version", version, stylesheet);
|
||||
}
|
||||
if (omitXmlDeclaration)
|
||||
{
|
||||
parent.setUserData("omit-xml-declaration", "yes", stylesheet);
|
||||
}
|
||||
if (standalone)
|
||||
{
|
||||
parent.setUserData("standalone", "yes", stylesheet);
|
||||
}
|
||||
if (mediaType != null)
|
||||
{
|
||||
parent.setUserData("media-type", mediaType, stylesheet);
|
||||
}
|
||||
if (cdataSectionElements != null)
|
||||
{
|
||||
List list = new LinkedList();
|
||||
StringTokenizer st = new StringTokenizer(cdataSectionElements);
|
||||
while (st.hasMoreTokens())
|
||||
{
|
||||
String name = st.nextToken();
|
||||
String localName = name;
|
||||
String uri = null;
|
||||
String prefix = null;
|
||||
int ci = name.indexOf(':');
|
||||
if (ci != -1)
|
||||
{
|
||||
// Use namespaces defined on xsl:output node to resolve
|
||||
// namespaces for QName
|
||||
prefix = name.substring(0, ci);
|
||||
localName = name.substring(ci + 1);
|
||||
uri = stylesheet.output.lookupNamespaceURI(prefix);
|
||||
}
|
||||
list.add(new QName(uri, localName, prefix));
|
||||
}
|
||||
if (!list.isEmpty())
|
||||
{
|
||||
Document resultDoc = (parent instanceof Document) ?
|
||||
(Document) parent :
|
||||
parent.getOwnerDocument();
|
||||
convertCdataSectionElements(resultDoc, parent, list);
|
||||
}
|
||||
}
|
||||
if (indent)
|
||||
{
|
||||
parent.normalize();
|
||||
strip(parent);
|
||||
Document resultDoc = (parent instanceof Document) ?
|
||||
(Document) parent :
|
||||
parent.getOwnerDocument();
|
||||
reindent(resultDoc, parent, 0);
|
||||
}
|
||||
// Render result to the target device
|
||||
if (outputTarget instanceof DOMResult)
|
||||
{
|
||||
if (created)
|
||||
{
|
||||
DOMResult dr = (DOMResult) outputTarget;
|
||||
dr.setNode(parent);
|
||||
dr.setNextSibling(null);
|
||||
}
|
||||
}
|
||||
else if (outputTarget instanceof StreamResult)
|
||||
{
|
||||
StreamResult sr = (StreamResult) outputTarget;
|
||||
IOException ex = null;
|
||||
try
|
||||
{
|
||||
writeStreamResult(parent, sr, outputMethod, encoding);
|
||||
}
|
||||
catch (UnsupportedEncodingException e)
|
||||
{
|
||||
try
|
||||
{
|
||||
writeStreamResult(parent, sr, outputMethod, "UTF-8");
|
||||
}
|
||||
catch (IOException e2)
|
||||
{
|
||||
ex = e2;
|
||||
}
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
ex = e;
|
||||
}
|
||||
if (ex != null)
|
||||
{
|
||||
if (errorListener != null)
|
||||
{
|
||||
errorListener.error(new TransformerException(ex));
|
||||
}
|
||||
else
|
||||
{
|
||||
ex.printStackTrace(System.err);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (outputTarget instanceof SAXResult)
|
||||
{
|
||||
SAXResult sr = (SAXResult) outputTarget;
|
||||
try
|
||||
{
|
||||
ContentHandler ch = sr.getHandler();
|
||||
LexicalHandler lh = sr.getLexicalHandler();
|
||||
if (lh == null && ch instanceof LexicalHandler)
|
||||
{
|
||||
lh = (LexicalHandler) ch;
|
||||
}
|
||||
SAXSerializer serializer = new SAXSerializer();
|
||||
serializer.serialize(parent, ch, lh);
|
||||
}
|
||||
catch (SAXException e)
|
||||
{
|
||||
if (errorListener != null)
|
||||
{
|
||||
errorListener.error(new TransformerException(e));
|
||||
}
|
||||
else
|
||||
{
|
||||
e.printStackTrace(System.err);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Strip whitespace from the source tree.
|
||||
*/
|
||||
void strip(Node node)
|
||||
throws TransformerConfigurationException
|
||||
{
|
||||
short nt = node.getNodeType();
|
||||
if (nt == Node.ENTITY_REFERENCE_NODE)
|
||||
{
|
||||
// Replace entity reference with its content
|
||||
Node parent = node.getParentNode();
|
||||
Node child = node.getFirstChild();
|
||||
if (child != null)
|
||||
{
|
||||
strip(child);
|
||||
}
|
||||
while (child != null)
|
||||
{
|
||||
Node next = child.getNextSibling();
|
||||
node.removeChild(child);
|
||||
parent.insertBefore(child, node);
|
||||
child = next;
|
||||
}
|
||||
parent.removeChild(node);
|
||||
}
|
||||
if (nt == Node.TEXT_NODE || nt == Node.CDATA_SECTION_NODE)
|
||||
{
|
||||
if (!stylesheet.isPreserved((Text) node))
|
||||
{
|
||||
node.getParentNode().removeChild(node);
|
||||
}
|
||||
else
|
||||
{
|
||||
String text = node.getNodeValue();
|
||||
String stripped = text.trim();
|
||||
if (!text.equals(stripped))
|
||||
{
|
||||
node.setNodeValue(stripped);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (Node child = node.getFirstChild(); child != null;
|
||||
child = child.getNextSibling())
|
||||
{
|
||||
strip(child);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtain a suitable output stream for writing the result to,
|
||||
* and use the StreamSerializer to write the result tree to the stream.
|
||||
*/
|
||||
void writeStreamResult(Node node, StreamResult sr, int outputMethod,
|
||||
String encoding)
|
||||
throws IOException
|
||||
{
|
||||
OutputStream out = null;
|
||||
try
|
||||
{
|
||||
out = sr.getOutputStream();
|
||||
if (out == null)
|
||||
{
|
||||
Writer writer = sr.getWriter();
|
||||
if (writer != null)
|
||||
{
|
||||
out = new WriterOutputStream(writer);
|
||||
}
|
||||
}
|
||||
if (out == null)
|
||||
{
|
||||
String systemId = sr.getSystemId();
|
||||
try
|
||||
{
|
||||
URL url = new URL(systemId);
|
||||
URLConnection connection = url.openConnection();
|
||||
connection.setDoOutput(true);
|
||||
out = connection.getOutputStream();
|
||||
}
|
||||
catch (MalformedURLException e)
|
||||
{
|
||||
out = new FileOutputStream(systemId);
|
||||
}
|
||||
catch (UnknownServiceException e)
|
||||
{
|
||||
URL url = new URL(systemId);
|
||||
out = new FileOutputStream(url.getPath());
|
||||
}
|
||||
}
|
||||
out = new BufferedOutputStream(out);
|
||||
StreamSerializer serializer =
|
||||
new StreamSerializer(outputMethod, encoding, null);
|
||||
if (stylesheet != null)
|
||||
{
|
||||
Collection celem = stylesheet.outputCdataSectionElements;
|
||||
serializer.setCdataSectionElements(celem);
|
||||
}
|
||||
serializer.serialize(node, out);
|
||||
out.flush();
|
||||
}
|
||||
finally
|
||||
{
|
||||
try
|
||||
{
|
||||
if (out != null)
|
||||
{
|
||||
out.close();
|
||||
}
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void copyChildren(Document dstDoc, Node src, Node dst)
|
||||
{
|
||||
Node srcChild = src.getFirstChild();
|
||||
while (srcChild != null)
|
||||
{
|
||||
Node dstChild = dstDoc.adoptNode(srcChild);
|
||||
dst.appendChild(dstChild);
|
||||
srcChild = srcChild.getNextSibling();
|
||||
}
|
||||
}
|
||||
|
||||
public void setParameter(String name, Object value)
|
||||
{
|
||||
if (stylesheet != null)
|
||||
{
|
||||
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 null;
|
||||
}
|
||||
|
||||
public void clearParameters()
|
||||
{
|
||||
if (stylesheet != null)
|
||||
{
|
||||
stylesheet.bindings.pop(Bindings.PARAM);
|
||||
stylesheet.bindings.push(Bindings.PARAM);
|
||||
}
|
||||
}
|
||||
|
||||
public void setURIResolver(URIResolver resolver)
|
||||
{
|
||||
uriResolver = resolver;
|
||||
}
|
||||
|
||||
public URIResolver getURIResolver()
|
||||
{
|
||||
return uriResolver;
|
||||
}
|
||||
|
||||
public void setOutputProperties(Properties oformat)
|
||||
throws IllegalArgumentException
|
||||
{
|
||||
if (oformat == null)
|
||||
{
|
||||
outputProperties.clear();
|
||||
}
|
||||
else
|
||||
{
|
||||
outputProperties.putAll(oformat);
|
||||
}
|
||||
}
|
||||
|
||||
public Properties getOutputProperties()
|
||||
{
|
||||
return (Properties) outputProperties.clone();
|
||||
}
|
||||
|
||||
public void setOutputProperty(String name, String value)
|
||||
throws IllegalArgumentException
|
||||
{
|
||||
outputProperties.put(name, value);
|
||||
}
|
||||
|
||||
public String getOutputProperty(String name)
|
||||
throws IllegalArgumentException
|
||||
{
|
||||
return outputProperties.getProperty(name);
|
||||
}
|
||||
|
||||
public void setErrorListener(ErrorListener listener)
|
||||
{
|
||||
errorListener = listener;
|
||||
}
|
||||
|
||||
public ErrorListener getErrorListener()
|
||||
{
|
||||
return errorListener;
|
||||
}
|
||||
|
||||
static final String INDENT_WHITESPACE = " ";
|
||||
|
||||
/*
|
||||
* Apply indent formatting to the given tree.
|
||||
*/
|
||||
void reindent(Document doc, Node node, int offset)
|
||||
{
|
||||
if (node.hasChildNodes())
|
||||
{
|
||||
boolean markupContent = false;
|
||||
boolean textContent = false;
|
||||
List children = new LinkedList();
|
||||
Node ctx = node.getFirstChild();
|
||||
while (ctx != null)
|
||||
{
|
||||
switch (ctx.getNodeType())
|
||||
{
|
||||
case Node.ELEMENT_NODE:
|
||||
case Node.PROCESSING_INSTRUCTION_NODE:
|
||||
case Node.DOCUMENT_TYPE_NODE:
|
||||
markupContent = true;
|
||||
break;
|
||||
case Node.TEXT_NODE:
|
||||
case Node.CDATA_SECTION_NODE:
|
||||
case Node.ENTITY_REFERENCE_NODE:
|
||||
case Node.COMMENT_NODE:
|
||||
textContent = true;
|
||||
break;
|
||||
}
|
||||
children.add(ctx);
|
||||
ctx = ctx.getNextSibling();
|
||||
}
|
||||
if (markupContent)
|
||||
{
|
||||
if (textContent)
|
||||
{
|
||||
// XXX handle mixed content differently?
|
||||
}
|
||||
int nodeType = node.getNodeType();
|
||||
if (nodeType == Node.DOCUMENT_NODE)
|
||||
{
|
||||
for (Iterator i = children.iterator(); i.hasNext(); )
|
||||
{
|
||||
ctx = (Node) i.next();
|
||||
reindent(doc, ctx, offset + 1);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
StringBuffer buf = new StringBuffer();
|
||||
buf.append('\n');
|
||||
for (int i = 0; i < offset + 1; i++)
|
||||
{
|
||||
buf.append(INDENT_WHITESPACE);
|
||||
}
|
||||
String ws = buf.toString();
|
||||
for (Iterator i = children.iterator(); i.hasNext(); )
|
||||
{
|
||||
ctx = (Node) i.next();
|
||||
node.insertBefore(doc.createTextNode(ws), ctx);
|
||||
reindent(doc, ctx, offset + 1);
|
||||
}
|
||||
buf = new StringBuffer();
|
||||
buf.append('\n');
|
||||
ws = buf.toString();
|
||||
for (int i = 0; i < offset; i++)
|
||||
{
|
||||
buf.append(INDENT_WHITESPACE);
|
||||
}
|
||||
node.appendChild(doc.createTextNode(ws));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the text node children of any cdata-section-elements in the
|
||||
* tree to CDATA section nodes.
|
||||
*/
|
||||
void convertCdataSectionElements(Document doc, Node node, List list)
|
||||
{
|
||||
if (node.getNodeType() == Node.ELEMENT_NODE)
|
||||
{
|
||||
boolean match = false;
|
||||
for (Iterator i = list.iterator(); i.hasNext(); )
|
||||
{
|
||||
QName qname = (QName) i.next();
|
||||
if (match(qname, node))
|
||||
{
|
||||
match = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (match)
|
||||
{
|
||||
Node ctx = node.getFirstChild();
|
||||
while (ctx != null)
|
||||
{
|
||||
if (ctx.getNodeType() == Node.TEXT_NODE)
|
||||
{
|
||||
Node cdata = doc.createCDATASection(ctx.getNodeValue());
|
||||
node.replaceChild(cdata, ctx);
|
||||
ctx = cdata;
|
||||
}
|
||||
ctx = ctx.getNextSibling();
|
||||
}
|
||||
}
|
||||
}
|
||||
Node ctx = node.getFirstChild();
|
||||
while (ctx != null)
|
||||
{
|
||||
if (ctx.hasChildNodes())
|
||||
{
|
||||
convertCdataSectionElements(doc, ctx, list);
|
||||
}
|
||||
ctx = ctx.getNextSibling();
|
||||
}
|
||||
}
|
||||
|
||||
boolean match(QName qname, Node node)
|
||||
{
|
||||
String ln1 = qname.getLocalPart();
|
||||
String ln2 = node.getLocalName();
|
||||
if (ln2 == null)
|
||||
{
|
||||
return ln1.equals(node.getNodeName());
|
||||
}
|
||||
else
|
||||
{
|
||||
String uri1 = qname.getNamespaceURI();
|
||||
String uri2 = node.getNamespaceURI();
|
||||
return (uri1.equals(uri2) && ln1.equals(ln2));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,185 @@
|
||||
/* TransformerOutputProperties.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.transform;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Properties;
|
||||
import java.util.StringTokenizer;
|
||||
import javax.xml.transform.OutputKeys;
|
||||
|
||||
/**
|
||||
* Helper class to manage JAXP user setting of output properties.
|
||||
*
|
||||
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
|
||||
*/
|
||||
class TransformerOutputProperties
|
||||
extends Properties
|
||||
{
|
||||
|
||||
final Properties defaultProperties;
|
||||
final Stylesheet stylesheet;
|
||||
boolean dirty;
|
||||
|
||||
TransformerOutputProperties(Stylesheet stylesheet)
|
||||
{
|
||||
this.stylesheet = stylesheet;
|
||||
defaultProperties = new Properties();
|
||||
switch (stylesheet.outputMethod)
|
||||
{
|
||||
case Stylesheet.OUTPUT_XML:
|
||||
defaultProperties.put(OutputKeys.METHOD, "xml");
|
||||
break;
|
||||
case Stylesheet.OUTPUT_HTML:
|
||||
defaultProperties.put(OutputKeys.METHOD, "html");
|
||||
break;
|
||||
case Stylesheet.OUTPUT_TEXT:
|
||||
defaultProperties.put(OutputKeys.METHOD, "text");
|
||||
break;
|
||||
}
|
||||
if (stylesheet.outputVersion != null)
|
||||
{
|
||||
defaultProperties.put(OutputKeys.VERSION, stylesheet.outputVersion);
|
||||
}
|
||||
if (stylesheet.outputEncoding != null)
|
||||
{
|
||||
defaultProperties.put(OutputKeys.ENCODING, stylesheet.outputEncoding);
|
||||
}
|
||||
defaultProperties.put(OutputKeys.OMIT_XML_DECLARATION,
|
||||
stylesheet.outputOmitXmlDeclaration ? "yes" : "no");
|
||||
defaultProperties.put(OutputKeys.STANDALONE,
|
||||
stylesheet.outputStandalone ? "yes" : "no");
|
||||
if (stylesheet.outputPublicId != null)
|
||||
{
|
||||
defaultProperties.put(OutputKeys.DOCTYPE_PUBLIC,
|
||||
stylesheet.outputPublicId);
|
||||
}
|
||||
if (stylesheet.outputSystemId != null)
|
||||
{
|
||||
defaultProperties.put(OutputKeys.DOCTYPE_SYSTEM,
|
||||
stylesheet.outputSystemId);
|
||||
}
|
||||
StringBuffer buf = new StringBuffer();
|
||||
for (Iterator i = stylesheet.outputCdataSectionElements.iterator();
|
||||
i.hasNext(); )
|
||||
{
|
||||
if (buf.length() > 0)
|
||||
{
|
||||
buf.append(' ');
|
||||
}
|
||||
buf.append((String) i.next());
|
||||
}
|
||||
defaultProperties.put(OutputKeys.CDATA_SECTION_ELEMENTS, buf.toString());
|
||||
defaultProperties.put(OutputKeys.INDENT,
|
||||
stylesheet.outputIndent ? "yes" : "no");
|
||||
if (stylesheet.outputMediaType != null)
|
||||
{
|
||||
defaultProperties.put(OutputKeys.MEDIA_TYPE,
|
||||
stylesheet.outputMediaType);
|
||||
}
|
||||
}
|
||||
|
||||
public String getProperty(String key)
|
||||
{
|
||||
String val = super.getProperty(key);
|
||||
if (val == null)
|
||||
{
|
||||
val = defaultProperties.getProperty(key);
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
public Object put(Object key, Object value)
|
||||
{
|
||||
Object ret = super.put(key, value);
|
||||
dirty = true;
|
||||
return ret;
|
||||
}
|
||||
|
||||
public void clear()
|
||||
{
|
||||
super.clear();
|
||||
dirty = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies the current set of properties to the underlying stylesheet.
|
||||
*/
|
||||
void apply()
|
||||
{
|
||||
if (!dirty)
|
||||
{
|
||||
return;
|
||||
}
|
||||
String method = getProperty(OutputKeys.METHOD);
|
||||
if ("xml".equals(method))
|
||||
{
|
||||
stylesheet.outputMethod = Stylesheet.OUTPUT_XML;
|
||||
}
|
||||
else if ("html".equals(method))
|
||||
{
|
||||
stylesheet.outputMethod = Stylesheet.OUTPUT_HTML;
|
||||
}
|
||||
else if ("text".equals(method))
|
||||
{
|
||||
stylesheet.outputMethod = Stylesheet.OUTPUT_TEXT;
|
||||
}
|
||||
stylesheet.outputVersion = getProperty(OutputKeys.VERSION);
|
||||
stylesheet.outputEncoding = getProperty(OutputKeys.ENCODING);
|
||||
stylesheet.outputOmitXmlDeclaration =
|
||||
"yes".equals(getProperty(OutputKeys.OMIT_XML_DECLARATION));
|
||||
stylesheet.outputStandalone =
|
||||
"yes".equals(getProperty(OutputKeys.STANDALONE));
|
||||
stylesheet.outputPublicId = getProperty(OutputKeys.DOCTYPE_PUBLIC);
|
||||
stylesheet.outputSystemId = getProperty(OutputKeys.DOCTYPE_SYSTEM);
|
||||
StringTokenizer st =
|
||||
new StringTokenizer(getProperty(OutputKeys.CDATA_SECTION_ELEMENTS));
|
||||
Collection acc = new LinkedHashSet();
|
||||
while (st.hasMoreTokens())
|
||||
{
|
||||
acc.add(st.nextToken());
|
||||
}
|
||||
stylesheet.outputCdataSectionElements = acc;
|
||||
stylesheet.outputIndent = "yes".equals(getProperty(OutputKeys.INDENT));
|
||||
stylesheet.outputMediaType = getProperty(OutputKeys.MEDIA_TYPE);
|
||||
dirty = false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
/* URIResolverEntityResolver.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.transform;
|
||||
|
||||
import java.io.IOException;
|
||||
import javax.xml.transform.Source;
|
||||
import javax.xml.transform.TransformerException;
|
||||
import javax.xml.transform.URIResolver;
|
||||
import javax.xml.transform.sax.SAXSource;
|
||||
import org.xml.sax.EntityResolver;
|
||||
import org.xml.sax.InputSource;
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
/**
|
||||
* EntityResolver that wraps a URIResolver.
|
||||
*
|
||||
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
|
||||
*/
|
||||
class URIResolverEntityResolver
|
||||
implements EntityResolver
|
||||
{
|
||||
|
||||
final URIResolver resolver;
|
||||
|
||||
URIResolverEntityResolver(URIResolver resolver)
|
||||
{
|
||||
this.resolver = resolver;
|
||||
}
|
||||
|
||||
public InputSource resolveEntity(String publicId, String systemId)
|
||||
throws SAXException, IOException
|
||||
{
|
||||
try
|
||||
{
|
||||
Source source = resolver.resolve(null, systemId);
|
||||
if (source == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return SAXSource.sourceToInputSource(source);
|
||||
}
|
||||
catch (TransformerException e)
|
||||
{
|
||||
throw new SAXException(e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,132 @@
|
||||
/* UnparsedEntityUriFunction.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.transform;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import javax.xml.namespace.QName;
|
||||
import javax.xml.xpath.XPathFunction;
|
||||
import javax.xml.xpath.XPathFunctionException;
|
||||
import org.w3c.dom.DocumentType;
|
||||
import org.w3c.dom.NamedNodeMap;
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.Notation;
|
||||
import gnu.xml.xpath.Expr;
|
||||
import gnu.xml.xpath.Function;
|
||||
|
||||
/**
|
||||
* The XSLT <code>unparsed-entity-uri()</code>function.
|
||||
*
|
||||
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
|
||||
*/
|
||||
final class UnparsedEntityUriFunction
|
||||
extends Expr
|
||||
implements XPathFunction, Function
|
||||
{
|
||||
|
||||
List args;
|
||||
|
||||
public Object evaluate(List args)
|
||||
throws XPathFunctionException
|
||||
{
|
||||
// Useless...
|
||||
return Collections.EMPTY_SET;
|
||||
}
|
||||
|
||||
public void setArguments(List args)
|
||||
{
|
||||
this.args = args;
|
||||
}
|
||||
|
||||
public Object evaluate(Node context, int pos, int len)
|
||||
{
|
||||
int arity = args.size();
|
||||
List values = new ArrayList(arity);
|
||||
for (int i = 0; i < arity; i++)
|
||||
{
|
||||
Expr arg = (Expr) args.get(i);
|
||||
values.add(arg.evaluate(context, pos, len));
|
||||
}
|
||||
String name = _string(context, values.get(0));
|
||||
DocumentType doctype = context.getOwnerDocument().getDoctype();
|
||||
if (doctype != null)
|
||||
{
|
||||
NamedNodeMap notations = doctype.getNotations();
|
||||
Notation notation = (Notation) notations.getNamedItem(name);
|
||||
if (notation != null)
|
||||
{
|
||||
String systemId = notation.getSystemId();
|
||||
// XXX absolutize?
|
||||
if (systemId != null)
|
||||
{
|
||||
return systemId;
|
||||
}
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
public Expr clone(Object context)
|
||||
{
|
||||
UnparsedEntityUriFunction f = new UnparsedEntityUriFunction();
|
||||
int len = args.size();
|
||||
List args2 = new ArrayList(len);
|
||||
for (int i = 0; i < len; i++)
|
||||
{
|
||||
args2.add(((Expr) args.get(i)).clone(context));
|
||||
}
|
||||
f.setArguments(args2);
|
||||
return f;
|
||||
}
|
||||
|
||||
public boolean references(QName var)
|
||||
{
|
||||
for (Iterator i = args.iterator(); i.hasNext(); )
|
||||
{
|
||||
if (((Expr) i.next()).references(var))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,161 @@
|
||||
/* ValueOfNode.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.transform;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import javax.xml.namespace.QName;
|
||||
import javax.xml.transform.TransformerException;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.Text;
|
||||
import gnu.xml.xpath.Expr;
|
||||
|
||||
/**
|
||||
* A template node representing an XSLT <code>value-of</code> instruction.
|
||||
*
|
||||
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
|
||||
*/
|
||||
final class ValueOfNode
|
||||
extends TemplateNode
|
||||
{
|
||||
|
||||
final Expr select;
|
||||
final boolean disableOutputEscaping;
|
||||
|
||||
ValueOfNode(Expr select, boolean disableOutputEscaping)
|
||||
{
|
||||
this.select = select;
|
||||
this.disableOutputEscaping = disableOutputEscaping;
|
||||
}
|
||||
|
||||
TemplateNode clone(Stylesheet stylesheet)
|
||||
{
|
||||
TemplateNode ret = new ValueOfNode(select.clone(stylesheet),
|
||||
disableOutputEscaping);
|
||||
if (children != null)
|
||||
{
|
||||
ret.children = children.clone(stylesheet);
|
||||
}
|
||||
if (next != null)
|
||||
{
|
||||
ret.next = next.clone(stylesheet);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void doApply(Stylesheet stylesheet, QName mode,
|
||||
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)
|
||||
{
|
||||
StringBuffer buf = new StringBuffer();
|
||||
for (Iterator i = ((Collection) ret).iterator(); i.hasNext(); )
|
||||
{
|
||||
Node node = (Node) i.next();
|
||||
buf.append(Expr.stringValue(node));
|
||||
}
|
||||
value = buf.toString();
|
||||
}
|
||||
else
|
||||
{
|
||||
value = Expr._string(context, ret);
|
||||
}
|
||||
if (stylesheet.debug)
|
||||
{
|
||||
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);
|
||||
}
|
||||
if (nextSibling != null)
|
||||
{
|
||||
parent.insertBefore(textNode, nextSibling);
|
||||
}
|
||||
else
|
||||
{
|
||||
parent.appendChild(textNode);
|
||||
}
|
||||
}
|
||||
// value-of doesn't process children
|
||||
if (next != null)
|
||||
{
|
||||
next.apply(stylesheet, mode,
|
||||
context, pos, len,
|
||||
parent, nextSibling);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean references(QName var)
|
||||
{
|
||||
if (select != null && select.references(var))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return super.references(var);
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
StringBuffer buf = new StringBuffer(getClass().getName());
|
||||
buf.append('[');
|
||||
buf.append("select=");
|
||||
buf.append(select);
|
||||
if (disableOutputEscaping)
|
||||
{
|
||||
buf.append(",disableOutputEscaping");
|
||||
}
|
||||
buf.append(']');
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,123 @@
|
||||
/* WhenNode.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.transform;
|
||||
|
||||
import javax.xml.namespace.QName;
|
||||
import javax.xml.transform.TransformerException;
|
||||
import org.w3c.dom.Node;
|
||||
import gnu.xml.xpath.Expr;
|
||||
|
||||
/**
|
||||
* A template node representing an XSL <code>when</code> instruction.
|
||||
*
|
||||
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
|
||||
*/
|
||||
final class WhenNode
|
||||
extends TemplateNode
|
||||
{
|
||||
|
||||
final Expr test;
|
||||
|
||||
WhenNode(Expr test)
|
||||
{
|
||||
this.test = test;
|
||||
}
|
||||
|
||||
TemplateNode clone(Stylesheet stylesheet)
|
||||
{
|
||||
TemplateNode ret = new WhenNode(test.clone(stylesheet));
|
||||
if (children != null)
|
||||
{
|
||||
ret.children = children.clone(stylesheet);
|
||||
}
|
||||
if (next != null)
|
||||
{
|
||||
ret.next = next.clone(stylesheet);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void doApply(Stylesheet stylesheet, QName mode,
|
||||
Node context, int pos, int len,
|
||||
Node parent, Node nextSibling)
|
||||
throws TransformerException
|
||||
{
|
||||
Object ret = test.evaluate(context, pos, len);
|
||||
boolean success = (ret instanceof Boolean) ?
|
||||
((Boolean) ret).booleanValue() :
|
||||
Expr._boolean(context, ret);
|
||||
if (success)
|
||||
{
|
||||
if (children != null)
|
||||
{
|
||||
children.apply(stylesheet, mode,
|
||||
context, pos, len,
|
||||
parent, nextSibling);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (next != null)
|
||||
{
|
||||
next.apply(stylesheet, mode,
|
||||
context, pos, len,
|
||||
parent, nextSibling);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean references(QName var)
|
||||
{
|
||||
if (test != null && test.references(var))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return super.references(var);
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
StringBuffer buf = new StringBuffer(getClass().getName());
|
||||
buf.append('[');
|
||||
buf.append("test=");
|
||||
buf.append(test);
|
||||
buf.append(']');
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,123 @@
|
||||
/* WithParam.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.transform;
|
||||
|
||||
import java.util.Collections;
|
||||
import javax.xml.namespace.QName;
|
||||
import javax.xml.transform.TransformerException;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.DocumentFragment;
|
||||
import org.w3c.dom.Node;
|
||||
import gnu.xml.xpath.Expr;
|
||||
|
||||
/**
|
||||
* A specification for setting a variable or parameter during template
|
||||
* processing with <code>apply-templates</code> or
|
||||
* <code>call-template</code>.
|
||||
*
|
||||
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
|
||||
*/
|
||||
final class WithParam
|
||||
{
|
||||
|
||||
final QName name;
|
||||
final Expr select;
|
||||
final TemplateNode content;
|
||||
|
||||
WithParam(QName name, Expr select)
|
||||
{
|
||||
this.name = name;
|
||||
this.select = select;
|
||||
content = null;
|
||||
}
|
||||
|
||||
WithParam(QName name, TemplateNode content)
|
||||
{
|
||||
this.name = name;
|
||||
this.content = content;
|
||||
select = null;
|
||||
}
|
||||
|
||||
Object getValue(Stylesheet stylesheet, QName mode,
|
||||
Node context, int pos, int len)
|
||||
throws TransformerException
|
||||
{
|
||||
if (select != null)
|
||||
{
|
||||
return select.evaluate(context, pos, len);
|
||||
}
|
||||
else
|
||||
{
|
||||
Document doc = (context instanceof Document) ? (Document) context :
|
||||
context.getOwnerDocument();
|
||||
DocumentFragment fragment = doc.createDocumentFragment();
|
||||
content.apply(stylesheet, mode,
|
||||
context, pos, len,
|
||||
fragment, null);
|
||||
return Collections.singleton(fragment);
|
||||
}
|
||||
}
|
||||
|
||||
WithParam clone(Stylesheet stylesheet)
|
||||
{
|
||||
if (content == null)
|
||||
{
|
||||
return new WithParam(name,
|
||||
select.clone(stylesheet));
|
||||
}
|
||||
else
|
||||
{
|
||||
return new WithParam(name,
|
||||
content.clone(stylesheet));
|
||||
}
|
||||
}
|
||||
|
||||
boolean references(QName var)
|
||||
{
|
||||
if (select != null && select.references(var))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (content != null && content.references(var))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,124 @@
|
||||
/* XSLComparator.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.transform;
|
||||
|
||||
import java.util.Comparator;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.text.Collator;
|
||||
import org.w3c.dom.Node;
|
||||
import gnu.xml.xpath.Expr;
|
||||
|
||||
/**
|
||||
* Comparator for sorting lists of nodes according to a list of sort keys.
|
||||
*
|
||||
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
|
||||
*/
|
||||
class XSLComparator
|
||||
implements Comparator
|
||||
{
|
||||
|
||||
final List sortKeys;
|
||||
|
||||
XSLComparator(List sortKeys)
|
||||
{
|
||||
this.sortKeys = sortKeys;
|
||||
}
|
||||
|
||||
public int compare(Object o1, Object o2)
|
||||
{
|
||||
if (o1 instanceof Node && o2 instanceof Node)
|
||||
{
|
||||
Node n1 = (Node) o1;
|
||||
Node n2 = (Node) o2;
|
||||
for (Iterator i = sortKeys.iterator(); i.hasNext(); )
|
||||
{
|
||||
SortKey sortKey = (SortKey) i.next();
|
||||
String k1 = sortKey.key(n1);
|
||||
String k2 = sortKey.key(n2);
|
||||
if ("text".equals(sortKey.dataType))
|
||||
{
|
||||
Locale locale = (sortKey.lang == null) ? Locale.getDefault() :
|
||||
new Locale(sortKey.lang);
|
||||
Collator collator = Collator.getInstance(locale);
|
||||
int d = collator.compare(k1, k2);
|
||||
if (d != 0)
|
||||
{
|
||||
switch (sortKey.caseOrder)
|
||||
{
|
||||
case SortKey.UPPER_FIRST:
|
||||
// TODO
|
||||
break;
|
||||
case SortKey.LOWER_FIRST:
|
||||
// TODO
|
||||
break;
|
||||
}
|
||||
if (sortKey.descending)
|
||||
{
|
||||
d = -d;
|
||||
}
|
||||
return d;
|
||||
}
|
||||
}
|
||||
else if ("number".equals(sortKey.dataType))
|
||||
{
|
||||
double kn1 = Expr._number(n1, k1);
|
||||
double kn2 = Expr._number(n2, k2);
|
||||
int d;
|
||||
if (Double.isNaN(kn1) || Double.isInfinite(kn2))
|
||||
{
|
||||
d = -1;
|
||||
}
|
||||
else if (Double.isNaN(kn2) || Double.isInfinite(kn1))
|
||||
{
|
||||
d = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
// conversion to int may give 0 for small numbers
|
||||
d = (kn1 > kn2) ? 1 : (kn1 < kn2) ? -1 : 0;
|
||||
}
|
||||
return (sortKey.descending) ? -d : d;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,282 @@
|
||||
/* XSLURIResolver.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.transform;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.InputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.Reader;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import javax.xml.parsers.DocumentBuilder;
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
import javax.xml.transform.ErrorListener;
|
||||
import javax.xml.transform.Source;
|
||||
import javax.xml.transform.TransformerException;
|
||||
import javax.xml.transform.URIResolver;
|
||||
import javax.xml.transform.dom.DOMSource;
|
||||
import javax.xml.transform.stream.StreamSource;
|
||||
import org.w3c.dom.Node;
|
||||
import org.xml.sax.InputSource;
|
||||
import org.xml.sax.SAXException;
|
||||
import gnu.xml.dom.ls.ReaderInputStream;
|
||||
|
||||
/**
|
||||
* URI resolver for XSLT.
|
||||
* This resolver parses external entities into DOMSources. It
|
||||
* maintains a cache of URIs to DOMSources to avoid expensive re-parsing.
|
||||
*
|
||||
* @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
|
||||
*/
|
||||
class XSLURIResolver
|
||||
implements URIResolver
|
||||
{
|
||||
|
||||
Map lastModifiedCache = new HashMap();
|
||||
Map nodeCache = new HashMap();
|
||||
DocumentBuilder builder;
|
||||
URIResolver userResolver;
|
||||
ErrorListener userListener;
|
||||
|
||||
void setUserResolver(URIResolver userResolver)
|
||||
{
|
||||
this.userResolver = userResolver;
|
||||
}
|
||||
|
||||
void setUserListener(ErrorListener userListener)
|
||||
{
|
||||
this.userListener = userListener;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear the cache.
|
||||
*/
|
||||
void flush()
|
||||
{
|
||||
lastModifiedCache.clear();
|
||||
nodeCache.clear();
|
||||
}
|
||||
|
||||
public Source resolve(String href, String base)
|
||||
throws TransformerException
|
||||
{
|
||||
Source source = null;
|
||||
if (userResolver != null)
|
||||
{
|
||||
source = userResolver.resolve(base, href);
|
||||
}
|
||||
return resolveDOM(source, href, base);
|
||||
}
|
||||
|
||||
DOMSource resolveDOM(Source source, String base, String href)
|
||||
throws TransformerException
|
||||
{
|
||||
if (source != null && source instanceof DOMSource)
|
||||
{
|
||||
return (DOMSource) source;
|
||||
}
|
||||
String systemId = (source == null) ? null : source.getSystemId();
|
||||
long lastModified = 0L, lastLastModified = 0L;
|
||||
|
||||
try
|
||||
{
|
||||
URL url = resolveURL(systemId, base, href);
|
||||
Node node = null;
|
||||
InputStream in = null;
|
||||
if (source instanceof StreamSource)
|
||||
{
|
||||
StreamSource ss = (StreamSource) source;
|
||||
in = ss.getInputStream();
|
||||
if (in == null)
|
||||
{
|
||||
Reader reader = ss.getReader();
|
||||
if (reader != null)
|
||||
{
|
||||
in = new ReaderInputStream(reader);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (in == null)
|
||||
{
|
||||
if (url != null)
|
||||
{
|
||||
systemId = url.toString();
|
||||
node = (Node) nodeCache.get(systemId);
|
||||
// Is the resource up to date?
|
||||
URLConnection conn = url.openConnection();
|
||||
Long llm = (Long) lastModifiedCache.get(systemId);
|
||||
if (llm != null)
|
||||
{
|
||||
lastLastModified = llm.longValue();
|
||||
conn.setIfModifiedSince(lastLastModified);
|
||||
}
|
||||
conn.connect();
|
||||
lastModified = conn.getLastModified();
|
||||
if (node != null &&
|
||||
lastModified > 0L &&
|
||||
lastModified <= lastLastModified)
|
||||
{
|
||||
// Resource unchanged
|
||||
return new DOMSource(node, systemId);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Resource new or modified
|
||||
in = conn.getInputStream();
|
||||
nodeCache.put(systemId, node);
|
||||
lastModifiedCache.put(systemId, new Long(lastModified));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new TransformerException("can't resolve URL: " +
|
||||
systemId);
|
||||
}
|
||||
}
|
||||
InputSource input = new InputSource(in);
|
||||
input.setSystemId(systemId);
|
||||
DocumentBuilder builder = getDocumentBuilder();
|
||||
node = builder.parse(input);
|
||||
return new DOMSource(node, systemId);
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
throw new TransformerException(e);
|
||||
}
|
||||
catch (SAXException e)
|
||||
{
|
||||
throw new TransformerException(e);
|
||||
}
|
||||
}
|
||||
|
||||
URL resolveURL(String systemId, String base, String href)
|
||||
throws IOException
|
||||
{
|
||||
URL url = null;
|
||||
try
|
||||
{
|
||||
if (systemId != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
url = new URL(systemId);
|
||||
}
|
||||
catch (MalformedURLException e)
|
||||
{
|
||||
// Try building from base + href
|
||||
}
|
||||
}
|
||||
if (url == null)
|
||||
{
|
||||
if (base != null)
|
||||
{
|
||||
URL baseURL = new URL(base);
|
||||
url = new URL(baseURL, href);
|
||||
}
|
||||
else if (href != null)
|
||||
{
|
||||
url = new URL(href);
|
||||
}
|
||||
else
|
||||
{
|
||||
// See below
|
||||
throw new MalformedURLException(systemId);
|
||||
}
|
||||
}
|
||||
return url;
|
||||
}
|
||||
catch (MalformedURLException e)
|
||||
{
|
||||
// Fall back to local filesystem
|
||||
File file = null;
|
||||
if (href == null)
|
||||
{
|
||||
href = systemId;
|
||||
}
|
||||
if (base != null)
|
||||
{
|
||||
int lsi = base.lastIndexOf(File.separatorChar);
|
||||
if (lsi != -1 && lsi < base.length() - 1)
|
||||
{
|
||||
base = base.substring(0, lsi);
|
||||
}
|
||||
File baseFile = new File(base);
|
||||
file = new File(baseFile, href);
|
||||
}
|
||||
else if (href != null)
|
||||
{
|
||||
file = new File(href);
|
||||
}
|
||||
return (file == null) ? null : file.toURL();
|
||||
}
|
||||
}
|
||||
|
||||
DocumentBuilder getDocumentBuilder()
|
||||
throws TransformerException
|
||||
{
|
||||
try
|
||||
{
|
||||
if (builder == null)
|
||||
{
|
||||
DocumentBuilderFactory factory =
|
||||
DocumentBuilderFactory.newInstance();
|
||||
factory.setNamespaceAware(true);
|
||||
factory.setExpandEntityReferences(true);
|
||||
builder = factory.newDocumentBuilder();
|
||||
}
|
||||
if (userResolver != null)
|
||||
{
|
||||
builder.setEntityResolver(new URIResolverEntityResolver(userResolver));
|
||||
}
|
||||
if (userListener != null)
|
||||
{
|
||||
builder.setErrorHandler(new ErrorListenerErrorHandler(userListener));
|
||||
}
|
||||
return builder;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
throw new TransformerException(e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
<html>
|
||||
<body>
|
||||
|
||||
<h1>GNU JAXP XSL transformer</h1>
|
||||
|
||||
<div>
|
||||
This package contains a Java XSL transformer compliant with the JAXP
|
||||
specification. It depends on the GNU DOM and XPath implementations, and
|
||||
will generate GNU DOM nodes unless a specific target from another
|
||||
implementation was given. It understands DOM, SAX, and stream sources
|
||||
and result sinks and supports these JAXP features.
|
||||
</div>
|
||||
|
||||
<div>
|
||||
To use this transformer, set the system property
|
||||
<code>javax.xml.transform.TransformerFactory</code> to the value
|
||||
<code>gnu.xml.transform.TransformerFactoryImpl</code>. You can then
|
||||
instantiate <a href='TransformerFactory.html'>TransformerFactory</a>
|
||||
and transformers in the ordinary manner. Reuse of stylesheets is
|
||||
supported using the JAXP <a href='Templates.html'>Templates</a>
|
||||
mechanism.
|
||||
</div>
|
||||
|
||||
<h3>Architecture</h3>
|
||||
|
||||
<div>
|
||||
When given a stylesheet source, this implementation compiles it internally
|
||||
into a Stylesheet object, which is a container for templates and state.
|
||||
Each stylesheet instruction is represented by a subclass of TemplateNode,
|
||||
which is arranged in a directed graph: each TemplateNode has a reference
|
||||
to its first child and the next node.
|
||||
</div>
|
||||
|
||||
<div>
|
||||
The transformation process consists of identifying the Template that matches
|
||||
the root of the source context, and calling <code>apply</code> on its
|
||||
corresponding TemplateNode. This in turn processes its children and next
|
||||
TemplateNode, depending on the semantics of each node type.
|
||||
</div>
|
||||
|
||||
<div>
|
||||
Template nodes may reference XPath expressions or patterns. These are fully
|
||||
compiled to objects of type <a href='../xpath/Expr.html'>Expr</a> at the
|
||||
time the stylesheet is compiled.
|
||||
</div>
|
||||
|
||||
<h3>Conformance</h3>
|
||||
|
||||
<div>
|
||||
This implementation is feature complete, but the XSLT specification is
|
||||
large and there are still many bugs that need to be ironed out. It has
|
||||
been tested against the OASIS XSLT TC test suite, comprising unit tests
|
||||
from the Xalan project and Microsoft. Conformance to these unit tests
|
||||
is approximately 70% at the current time, although normal usage of the
|
||||
transformer should involve relatively few surprises (the test suite is
|
||||
designed to test very complex and obscure functionality).
|
||||
</div>
|
||||
|
||||
<h3>Known bugs</h3>
|
||||
|
||||
<ul>
|
||||
<li>When reusing stylesheets using the JAXP Templates mechanism, XSL
|
||||
<code>apply-imports</code> instructions will not work.</li>
|
||||
<li>XPath filter expressions do not always work as expected (this is a
|
||||
problem with the GNU XPath implementation rather than the transformer).
|
||||
This can result in problems with the <code>position()</code> function,
|
||||
as well as <code>select</code> expressions and numbering.</li>
|
||||
</ul>
|
||||
|
||||
<div>
|
||||
Obviously we'd like to improve conformance and fix these bugs. If you're
|
||||
interested in working on any of these issues please
|
||||
<a href='mailto:classpathx-xml@gnu.org'>contact us</a>.
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user