You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@xalan.apache.org by sa...@apache.org on 2002/04/15 21:49:55 UTC
cvs commit: xml-xalan/java/src/org/apache/xalan/xsltc/compiler AttributeValue.java AttributeValueTemplate.java Number.java XslAttribute.java XslElement.java
santiagopg 02/04/15 12:49:54
Modified: java/src/org/apache/xalan/xsltc/compiler Tag:
jaxp-ri-1_2_0-fcs-branch AttributeValue.java
AttributeValueTemplate.java Number.java
XslAttribute.java XslElement.java
Log:
New implementation of xsl:element
Revision Changes Path
No revision
No revision
1.1.12.1 +4 -4 xml-xalan/java/src/org/apache/xalan/xsltc/compiler/AttributeValue.java
Index: AttributeValue.java
===================================================================
RCS file: /home/cvs/xml-xalan/java/src/org/apache/xalan/xsltc/compiler/AttributeValue.java,v
retrieving revision 1.1
retrieving revision 1.1.12.1
diff -u -r1.1 -r1.1.12.1
--- AttributeValue.java 17 Apr 2001 18:51:20 -0000 1.1
+++ AttributeValue.java 15 Apr 2002 19:49:54 -0000 1.1.12.1
@@ -1,5 +1,5 @@
/*
- * @(#)$Id: AttributeValue.java,v 1.1 2001/04/17 18:51:20 sboag Exp $
+ * @(#)$Id: AttributeValue.java,v 1.1.12.1 2002/04/15 19:49:54 santiagopg Exp $
*
* The Apache Software License, Version 1.1
*
@@ -71,16 +71,16 @@
AttributeValue result;
if (text.indexOf('{') != -1) {
- result = new AttributeValueTemplate(text, parser);
+ result = new AttributeValueTemplate(text, parser, parent);
}
else if (text.indexOf('}') != -1) {
- result = new AttributeValueTemplate(text, parser);
+ result = new AttributeValueTemplate(text, parser, parent);
}
else {
result = new SimpleAttributeValue(text);
result.setParser(parser);
+ result.setParent(parent);
}
- result.setParent(parent);
return result;
}
}
1.5.4.1 +7 -3 xml-xalan/java/src/org/apache/xalan/xsltc/compiler/AttributeValueTemplate.java
Index: AttributeValueTemplate.java
===================================================================
RCS file: /home/cvs/xml-xalan/java/src/org/apache/xalan/xsltc/compiler/AttributeValueTemplate.java,v
retrieving revision 1.5
retrieving revision 1.5.4.1
diff -u -r1.5 -r1.5.4.1
--- AttributeValueTemplate.java 1 Feb 2002 20:07:08 -0000 1.5
+++ AttributeValueTemplate.java 15 Apr 2002 19:49:54 -0000 1.5.4.1
@@ -1,5 +1,5 @@
/*
- * @(#)$Id: AttributeValueTemplate.java,v 1.5 2002/02/01 20:07:08 tmiller Exp $
+ * @(#)$Id: AttributeValueTemplate.java,v 1.5.4.1 2002/04/15 19:49:54 santiagopg Exp $
*
* The Apache Software License, Version 1.1
*
@@ -72,10 +72,14 @@
final class AttributeValueTemplate extends AttributeValue {
- public AttributeValueTemplate(String value, Parser parser) {
+ public AttributeValueTemplate(String value, Parser parser,
+ SyntaxTreeNode parent)
+ {
+ setParent(parent);
setParser(parser);
- if (check(value, parser))
+ if (check(value, parser)) {
parseAVTemplate(0, value, parser);
+ }
}
private void parseAVTemplate(final int start, String text, Parser parser) {
1.8.4.1 +6 -6 xml-xalan/java/src/org/apache/xalan/xsltc/compiler/Number.java
Index: Number.java
===================================================================
RCS file: /home/cvs/xml-xalan/java/src/org/apache/xalan/xsltc/compiler/Number.java,v
retrieving revision 1.8
retrieving revision 1.8.4.1
diff -u -r1.8 -r1.8.4.1
--- Number.java 1 Feb 2002 20:07:08 -0000 1.8
+++ Number.java 15 Apr 2002 19:49:54 -0000 1.8.4.1
@@ -1,5 +1,5 @@
/*
- * @(#)$Id: Number.java,v 1.8 2002/02/01 20:07:08 tmiller Exp $
+ * @(#)$Id: Number.java,v 1.8.4.1 2002/04/15 19:49:54 santiagopg Exp $
*
* The Apache Software License, Version 1.1
*
@@ -129,23 +129,23 @@
}
}
else if (name.equals("format")) {
- _format = new AttributeValueTemplate(value, parser);
+ _format = new AttributeValueTemplate(value, parser, this);
_formatNeeded = true;
}
else if (name.equals("lang")) {
- _lang = new AttributeValueTemplate(value, parser);
+ _lang = new AttributeValueTemplate(value, parser, this);
_formatNeeded = true;
}
else if (name.equals("letter-value")) {
- _letterValue = new AttributeValueTemplate(value, parser);
+ _letterValue = new AttributeValueTemplate(value, parser, this);
_formatNeeded = true;
}
else if (name.equals("grouping-separator")) {
- _groupingSeparator = new AttributeValueTemplate(value, parser);
+ _groupingSeparator = new AttributeValueTemplate(value, parser, this);
_formatNeeded = true;
}
else if (name.equals("grouping-size")) {
- _groupingSize = new AttributeValueTemplate(value, parser);
+ _groupingSize = new AttributeValueTemplate(value, parser, this);
_formatNeeded = true;
}
}
1.16.4.2 +3 -3 xml-xalan/java/src/org/apache/xalan/xsltc/compiler/XslAttribute.java
Index: XslAttribute.java
===================================================================
RCS file: /home/cvs/xml-xalan/java/src/org/apache/xalan/xsltc/compiler/XslAttribute.java,v
retrieving revision 1.16.4.1
retrieving revision 1.16.4.2
diff -u -r1.16.4.1 -r1.16.4.2
--- XslAttribute.java 3 Apr 2002 19:26:49 -0000 1.16.4.1
+++ XslAttribute.java 15 Apr 2002 19:49:54 -0000 1.16.4.2
@@ -1,5 +1,5 @@
/*
- * @(#)$Id: XslAttribute.java,v 1.16.4.1 2002/04/03 19:26:49 tmiller Exp $
+ * @(#)$Id: XslAttribute.java,v 1.16.4.2 2002/04/15 19:49:54 santiagopg Exp $
*
* The Apache Software License, Version 1.1
*
@@ -137,14 +137,14 @@
// Get namespace from namespace attribute?
if (namespace != null && namespace != Constants.EMPTYSTRING) {
_prefix = lookupPrefix(namespace);
- _namespace = new AttributeValueTemplate(namespace, parser);
+ _namespace = new AttributeValueTemplate(namespace, parser, this);
}
// Get namespace from prefix in name attribute?
else if (prefix != null && prefix != Constants.EMPTYSTRING) {
_prefix = prefix;
namespace = lookupNamespace(prefix);
if (namespace != null) {
- _namespace = new AttributeValueTemplate(namespace, parser);
+ _namespace = new AttributeValueTemplate(namespace, parser, this);
}
}
1.15.4.2 +193 -81 xml-xalan/java/src/org/apache/xalan/xsltc/compiler/XslElement.java
Index: XslElement.java
===================================================================
RCS file: /home/cvs/xml-xalan/java/src/org/apache/xalan/xsltc/compiler/XslElement.java,v
retrieving revision 1.15.4.1
retrieving revision 1.15.4.2
diff -u -r1.15.4.1 -r1.15.4.2
--- XslElement.java 3 Apr 2002 19:26:49 -0000 1.15.4.1
+++ XslElement.java 15 Apr 2002 19:49:54 -0000 1.15.4.2
@@ -1,5 +1,5 @@
/*
- * @(#)$Id: XslElement.java,v 1.15.4.1 2002/04/03 19:26:49 tmiller Exp $
+ * @(#)$Id: XslElement.java,v 1.15.4.2 2002/04/15 19:49:54 santiagopg Exp $
*
* The Apache Software License, Version 1.1
*
@@ -74,10 +74,11 @@
final class XslElement extends Instruction {
- private AttributeValue _name; // name treated as AVT (7.1.3)
- private AttributeValueTemplate _namespace = null;
private String _prefix;
private boolean _ignore = false;
+ private boolean _isLiteralName = true;
+ private AttributeValueTemplate _name;
+ private AttributeValueTemplate _namespace;
/**
* Displays the contents of the element
@@ -88,92 +89,125 @@
displayContents(indent + IndentIncrement);
}
+ /**
+ * This method is now deprecated. The new implemation of this class
+ * never declares the default NS.
+ */
public boolean declaresDefaultNS() {
- return (_namespace != null && _prefix == EMPTYSTRING);
+ return false;
}
/**
- * Parses the element's contents. Special care taken for namespaces.
- * TODO: The namespace attribute that specifies the namespace to use
- * for the element is an attribute value template and not a string
- * constant. This means that we do not know what namespace is used
- * before runtime. This causes a problem with the way output namespaces
- * are handled at compile-time. We use a shortcut in this method to get
- * around the problem by treating the namaspace attribute as a constant.
- * (Yes, I know this is a hack, bad, bad, bad.)
+ * Checks if <param>str</param> is a literal (i.e. not an AVT) or not.
*/
- public void parseContents(Parser parser) {
+ private boolean isLiteral(String str) {
+ final int length = str.length();
+ for (int i = 0; i < length; i++) {
+ if (str.charAt(i) == '{' && str.charAt(i + 1) != '{') {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Simple check to determine if qname is legal. If it returns false
+ * then <param>str</param> is illegal; if it returns true then
+ * <param>str</param> may or may not be legal.
+ */
+ private boolean isLegalName(String str) {
+ if (str.indexOf(' ') > -1) {
+ return false;
+ }
+ final int colon = str.indexOf(':');
+ if (colon == 0 || colon == str.length() - 1) {
+ return false;
+ }
+ final char first = str.charAt(0);
+ if (!Character.isLetter(first) && first != '_') {
+ return false;
+ }
+ return true;
+ }
+ public void parseContents(Parser parser) {
final SymbolTable stable = parser.getSymbolTable();
- // Get the "name" attribute of the <xsl:element> element
+ // Handle the 'name' attribute
String name = getAttribute("name");
- if ((name == null) || (name.equals(EMPTYSTRING))) {
+ if (name == EMPTYSTRING) {
ErrorMsg msg = new ErrorMsg(ErrorMsg.ILLEGAL_ELEM_NAME_ERR,
name, this);
parser.reportError(WARNING, msg);
- _ignore = true; // Ignore the element if the QName is invalid
+ parseChildren(parser);
+ _ignore = true; // Ignore the element if the QName is invalid
return;
}
- // Try to construct a QName and then get the prefix and local part
- QName qname = parser.getQNameSafe(name);
- String prefix = qname.getPrefix();
- String local = qname.getLocalPart();
-
- // First try to get the namespace URI from the "namespace" attribute
+ // Get namespace attribute
String namespace = getAttribute("namespace");
- // Then try to get it from the "name" attribute QName prefix
- if (!hasAttribute("namespace")) {
- // We are supposed to use the default namespace URI if the QName
- // from the "name" attribute is not prefixed, so check that first
- if (prefix == null) prefix = EMPTYSTRING;
- // Then look up the URI that is in scope for the prefix
- namespace = lookupNamespace(prefix);
-
- // Signal error if the prefix does not map to any namespace URI
- if (namespace == null) {
- ErrorMsg err = new ErrorMsg(ErrorMsg.NAMESPACE_UNDEF_ERR,
- prefix, this);
- parser.reportError(WARNING, err);
+
+ // Optimize compilation when name is known at compile time
+ _isLiteralName = isLiteral(name);
+ if (_isLiteralName) {
+ if (!isLegalName(name)) {
+ ErrorMsg msg = new ErrorMsg(ErrorMsg.ILLEGAL_ELEM_NAME_ERR,
+ name, this);
+ parser.reportError(WARNING, msg);
parseChildren(parser);
- _ignore = true; // Ignore the element if prefix is undeclared
+ _ignore = true; // Ignore the element if the QName is invalid
return;
}
- _namespace = new AttributeValueTemplate(namespace, parser);
- _prefix = prefix;
+
+ final QName qname = parser.getQNameSafe(name);
+ String prefix = qname.getPrefix();
+ String local = qname.getLocalPart();
+
+ if (prefix == null) {
+ prefix = EMPTYSTRING;
+ }
+
+ if (!hasAttribute("namespace")) {
+ namespace = lookupNamespace(prefix);
+ if (namespace == null) {
+ ErrorMsg err = new ErrorMsg(ErrorMsg.NAMESPACE_UNDEF_ERR,
+ prefix, this);
+ parser.reportError(WARNING, err);
+ parseChildren(parser);
+ _ignore = true; // Ignore the element if prefix is undeclared
+ return;
+ }
+ _prefix = prefix;
+ _namespace = (namespace == EMPTYSTRING) ? null :
+ new AttributeValueTemplate(namespace, parser, this);
+ }
+ else {
+ if (prefix == EMPTYSTRING) {
+ if (isLiteral(namespace)) {
+ prefix = lookupPrefix(namespace);
+ if (prefix == null) {
+ prefix = stable.generateNamespacePrefix();
+ }
+ }
+
+ // Prepend prefix to local name
+ final StringBuffer newName = new StringBuffer(prefix);
+ if (prefix != EMPTYSTRING) {
+ newName.append(':');
+ }
+ name = newName.append(local).toString();
+ }
+ _prefix = prefix;
+ _namespace = new AttributeValueTemplate(namespace, parser, this);
+ }
}
- // Check if this element belongs in a specific namespace
else {
- // Get the namespace requested by the xsl:element
- _namespace = new AttributeValueTemplate(namespace, parser);
- // Get the current prefix for that namespace (if any)
- _prefix = lookupPrefix(namespace);
- // Is it the default namespace?
- if ((_prefix = prefix) == null) _prefix = EMPTYSTRING;
-
- // Construct final element QName
- if (_prefix == EMPTYSTRING)
- name = qname.getLocalPart();
- else
- name = _prefix+":"+qname.getLocalPart();
- }
-
- _name = AttributeValue.create(this, name, parser);
-
- // Next check that the local part of the QName is legal (no whitespace)
- if (_name instanceof SimpleAttributeValue) {
- if (local.equals(EMPTYSTRING) || (local.indexOf(' ') > -1)) {
- ErrorMsg err = new ErrorMsg(ErrorMsg.ILLEGAL_ELEM_NAME_ERR,
- local, this);
- parser.reportError(WARNING, err);
- parseChildren(parser);
- _ignore = true; // Ignore the element if local part is invalid
- return;
- }
+ _namespace = (namespace == EMPTYSTRING) ? null :
+ new AttributeValueTemplate(namespace, parser, this);
}
- // Handle the 'use-attribute-sets' attribute
+ _name = new AttributeValueTemplate(name, parser, this);
+
final String useSets = getAttribute("use-attribute-sets");
if (useSets.length() > 0) {
setFirstElement(new UseAttributeSets(useSets, parser));
@@ -188,34 +222,30 @@
public Type typeCheck(SymbolTable stable) throws TypeCheckError {
if (!_ignore) {
_name.typeCheck(stable);
- if (_namespace != null)
+ if (_namespace != null) {
_namespace.typeCheck(stable);
+ }
}
typeCheckContents(stable);
return Type.Void;
}
/**
- * Compiles code that emits the element with the necessary namespace
- * definitions. The element itself is ignored if the element definition
- * was in any way erronous, but the child nodes are still processed.
- * See the overriden translateContents() method as well.
+ * This method is called when the name of the element is known at compile time.
+ * In this case, there is no need to inspect the element name at runtime to
+ * determine if a prefix exists, needs to be generated, etc.
*/
- public void translate(ClassGenerator classGen, MethodGenerator methodGen) {
+ public void translateLiteral(ClassGenerator classGen, MethodGenerator methodGen) {
final ConstantPoolGen cpg = classGen.getConstantPool();
final InstructionList il = methodGen.getInstructionList();
- // Ignore this element if not correctly declared
if (!_ignore) {
- // Compile code that emits the element start tag
il.append(methodGen.loadHandler());
_name.translate(classGen, methodGen);
- il.append(DUP2); // duplicate these 2 args for endElement
+ il.append(DUP2);
il.append(methodGen.startElement());
- // Compile code that emits any needed namespace declaration
if (_namespace != null) {
- // public void attribute(final String name, final String value)
il.append(methodGen.loadHandler());
il.append(new PUSH(cpg, _prefix));
_namespace.translate(classGen,methodGen);
@@ -223,12 +253,94 @@
}
}
- // Compile code that emits the element attributes and contents
translateContents(classGen, methodGen);
- // Ignore this element if not correctly declared
if (!_ignore) {
- // Compile code that emits the element end tag
+ il.append(methodGen.endElement());
+ }
+ }
+
+ /**
+ * At runtime the compilation of xsl:element results in code that: (i)
+ * evaluates the avt for the name, (ii) checks for a prefix in the name
+ * (iii) generates a new prefix and create a new qname when necessary
+ * (iv) calls startElement() on the handler (v) looks up a uri in the XML
+ * when the prefix is not known at compile time (vi) calls namespace()
+ * on the handler (vii) evaluates the contents (viii) calls endElement().
+ */
+ public void translate(ClassGenerator classGen, MethodGenerator methodGen) {
+ LocalVariableGen local = null;
+ final ConstantPoolGen cpg = classGen.getConstantPool();
+ final InstructionList il = methodGen.getInstructionList();
+
+ // Optimize translation if element name is a literal
+ if (_isLiteralName) {
+ translateLiteral(classGen, methodGen);
+ return;
+ }
+
+ if (!_ignore) {
+ il.append(methodGen.loadHandler());
+ _name.translate(classGen, methodGen);
+
+ // Call BasisLibrary.getPrefix() and store result in local variable
+ il.append(DUP);
+ final int getPrefix = cpg.addMethodref(BASIS_LIBRARY_CLASS, "getPrefix",
+ "(" + STRING_SIG + ")" + STRING_SIG);
+ il.append(new INVOKESTATIC(getPrefix));
+ il.append(DUP);
+ local = methodGen.addLocalVariable("prefix",
+ org.apache.bcel.generic.Type.STRING,
+ il.getEnd(), null);
+ il.append(new ASTORE(local.getIndex()));
+
+ // If prefix is null then generate a prefix at runtime
+ final BranchHandle ifNotNull = il.append(new IFNONNULL(null));
+ if (_namespace != null) {
+ final int generatePrefix = cpg.addMethodref(BASIS_LIBRARY_CLASS,
+ "generatePrefix",
+ "()" + STRING_SIG);
+ il.append(new INVOKESTATIC(generatePrefix));
+ il.append(DUP);
+ il.append(new ASTORE(local.getIndex()));
+
+ // Prepend newly generated prefix to the name
+ final int makeQName = cpg.addMethodref(BASIS_LIBRARY_CLASS, "makeQName",
+ "(" + STRING_SIG + STRING_SIG + ")" + STRING_SIG);
+ il.append(new INVOKESTATIC(makeQName));
+ }
+ ifNotNull.setTarget(il.append(DUP2));
+ il.append(methodGen.startElement());
+
+ if (_namespace != null) {
+ il.append(methodGen.loadHandler());
+ il.append(new ALOAD(local.getIndex()));
+ _namespace.translate(classGen, methodGen);
+ il.append(methodGen.namespace());
+ }
+ else {
+ // If prefix not known at compile time, call DOM.lookupNamespace()
+ il.append(new ALOAD(local.getIndex()));
+ final BranchHandle ifNull = il.append(new IFNULL(null));
+ il.append(methodGen.loadHandler());
+ il.append(new ALOAD(local.getIndex()));
+
+ il.append(methodGen.loadDOM());
+ il.append(methodGen.loadCurrentNode());
+ il.append(new ALOAD(local.getIndex()));
+
+ final int lookupNamespace = cpg.addInterfaceMethodref(DOM_INTF,
+ "lookupNamespace",
+ "(I" + STRING_SIG + ")" + STRING_SIG);
+ il.append(new INVOKEINTERFACE(lookupNamespace, 3));
+ il.append(methodGen.namespace());
+ ifNull.setTarget(il.append(NOP));
+ }
+ }
+
+ translateContents(classGen, methodGen);
+
+ if (!_ignore) {
il.append(methodGen.endElement());
}
}
@@ -243,7 +355,7 @@
for (int i = 0; i < n; i++) {
final SyntaxTreeNode item =
(SyntaxTreeNode)getContents().elementAt(i);
- if ((_ignore) && (item instanceof XslAttribute)) continue;
+ if (_ignore && item instanceof XslAttribute) continue;
item.translate(classGen, methodGen);
}
}
---------------------------------------------------------------------
To unsubscribe, e-mail: xalan-cvs-unsubscribe@xml.apache.org
For additional commands, e-mail: xalan-cvs-help@xml.apache.org