zongaro 2003/04/16 13:58:24
Modified: java/src/org/apache/xalan/xsltc/compiler DocumentCall.java
java/src/org/apache/xalan/xsltc/dom LoadDocument.java
Log:
Applying patches from Igor Hersht ([EMAIL PROTECTED]) for bug 15200 and
bug 18585.
Fixed up code that processes the document function when it has two arguments,
the second of which must be a node-set; the code didn't always resolve the
value of the first argument against the first node in the second argument, as
it
should have.
In addition, in order to simplify run-time processing, added a new
LoadDocument.documentF method that is used when the second argument to the
XSLT
document function is present; if that argument is an empty node-set, the
result
of the document function should be an empty node-set, and that logic is much
easier to code in the run-time than via generated code.
Revision Changes Path
1.17 +91 -107
xml-xalan/java/src/org/apache/xalan/xsltc/compiler/DocumentCall.java
Index: DocumentCall.java
===================================================================
RCS file:
/home/cvs/xml-xalan/java/src/org/apache/xalan/xsltc/compiler/DocumentCall.java,v
retrieving revision 1.16
retrieving revision 1.17
diff -u -r1.16 -r1.17
--- DocumentCall.java 1 Apr 2003 21:08:59 -0000 1.16
+++ DocumentCall.java 16 Apr 2003 20:58:24 -0000 1.17
@@ -79,15 +79,15 @@
final class DocumentCall extends FunctionCall {
- private Expression _uri = null;
- private Expression _base = null;
- private Type _uriType;
+ private Expression _arg1 = null;
+ private Expression _arg2 = null;
+ private Type _arg1Type;
/**
* Default function call constructor
*/
public DocumentCall(QName fname, Vector arguments) {
- super(fname, arguments);
+ super(fname, arguments);
}
/**
@@ -96,115 +96,99 @@
* URI of the document
*/
public Type typeCheck(SymbolTable stable) throws TypeCheckError {
- // At least one argument - two at most
- final int ac = argumentCount();
- if ((ac < 1) || (ac > 2)) {
- ErrorMsg msg = new ErrorMsg(ErrorMsg.ILLEGAL_ARG_ERR, this);
- throw new TypeCheckError(msg);
- }
-
- // Parse the first argument - the document URI
- _uri = argument(0);
- if (_uri instanceof LiteralExpr) {
- LiteralExpr expr = (LiteralExpr)_uri;
- if (expr.getValue().equals(EMPTYSTRING)) {
- Stylesheet stylesheet = getStylesheet();
- if (stylesheet == null) {
- ErrorMsg msg = new ErrorMsg(ErrorMsg.ILLEGAL_ARG_ERR, this);
- throw new TypeCheckError(msg);
- }
- _uri = new LiteralExpr(stylesheet.getSystemId(), EMPTYSTRING);
- }
- }
-
- _uriType = _uri.typeCheck(stable);
- if ((_uriType != Type.NodeSet) && (_uriType != Type.String)) {
- _uri = new CastExpr(_uri, Type.String);
- }
-
- // Parse the second argument - the document URI base
- if (ac == 2) {
- _base = argument(1);
- final Type baseType = _base.typeCheck(stable);
-
- if (baseType.identicalTo(Type.Node)) {
- _base = new CastExpr(_base, Type.NodeSet);
- }
- else if (baseType.identicalTo(Type.NodeSet)) {
- // falls through
- }
- else {
- ErrorMsg msg = new ErrorMsg(ErrorMsg.DOCUMENT_ARG_ERR, this);
- throw new TypeCheckError(msg);
- }
- }
+ // At least one argument - two at most
+ final int ac = argumentCount();
+ if ((ac < 1) || (ac > 2)) {
+ ErrorMsg msg = new ErrorMsg(ErrorMsg.ILLEGAL_ARG_ERR, this);
+ throw new TypeCheckError(msg);
+ }
+ if (getStylesheet() == null) {
+ ErrorMsg msg = new ErrorMsg(ErrorMsg.ILLEGAL_ARG_ERR, this);
+ throw new TypeCheckError(msg);
+ }
+
+ // Parse the first argument
+ _arg1 = argument(0);
+
+ if (_arg1 == null) {// should not happened
+ ErrorMsg msg = new ErrorMsg(ErrorMsg.DOCUMENT_ARG_ERR, this);
+ throw new TypeCheckError(msg);
+ }
+
+ _arg1Type = _arg1.typeCheck(stable);
+ if ((_arg1Type != Type.NodeSet) && (_arg1Type != Type.String)) {
+ _arg1 = new CastExpr(_arg1, Type.String);
+ }
+
+ // Parse the second argument
+ if (ac == 2) {
+ _arg2 = argument(1);
+
+ if (_arg2 == null) {// should not happened
+ ErrorMsg msg = new ErrorMsg(ErrorMsg.DOCUMENT_ARG_ERR, this);
+ throw new TypeCheckError(msg);
+ }
+
+ final Type arg2Type = _arg2.typeCheck(stable);
+
+ if (arg2Type.identicalTo(Type.Node)) {
+ _arg2 = new CastExpr(_arg2, Type.NodeSet);
+ } else if (arg2Type.identicalTo(Type.NodeSet)) {
+ // falls through
+ } else {
+ ErrorMsg msg = new ErrorMsg(ErrorMsg.DOCUMENT_ARG_ERR, this);
+ throw new TypeCheckError(msg);
+ }
+ }
- return _type = Type.NodeSet;
+ return _type = Type.NodeSet;
}
-
+
/**
* Translates the document() function call to a call to LoadDocument()'s
* static method document().
*/
public void translate(ClassGenerator classGen, MethodGenerator
methodGen) {
- final ConstantPoolGen cpg = classGen.getConstantPool();
- final InstructionList il = methodGen.getInstructionList();
-
- final int domField = cpg.addFieldref(classGen.getClassName(),
- DOM_FIELD,
- DOM_INTF_SIG);
- final String docParamList =
- "("+OBJECT_SIG+STRING_SIG+STRING_SIG+TRANSLET_SIG+DOM_INTF_SIG+")"+
- NODE_ITERATOR_SIG;
- final int docIdx = cpg.addMethodref(LOAD_DOCUMENT_CLASS,
- "document", docParamList);
-
- final int uriIdx = cpg.addInterfaceMethodref(DOM_INTF,
- "getDocumentURI",
- "(I)"+STRING_SIG);
-
- final int nextIdx = cpg.addInterfaceMethodref(NODE_ITERATOR,
- NEXT, NEXT_SIG);
-
- // The URI can be either a node-set or something else cast to a string
- _uri.translate(classGen, methodGen);
- if (_uriType == Type.NodeSet)
- _uri.startResetIterator(classGen, methodGen);
-
- // The base of the URI may be given as a second argument (a node-set)
- //il.append(methodGen.loadDOM());
- if (_base != null) {
- il.append(methodGen.loadDOM());
- _base.translate(classGen, methodGen);
- il.append(new INVOKEINTERFACE(nextIdx, 1));
- il.append(new INVOKEINTERFACE(uriIdx, 2));
- }
- else {
- //TODO: (MM) Need someone to double check me on this
- // but I think this code was wrong because it would
- // resolve document() relative to the input xml
- // rather than relative to the input xsl when there
- // is no second argument!!!
- // The context node here would be at runtime in the xml
- // I think the reason this worked was because if the
- // xml fails, then the xsl is tried in the current code.
- //il.append(methodGen.loadContextNode());
- // Instead just pass in the current stylesheet
- // I think this get the stylesheet associated with the
- // context node, but...
- if (_uriType == Type.NodeSet)
- il.append(new PUSH(cpg,""));
- else
- il.append(new PUSH(cpg, getStylesheet().getSystemId()));
- }
- //il.append(new INVOKEINTERFACE(uriIdx, 2));
- il.append(new PUSH(cpg, getStylesheet().getSystemId()));
-
- // Feck the rest of the parameters on the stack
- il.append(classGen.loadTranslet());
- il.append(DUP);
- il.append(new GETFIELD(domField));
- il.append(new INVOKESTATIC(docIdx));
+ final ConstantPoolGen cpg = classGen.getConstantPool();
+ final InstructionList il = methodGen.getInstructionList();
+ final int ac = argumentCount();
+
+ final int domField = cpg.addFieldref(classGen.getClassName(),
+ DOM_FIELD,
+ DOM_INTF_SIG);
+
+ String docParamList = null;
+ if (ac == 1) {
+ // documentF(Object,String,AbstractTranslet,DOM)
+ docParamList = "("+OBJECT_SIG+STRING_SIG+TRANSLET_SIG+DOM_INTF_SIG
+ +")"+NODE_ITERATOR_SIG;
+ } else { //ac == 2; ac < 1 or as >2 was tested in typeChec()
+ // documentF(Object,DTMAxisIterator,String,AbstractTranslet,DOM)
+ docParamList = "("+OBJECT_SIG+NODE_ITERATOR_SIG+STRING_SIG
+ +TRANSLET_SIG+DOM_INTF_SIG+")"+NODE_ITERATOR_SIG;
+ }
+ final int docIdx = cpg.addMethodref(LOAD_DOCUMENT_CLASS, "documentF",
+ docParamList);
+
+
+ // The URI can be either a node-set or something else cast to a
string
+ _arg1.translate(classGen, methodGen);
+ if (_arg1Type == Type.NodeSet) {
+ _arg1.startResetIterator(classGen, methodGen);
+ }
+
+ if (ac == 2) {
+ //_arg2 == null was tested in typeChec()
+ _arg2.translate(classGen, methodGen);
+ _arg2.startResetIterator(classGen, methodGen);
+ }
+
+ // Feck the rest of the parameters on the stack
+ il.append(new PUSH(cpg, getStylesheet().getSystemId()));
+ il.append(classGen.loadTranslet());
+ il.append(DUP);
+ il.append(new GETFIELD(domField));
+ il.append(new INVOKESTATIC(docIdx));
}
}
1.16 +104 -102
xml-xalan/java/src/org/apache/xalan/xsltc/dom/LoadDocument.java
Index: LoadDocument.java
===================================================================
RCS file:
/home/cvs/xml-xalan/java/src/org/apache/xalan/xsltc/dom/LoadDocument.java,v
retrieving revision 1.15
retrieving revision 1.16
diff -u -r1.15 -r1.16
--- LoadDocument.java 7 Apr 2003 19:23:15 -0000 1.15
+++ LoadDocument.java 16 Apr 2003 20:58:24 -0000 1.16
@@ -76,6 +76,7 @@
import org.apache.xml.dtm.DTM;
import org.apache.xml.dtm.DTMAxisIterator;
import org.apache.xml.dtm.ref.DTMDefaultBase;
+import org.apache.xml.dtm.ref.EmptyIterator;
import org.xml.sax.InputSource;
import org.xml.sax.XMLReader;
@@ -83,15 +84,80 @@
public final class LoadDocument {
private static final String NAMESPACE_FEATURE =
- "http://xml.org/sax/features/namespaces";
+ "http://xml.org/sax/features/namespaces";
/**
- * Returns an iterator containing a set of nodes from an XML document
- * loaded by the document() function.
+ * Interprets the arguments passed from the document() function (see
+ * org/apache/xalan/xsltc/compiler/DocumentCall.java) and returns an
+ * iterator containing the requested nodes. Builds a union-iterator if
+ * several documents are requested.
+ * 2 arguments arg1 and arg2. document(Obj, node-set) call
*/
- public static DTMAxisIterator document(String uri, String base,
- AbstractTranslet translet, DOM dom)
- throws Exception
+ public static DTMAxisIterator documentF(Object arg1, DTMAxisIterator
arg2,
+ String xslURI, AbstractTranslet translet, DOM
dom)
+ throws TransletException {
+ String baseURI = null;
+ final int arg2FirstNode = arg2.next();
+ if (arg2FirstNode == DTMAxisIterator.END) {
+ // the second argument node-set is empty
+ return EmptyIterator.getInstance();
+ } else {
+ //System.err.println("arg2FirstNode name: "
+ // + dom.getNodeName(arg2FirstNode )+"["
+ // +Integer.toHexString(arg2FirstNode )+"]");
+ baseURI = getBaseFromURI(dom.getDocumentURI(arg2FirstNode));
+ }
+
+ try {
+ if (arg1 instanceof String) {
+ if (((String)arg1).length() == 0) {
+ return document(xslURI, "", translet, dom);
+ } else {
+ return document((String)arg1, baseURI, translet, dom);
+ }
+ } else if (arg1 instanceof DTMAxisIterator) {
+ return document((DTMAxisIterator)arg1, baseURI, translet,
dom);
+ } else {
+ final String err = "document("+arg1.toString()+")";
+ throw new IllegalArgumentException(err);
+ }
+ } catch (Exception e) {
+ throw new TransletException(e);
+ }
+ }
+ /**
+ * Interprets the arguments passed from the document() function (see
+ * org/apache/xalan/xsltc/compiler/DocumentCall.java) and returns an
+ * iterator containing the requested nodes. Builds a union-iterator if
+ * several documents are requested.
+ * 1 arguments arg. document(Obj) call
+ */
+ public static DTMAxisIterator documentF(Object arg, String xslURI,
+ AbstractTranslet translet, DOM dom)
+ throws TransletException {
+ try {
+ if (arg instanceof String) {
+ if (((String)arg).length() == 0) {
+ return document(xslURI, "", translet, dom);
+ } else {
+ return document((String)arg, getBaseFromURI(xslURI),
+ translet, dom);
+ }
+ } else if (arg instanceof DTMAxisIterator) {
+ return document((DTMAxisIterator)arg, null, translet, dom);
+ } else {
+ final String err = "document("+arg.toString()+")";
+ throw new IllegalArgumentException(err);
+ }
+ } catch (Exception e) {
+ throw new TransletException(e);
+ }
+ }
+
+
+ private static DTMAxisIterator document(String uri, String base,
+ AbstractTranslet translet, DOM dom)
+ throws Exception
{
final String originalUri = uri;
MultiDOM multiplexer = (MultiDOM)dom;
@@ -99,7 +165,7 @@
// Return an empty iterator if the URI is clearly invalid
// (to prevent some unncessary MalformedURL exceptions).
if (uri == null || uri.equals("")) {
- return(new SingletonIterator(DTM.NULL,true));
+ return(EmptyIterator.getInstance());
}
// Prepend URI base to URI (from context)
@@ -117,7 +183,7 @@
if (file.exists()) {
uri = file.toURL().toExternalForm();
}
-
+
// Check if this DOM has already been added to the multiplexer
int mask = multiplexer.getDocumentMask(uri);
if (mask != -1) {
@@ -160,8 +226,8 @@
((DTMDefaultBase)((DOMAdapter)multiplexer.getMain())
.getDOMImpl()).m_mgr;
newdom = (SAXImpl)dtmManager.getDTM(
- new SAXSource(reader, new InputSource(uri)),
- false, null, true, false,
translet.hasIdCall());
+ new SAXSource(reader, new InputSource(uri)),
+ false, null, true, false,
translet.hasIdCall());
translet.prepassDocument(newdom);
@@ -173,102 +239,38 @@
multiplexer.addDOMAdapter(domAdapter);
// Create index for any key elements
- translet.buildKeys(domAdapter, null, null,
((SAXImpl)newdom).getDocument());
+ translet.buildKeys(domAdapter, null, null,
+ ((SAXImpl)newdom).getDocument());
// Return a singleton iterator containing the root node
return new SingletonIterator(((SAXImpl)newdom).getDocument(), true);
}
- /**
- * Interprets the arguments passed from the document() function (see
- * org/apache/xalan/xsltc/compiler/DocumentCall.java) and returns an
- * iterator containing the requested nodes. Builds a union-iterator if
- * several documents are requested.
- */
- public static DTMAxisIterator document(Object arg,String xmlURI,String
xslURI,
- AbstractTranslet translet, DOM dom)
- throws TransletException {
- try {
-
- // Get the base of the current DOM's URI
- if (xmlURI != null) {
- int sep = xmlURI.lastIndexOf('\\') + 1;
- if (sep <= 0) {
- sep = xmlURI.lastIndexOf('/') + 1;
- }
- xmlURI = xmlURI.substring(0, sep); // could be empty string
- }
- else {
- xmlURI = "";
- }
-
- // Get the base of the current stylesheet's URI
- if (xslURI != null) {
- int sep = xslURI.lastIndexOf('\\') + 1;
- if (sep <= 0) {
- sep = xslURI.lastIndexOf('/') + 1;
- }
- xslURI = xslURI.substring(0, sep); // could be empty string
- }
- else {
- xslURI = "";
- }
-
- // If the argument is just a single string (an URI) we just return
- // the nodes from the one document this URI points to.
- if (arg instanceof String) {
- // First try to load doc relative to current DOM
- try {
- return document((String)arg, xmlURI, translet, dom);
- }
- // Then try to load doc relative to original stylesheet
- catch (java.io.FileNotFoundException e) {
- return document((String)arg, xslURI, translet, dom);
- }
- catch (org.xml.sax.SAXParseException e) {
- return document((String)arg, xslURI, translet, dom);
- }
- }
- // Otherwise we must create a union iterator, add the nodes from
- // all the DOMs to this iterator, and return the union in the end.
- else if (arg instanceof DTMAxisIterator) {
- UnionIterator union = new UnionIterator(dom);
- DTMAxisIterator iterator = (DTMAxisIterator)arg;
- int node;
-
- while ((node = iterator.next()) != DTM.NULL) {
- String uri = dom.getStringValueX(node);
- // Get the URI from this node if no xml URI base is set
- if ((xmlURI == null) || xmlURI.equals("")) {
- xmlURI = dom.getDocumentURI(node);
- int sep = xmlURI.lastIndexOf('\\') + 1;
- if (sep <= 0) {
- sep = xmlURI.lastIndexOf('/') + 1;
- }
- xmlURI = xmlURI.substring(0, sep);
- }
- // First try to load doc relative to current DOM
- try {
- union.addIterator(document(uri, xmlURI, translet, dom));
- }
- // Then try to load doc relative to original stylesheet
- catch (java.io.FileNotFoundException e) {
- union.addIterator(document(uri, xslURI, translet, dom));
- }
- }
- return(union);
- }
- else {
- final String err = "document("+arg.toString()+")";
- throw new IllegalArgumentException(err);
- }
- }
- catch (TransletException e) {
- throw e;
- }
- catch (Exception e) {
- throw new TransletException(e);
- }
+
+ private static DTMAxisIterator document(DTMAxisIterator arg1,
+ String baseURI,
+ AbstractTranslet translet, DOM
dom)
+ throws Exception
+ {
+ UnionIterator union = new UnionIterator(dom);
+ int node = DTM.NULL;
+
+ while ((node = arg1.next()) != DTM.NULL) {
+ String uri = dom.getStringValueX(node);
+ //document(node-set) if true; document(node-set,node-set) if
false
+ if (baseURI == null) {
+ baseURI = getBaseFromURI(dom.getDocumentURI(node));
+ }
+ union.addIterator(document(uri, baseURI, translet, dom));
+ }
+ return(union);
+ }
+
+ private static String getBaseFromURI( String uri){
+ final int backwardSep = uri.lastIndexOf('\\') + 1;
+ final int forwardSep = uri.lastIndexOf('/') + 1;
+
+ return uri.substring(0, Math.max(backwardSep, forwardSep));
}
}
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]