/** * Get the owning xsl:template element. * * @return The owning xsl:template element, this element if it is a xsl:template, or null if not * found. */ public ElemTemplate getOwnerXSLTemplate() { ElemTemplateElement el = this; int type = el.getXSLToken(); while ((null != el) && (type != Constants.ELEMNAME_TEMPLATE)) { el = el.getParentElem(); if (null != el) type = el.getXSLToken(); } return (ElemTemplate) el; }
/* 35: */ /* 36: */ private boolean hasFallbackChildren() /* 37: */ { /* 38: 86 */ for (ElemTemplateElement child = this.m_firstChild; child != null; child = child.m_nextSibling) { /* 39: 89 */ if (child.getXSLToken() == 57) { /* 40: 90 */ return true; /* 41: */ } /* 42: */ } /* 43: 93 */ return false; /* 44: */ }
/** * Compares this object with the specified object for precedence order. The order is determined by * the getImportCountComposed() of the containing composed stylesheet and the getUid() of this * element. Returns a negative integer, zero, or a positive integer as this object is less than, * equal to, or greater than the specified object. * * @param o The object to be compared to this object * @return a negative integer, zero, or a positive integer as this object is less than, equal to, * or greater than the specified object. * @throws ClassCastException if the specified object's type prevents it from being compared to * this Object. */ public int compareTo(Object o) throws ClassCastException { ElemTemplateElement ro = (ElemTemplateElement) o; int roPrecedence = ro.getStylesheetComposed().getImportCountComposed(); int myPrecedence = this.getStylesheetComposed().getImportCountComposed(); if (myPrecedence < roPrecedence) return -1; else if (myPrecedence > roPrecedence) return 1; else return this.getUid() - ro.getUid(); }
/** * This function is called after everything else has been recomposed, and allows the template to * set remaining values that may be based on some other property that depends on recomposition. */ public void compose(StylesheetRoot sroot) throws TransformerException { resolvePrefixTables(); ElemTemplateElement t = getFirstChildElem(); m_hasTextLitOnly = ((t != null) && (t.getXSLToken() == Constants.ELEMNAME_TEXTLITERALRESULT) && (t.getNextSiblingElem() == null)); StylesheetRoot.ComposeState cstate = sroot.getComposeState(); cstate.pushStackMark(); }
/** * Get the previous sibling (as a Node) or return null. Note that this may be expensive if the * parent has many kids; we accept that price in exchange for avoiding the prev pointer TODO: If * we were sure parents and sibs are always ElemTemplateElements, we could hit the fields directly * rather than thru accessors. * * @return This node's previous sibling or null */ public ElemTemplateElement getPreviousSiblingElem() { ElemTemplateElement walker = getParentNodeElem(); ElemTemplateElement prev = null; if (walker != null) for (walker = walker.getFirstChildElem(); walker != null; prev = walker, walker = walker.getNextSiblingElem()) { if (walker == this) return prev; } return null; }
/** * Append the current template element to the current template element, and then push it onto the * current template element stack. * * @param handler non-null reference to current StylesheetHandler that is constructing the * Templates. * @param elem non-null reference to a {@link org.apache.xalan.templates.ElemText}. * @throws org.xml.sax.SAXException Any SAX exception, possibly wrapping another exception. */ protected void appendAndPush(StylesheetHandler handler, ElemTemplateElement elem) throws org.xml.sax.SAXException { // Don't push this element onto the element stack. ProcessorCharacters charProcessor = (ProcessorCharacters) handler.getProcessorFor(null, "text()", "text"); charProcessor.setXslTextElement((ElemText) elem); ElemTemplateElement parent = handler.getElemTemplateElement(); parent.appendChild(elem); elem.setDOMBackPointer(handler.getOriginatingNode()); }
/** * This function is called after everything else has been recomposed, and allows the template to * set remaining values that may be based on some other property that depends on recomposition. */ public void compose(StylesheetRoot sroot) throws TransformerException { // See if we can reduce an RTF to a select with a string expression. if (null == m_selectPattern && sroot.getOptimizer()) { XPath newSelect = rewriteChildToExpression(this); if (null != newSelect) m_selectPattern = newSelect; } StylesheetRoot.ComposeState cstate = sroot.getComposeState(); // This should be done before addVariableName, so we don't have visibility // to the variable now being defined. java.util.Vector vnames = cstate.getVariableNames(); if (null != m_selectPattern) m_selectPattern.fixupVariables(vnames, cstate.getGlobalsSize()); // Only add the variable if this is not a global. If it is a global, // it was already added by stylesheet root. if (!(m_parentNode instanceof Stylesheet) && m_qname != null) { m_index = cstate.addVariableName(m_qname) - cstate.getGlobalsSize(); } else if (m_parentNode instanceof Stylesheet) { // If this is a global, then we need to treat it as if it's a xsl:template, // and count the number of variables it contains. So we set the count to // zero here. cstate.resetStackFrameSize(); } // This has to be done after the addVariableName, so that the variable // pushed won't be immediately popped again in endCompose. super.compose(sroot); }
/** * This after the template's children have been composed. We have to get the count of how many * variables have been declared, so we can do a link and unlink. */ public void endCompose(StylesheetRoot sroot) throws TransformerException { super.endCompose(sroot); if (m_parentNode instanceof Stylesheet) { StylesheetRoot.ComposeState cstate = sroot.getComposeState(); m_frameSize = cstate.getFrameSize(); cstate.resetStackFrameSize(); } }
/** This after the template's children have been composed. */ public void endCompose(StylesheetRoot sroot) throws TransformerException { int length = getSortElemCount(); for (int i = 0; i < length; i++) { getSortElem(i).endCompose(sroot); } super.endCompose(sroot); }
/** * Remove a child. ADDED 9/8/200 to support compilation. TODO: ***** Alternative is "removeMe() * from my parent if any" ... which is less well checked, but more convenient in some cases. Given * that we assume only experts are calling this class, it might be preferable. It's less DOMish, * though. * * @param childETE The child to remove. This operation is a no-op if oldChild is not a child of * this node. * @return the removed child, or null if the specified node was not a child of this element. */ public ElemTemplateElement removeChild(ElemTemplateElement childETE) { if (childETE == null || childETE.m_parentNode != this) return null; // Pointers to the child if (childETE == m_firstChild) m_firstChild = childETE.m_nextSibling; else { ElemTemplateElement prev = childETE.getPreviousSiblingElem(); prev.m_nextSibling = childETE.m_nextSibling; } // Pointers from the child childETE.m_parentNode = null; childETE.m_nextSibling = null; return childETE; }
/** * Add a child to the child list. NOTE: This presumes the child did not previously have a parent. * Making that assumption makes this a less expensive operation -- but requires that if you *do* * want to reparent a node, you use removeChild() first to remove it from its previous context. * Failing to do so will damage the tree. * * @param elem Child to be added to child list * @return Child just added to the child list */ public ElemTemplateElement appendChild(ElemTemplateElement elem) { if (null == elem) { error(XSLTErrorResources.ER_NULL_CHILD, null); // "Trying to add a null child!"); } if (null == m_firstChild) { m_firstChild = elem; } else { ElemTemplateElement last = getLastChildElem(); last.m_nextSibling = elem; } elem.setParentElem(this); return elem; }
/** * This function is called after everything else has been recomposed, and allows the template to * set remaining values that may be based on some other property that depends on recomposition. */ public void compose(StylesheetRoot sroot) throws TransformerException { super.compose(sroot); // Call compose on each param no matter if this is apply-templates // or call templates. int length = getParamElemCount(); for (int i = 0; i < length; i++) { ElemWithParam ewp = getParamElem(i); ewp.compose(sroot); } if ((null != m_templateName) && (null == m_template)) { m_template = this.getStylesheetRoot().getTemplateComposed(m_templateName); if (null == m_template) { String themsg = XSLMessages.createMessage( XSLTErrorResources.ER_ELEMTEMPLATEELEM_ERR, new Object[] {m_templateName}); throw new TransformerException(themsg, this); // "Could not find template named: '"+templateName+"'"); } length = getParamElemCount(); for (int i = 0; i < length; i++) { ElemWithParam ewp = getParamElem(i); ewp.m_index = -1; // Find the position of the param in the template being called, // and set the index of the param slot. int etePos = 0; for (ElemTemplateElement ete = m_template.getFirstChildElem(); null != ete; ete = ete.getNextSiblingElem()) { if (ete.getXSLToken() == Constants.ELEMNAME_PARAMVARIABLE) { ElemParam ep = (ElemParam) ete; if (ep.getName().equals(ewp.getName())) { ewp.m_index = etePos; } } else break; etePos++; } } } }
/* 17: */ /* 18: */ private void executeFallbacks(TransformerImpl transformer) /* 19: */ throws TransformerException /* 20: */ { /* 21: 60 */ for (ElemTemplateElement child = this.m_firstChild; child != null; child = child.m_nextSibling) { /* 22: 63 */ if (child.getXSLToken() == 57) { /* 23: */ try /* 24: */ { /* 25: 67 */ transformer.pushElemTemplateElement(child); /* 26: 68 */ ((ElemFallback) child).executeFallback(transformer); /* 27: */ } /* 28: */ finally /* 29: */ { /* 30: 72 */ transformer.popElemTemplateElement(); /* 31: */ } /* 32: */ } /* 33: */ } /* 34: */ }
/** * Add a child to the child list. NOTE: This presumes the child did not previously have a parent. * Making that assumption makes this a less expensive operation -- but requires that if you *do* * want to reparent a node, you use removeChild() first to remove it from its previous context. * Failing to do so will damage the tree. * * @param newChild Child to be added to child list * @return Child just added to the child list * @throws DOMException */ public Node appendChild(Node newChild) throws DOMException { if (null == newChild) { error(XSLTErrorResources.ER_NULL_CHILD, null); // "Trying to add a null child!"); } ElemTemplateElement elem = (ElemTemplateElement) newChild; if (null == m_firstChild) { m_firstChild = elem; } else { ElemTemplateElement last = (ElemTemplateElement) getLastChild(); last.m_nextSibling = elem; } elem.m_parentNode = this; return newChild; }
/** * Call the children visitors. * * @param visitor The visitor whose appropriate method will be called. */ public void callChildVisitors(XSLTVisitor visitor, boolean callAttributes) { if (callAttributes && (null != m_selectExpression)) m_selectExpression.callVisitors(this, visitor); int length = getSortElemCount(); for (int i = 0; i < length; i++) { getSortElem(i).callVisitors(visitor); } super.callChildVisitors(visitor, callAttributes); }
/** * If the children of a variable is a single xsl:value-of or text literal, it is cheaper to * evaluate this as an expression, so try and adapt the child an an expression. * * @param varElem Should be a ElemParam, ElemVariable, or ElemWithParam. * @return An XPath if rewrite is possible, else null. * @throws javax.xml.transform.TransformerException */ static XPath rewriteChildToExpression(ElemTemplateElement varElem) throws TransformerException { ElemTemplateElement t = varElem.getFirstChildElem(); // Down the line this can be done with multiple string objects using // the concat function. if (null != t && null == t.getNextSiblingElem()) { int etype = t.getXSLToken(); if (Constants.ELEMNAME_VALUEOF == etype) { ElemValueOf valueof = (ElemValueOf) t; // %TBD% I'm worried about extended attributes here. if (valueof.getDisableOutputEscaping() == false && valueof.getDOMBackPointer() == null) { varElem.m_firstChild = null; return new XPath(new XRTreeFragSelectWrapper(valueof.getSelect().getExpression())); } } else if (Constants.ELEMNAME_TEXTLITERALRESULT == etype) { ElemTextLiteral lit = (ElemTextLiteral) t; if (lit.getDisableOutputEscaping() == false && lit.getDOMBackPointer() == null) { String str = lit.getNodeValue(); XString xstr = new XString(str); varElem.m_firstChild = null; return new XPath(new XRTreeFragSelectWrapper(xstr)); } } } return null; }
public void compose(StylesheetRoot sroot) throws TransformerException { super.compose(sroot); String prefix = getPrefix(); String declNamespace = getNamespaceForPrefix(prefix); String lang = null; String srcURL = null; String scriptSrc = null; if (null == declNamespace) throw new TransformerException( XSLMessages.createMessage( XSLTErrorResources.ER_NO_NAMESPACE_DECL, new Object[] {prefix})); // "Prefix " + prefix does not have a corresponding namespace declaration"); for (ElemTemplateElement child = getFirstChildElem(); child != null; child = child.getNextSiblingElem()) { if (Constants.ELEMNAME_EXTENSIONSCRIPT == child.getXSLToken()) { ElemExtensionScript sdecl = (ElemExtensionScript) child; lang = sdecl.getLang(); srcURL = sdecl.getSrc(); ElemTemplateElement childOfSDecl = sdecl.getFirstChildElem(); if (null != childOfSDecl) { if (Constants.ELEMNAME_TEXTLITERALRESULT == childOfSDecl.getXSLToken()) { ElemTextLiteral tl = (ElemTextLiteral) childOfSDecl; char[] chars = tl.getChars(); scriptSrc = new String(chars); if (scriptSrc.trim().length() == 0) scriptSrc = null; } } } } if (null == lang) lang = "javaclass"; if (lang.equals("javaclass") && (scriptSrc != null)) throw new TransformerException( XSLMessages.createMessage( XSLTErrorResources.ER_ELEM_CONTENT_NOT_ALLOWED, new Object[] {scriptSrc})); // "Element content not allowed for lang=javaclass " + scriptSrc); // Register the extension namespace if it has not already been registered. ExtensionNamespaceSupport extNsSpt = null; ExtensionNamespacesManager extNsMgr = sroot.getExtensionNamespacesManager(); if (extNsMgr.namespaceIndex(declNamespace, extNsMgr.getExtensions()) == -1) { if (lang.equals("javaclass")) { if (null == srcURL) { extNsSpt = extNsMgr.defineJavaNamespace(declNamespace); } else if (extNsMgr.namespaceIndex(srcURL, extNsMgr.getExtensions()) == -1) { extNsSpt = extNsMgr.defineJavaNamespace(declNamespace, srcURL); } } else // not java { String handler = "org.apache.xalan.extensions.ExtensionHandlerGeneral"; Object[] args = { declNamespace, this.m_elements, this.m_functions, lang, srcURL, scriptSrc, getSystemId() }; extNsSpt = new ExtensionNamespaceSupport(declNamespace, handler, args); } } if (extNsSpt != null) extNsMgr.registerExtension(extNsSpt); }
/** * Receive notification of the start of an xsl:output element. * * @param handler The calling StylesheetHandler/TemplatesBuilder. * @param uri The Namespace URI, or the empty string if the element has no Namespace URI or if * Namespace processing is not being performed. * @param localName The local name (without prefix), or the empty string if Namespace processing * is not being performed. * @param rawName The raw XML 1.0 name (with prefix), or the empty string if raw names are not * available. * @param attributes The attributes attached to the element. If there are no attributes, it shall * be an empty Attributes object. * @throws org.xml.sax.SAXException */ public void startElement( StylesheetHandler handler, String uri, String localName, String rawName, Attributes attributes) throws org.xml.sax.SAXException { // Hmmm... for the moment I don't think I'll have default properties set for this. -sb m_outputProperties = new OutputProperties(); m_outputProperties.setDOMBackPointer(handler.getOriginatingNode()); m_outputProperties.setLocaterInfo(handler.getLocator()); m_outputProperties.setUid(handler.nextUid()); setPropertiesFromAttributes(handler, rawName, attributes, this); // Access this only from the Hashtable level... we don't want to // get default properties. String entitiesFileName = (String) m_outputProperties.getProperties().get(OutputPropertiesFactory.S_KEY_ENTITIES); if (null != entitiesFileName) { try { String absURL = SystemIDResolver.getAbsoluteURI(entitiesFileName, handler.getBaseIdentifier()); m_outputProperties.getProperties().put(OutputPropertiesFactory.S_KEY_ENTITIES, absURL); } catch (TransformerException te) { handler.error(te.getMessage(), te); } } handler.getStylesheet().setOutput(m_outputProperties); ElemTemplateElement parent = handler.getElemTemplateElement(); parent.appendChild(m_outputProperties); m_outputProperties = null; }
/** * Unimplemented. See org.w3c.dom.Node * * @param newChild New child node to insert * @param refChild Insert in front of this child * @return null * @throws DOMException */ public Node insertBefore(Node newChild, Node refChild) throws DOMException { if (null == refChild) { appendChild(newChild); return newChild; } if (newChild == refChild) { // hmm... return newChild; } Node node = m_firstChild; Node prev = null; boolean foundit = false; while (null != node) { // If the newChild is already in the tree, it is first removed. if (newChild == node) { if (null != prev) ((ElemTemplateElement) prev).m_nextSibling = (ElemTemplateElement) node.getNextSibling(); else m_firstChild = (ElemTemplateElement) node.getNextSibling(); node = node.getNextSibling(); continue; // prev remains the same. } if (refChild == node) { if (null != prev) { ((ElemTemplateElement) prev).m_nextSibling = (ElemTemplateElement) newChild; } else { m_firstChild = (ElemTemplateElement) newChild; } ((ElemTemplateElement) newChild).m_nextSibling = (ElemTemplateElement) refChild; ((ElemTemplateElement) newChild).setParentElem(this); prev = newChild; node = node.getNextSibling(); foundit = true; continue; } prev = node; node = node.getNextSibling(); } if (!foundit) throw new DOMException( DOMException.NOT_FOUND_ERR, "refChild was not found in insertBefore method!"); else return newChild; }
/** * This function is called after everything else has been recomposed, and allows the template to * set remaining values that may be based on some other property that depends on recomposition. * * <p>NEEDSDOC @param sroot * * @throws TransformerException */ public void compose(StylesheetRoot sroot) throws TransformerException { super.compose(sroot); int length = getSortElemCount(); for (int i = 0; i < length; i++) { getSortElem(i).compose(sroot); } java.util.Vector vnames = sroot.getComposeState().getVariableNames(); if (null != m_selectExpression) m_selectExpression.fixupVariables(vnames, sroot.getComposeState().getGlobalsSize()); else { m_selectExpression = getStylesheetRoot().m_selectDefault.getExpression(); } }
/** * Replace the old child with a new child. * * @param newChild New child to replace with * @param oldChild Old child to be replaced * @return The new child * @throws DOMException */ public Node replaceChild(Node newChild, Node oldChild) throws DOMException { if (oldChild == null || oldChild.getParentNode() != this) return null; ElemTemplateElement newChildElem = ((ElemTemplateElement) newChild); ElemTemplateElement oldChildElem = ((ElemTemplateElement) oldChild); // Fix up previous sibling. ElemTemplateElement prev = (ElemTemplateElement) oldChildElem.getPreviousSibling(); if (null != prev) prev.m_nextSibling = newChildElem; // Fix up parent (this) if (m_firstChild == oldChildElem) m_firstChild = newChildElem; newChildElem.m_parentNode = this; oldChildElem.m_parentNode = null; newChildElem.m_nextSibling = oldChildElem.m_nextSibling; oldChildElem.m_nextSibling = null; // newChildElem.m_stylesheet = oldChildElem.m_stylesheet; // oldChildElem.m_stylesheet = null; return newChildElem; }
/** * Add a child to the child list. <!ELEMENT xsl:attribute-set (xsl:attribute)*> <!ATTLIST * xsl:attribute-set name %qname; #REQUIRED use-attribute-sets %qnames; #IMPLIED > * * @param newChild Child to be added to this node's list of children * @return The child that was just added to the list of children * @throws DOMException */ public ElemTemplateElement appendChildElem(ElemTemplateElement newChild) { int type = ((ElemTemplateElement) newChild).getXSLToken(); switch (type) { case Constants.ELEMNAME_ATTRIBUTE: break; default: error( XSLTErrorResources.ER_CANNOT_ADD, new Object[] { newChild.getNodeName(), this.getNodeName() }); // "Can not add " +((ElemTemplateElement)newChild).m_elemName + // " to " + this.m_elemName); } return super.appendChild(newChild); }
/** * Replace the old child with a new child. * * @param newChildElem New child to replace with * @param oldChildElem Old child to be replaced * @return The new child * @throws DOMException */ public ElemTemplateElement replaceChild( ElemTemplateElement newChildElem, ElemTemplateElement oldChildElem) { if (oldChildElem == null || oldChildElem.getParentElem() != this) return null; // Fix up previous sibling. ElemTemplateElement prev = oldChildElem.getPreviousSiblingElem(); if (null != prev) prev.m_nextSibling = newChildElem; // Fix up parent (this) if (m_firstChild == oldChildElem) m_firstChild = newChildElem; newChildElem.m_parentNode = this; oldChildElem.m_parentNode = null; newChildElem.m_nextSibling = oldChildElem.m_nextSibling; oldChildElem.m_nextSibling = null; // newChildElem.m_stylesheet = oldChildElem.m_stylesheet; // oldChildElem.m_stylesheet = null; return newChildElem; }
/** * Add a child to the child list. * * @param newChild Child to add to this node's child list * @return Child that was just added to child list * @throws DOMException */ public ElemTemplateElement appendChild(ElemTemplateElement newChild) { int type = ((ElemTemplateElement) newChild).getXSLToken(); switch (type) { // char-instructions case Constants.ELEMNAME_TEXTLITERALRESULT: case Constants.ELEMNAME_APPLY_TEMPLATES: case Constants.ELEMNAME_APPLY_IMPORTS: case Constants.ELEMNAME_CALLTEMPLATE: case Constants.ELEMNAME_FOREACH: case Constants.ELEMNAME_VALUEOF: case Constants.ELEMNAME_COPY_OF: case Constants.ELEMNAME_NUMBER: case Constants.ELEMNAME_CHOOSE: case Constants.ELEMNAME_IF: case Constants.ELEMNAME_TEXT: case Constants.ELEMNAME_COPY: case Constants.ELEMNAME_VARIABLE: case Constants.ELEMNAME_MESSAGE: // instructions // case Constants.ELEMNAME_PI: // case Constants.ELEMNAME_COMMENT: // case Constants.ELEMNAME_ELEMENT: // case Constants.ELEMNAME_ATTRIBUTE: break; default: error( XSLTErrorResources.ER_CANNOT_ADD, new Object[] { newChild.getNodeName(), this.getNodeName() }); // "Can not add " +((ElemTemplateElement)newChild).m_elemName + // " to " + this.m_elemName); } return super.appendChild(newChild); }
/** * Get a variable based on it's qualified name. This is for external use only. * * @param xctxt The XPath context, which must be passed in order to lazy evaluate variables. * @param qname The qualified name of the variable. * @return The evaluated value of the variable. * @throws javax.xml.transform.TransformerException */ public XObject getVariableOrParam(XPathContext xctxt, org.apache.xml.utils.QName qname) throws javax.xml.transform.TransformerException { org.apache.xml.utils.PrefixResolver prefixResolver = xctxt.getNamespaceContext(); // Get the current ElemTemplateElement, which must be pushed in as the // prefix resolver, and then walk backwards in document order, searching // for an xsl:param element or xsl:variable element that matches our // qname. If we reach the top level, use the StylesheetRoot's composed // list of top level variables and parameters. if (prefixResolver instanceof org.apache.xalan.templates.ElemTemplateElement) { org.apache.xalan.templates.ElemVariable vvar; org.apache.xalan.templates.ElemTemplateElement prev = (org.apache.xalan.templates.ElemTemplateElement) prefixResolver; if (!(prev instanceof org.apache.xalan.templates.Stylesheet)) { while (!(prev.getParentNode() instanceof org.apache.xalan.templates.Stylesheet)) { org.apache.xalan.templates.ElemTemplateElement savedprev = prev; while (null != (prev = prev.getPreviousSiblingElem())) { if (prev instanceof org.apache.xalan.templates.ElemVariable) { vvar = (org.apache.xalan.templates.ElemVariable) prev; if (vvar.getName().equals(qname)) return getLocalVariable(xctxt, vvar.getIndex()); } } prev = savedprev.getParentElem(); } } vvar = prev.getStylesheetRoot().getVariableOrParamComposed(qname); if (null != vvar) return getGlobalVariable(xctxt, vvar.getIndex()); } throw new javax.xml.transform.TransformerException( XSLMessages.createXPATHMessage( XPATHErrorResources.ER_VAR_NOT_RESOLVABLE, new Object[] {qname.toString()})); // "Variable not resolvable: " + qname); }
/** * Perform a query if needed, and call transformNode for each child. * * @param transformer non-null reference to the the current transform-time state. * @throws TransformerException Thrown in a variety of circumstances. * @xsl.usage advanced */ public void transformSelectedNodes(TransformerImpl transformer) throws TransformerException { final XPathContext xctxt = transformer.getXPathContext(); final int sourceNode = xctxt.getCurrentNode(); DTMIterator sourceNodes = m_selectExpression.asIterator(xctxt, sourceNode); try { final Vector keys = (m_sortElems == null) ? null : transformer.processSortKeys(this, sourceNode); // Sort if we need to. if (null != keys) sourceNodes = sortNodes(xctxt, keys, sourceNodes); if (transformer.getDebug()) { // The original code, which is broken for bug#16889, // which fails to get the original select expression in the select event. /* transformer.getTraceManager().fireSelectedEvent( * sourceNode, * this, * "select", * new XPath(m_selectExpression), * new org.apache.xpath.objects.XNodeSet(sourceNodes)); */ // The following code fixes bug#16889 // Solution: Store away XPath in setSelect(Xath), and use it here. // Pass m_xath, which the current node is associated with, onto the TraceManager. Expression expr = m_xpath.getExpression(); org.apache.xpath.objects.XObject xObject = expr.execute(xctxt); int current = xctxt.getCurrentNode(); transformer.getTraceManager().fireSelectedEvent(current, this, "select", m_xpath, xObject); } xctxt.pushCurrentNode(DTM.NULL); IntStack currentNodes = xctxt.getCurrentNodeStack(); xctxt.pushCurrentExpressionNode(DTM.NULL); IntStack currentExpressionNodes = xctxt.getCurrentExpressionNodeStack(); xctxt.pushSAXLocatorNull(); xctxt.pushContextNodeList(sourceNodes); transformer.pushElemTemplateElement(null); // pushParams(transformer, xctxt); // Should be able to get this from the iterator but there must be a bug. DTM dtm = xctxt.getDTM(sourceNode); int docID = sourceNode & DTMManager.IDENT_DTM_DEFAULT; int child; while (DTM.NULL != (child = sourceNodes.nextNode())) { currentNodes.setTop(child); currentExpressionNodes.setTop(child); if ((child & DTMManager.IDENT_DTM_DEFAULT) != docID) { dtm = xctxt.getDTM(child); docID = child & DTMManager.IDENT_DTM_DEFAULT; } // final int exNodeType = dtm.getExpandedTypeID(child); final int nodeType = dtm.getNodeType(child); // Fire a trace event for the template. if (transformer.getDebug()) { transformer.getTraceManager().fireTraceEvent(this); } // And execute the child templates. // Loop through the children of the template, calling execute on // each of them. for (ElemTemplateElement t = this.m_firstChild; t != null; t = t.m_nextSibling) { xctxt.setSAXLocator(t); transformer.setCurrentElement(t); t.execute(transformer); } if (transformer.getDebug()) { // We need to make sure an old current element is not // on the stack. See TransformerImpl#getElementCallstack. transformer.setCurrentElement(null); transformer.getTraceManager().fireTraceEndEvent(this); } // KLUGE: Implement <?xalan:doc_cache_off?> // ASSUMPTION: This will be set only when the XPath was indeed // a call to the Document() function. Calling it in other // situations is likely to fry Xalan. // // %REVIEW% We need a MUCH cleaner solution -- one that will // handle cleaning up after document() and getDTM() in other // contexts. The whole SourceTreeManager mechanism should probably // be moved into DTMManager rather than being explicitly invoked in // FuncDocument and here. if (m_doc_cache_off) { if (DEBUG) System.out.println( "JJK***** CACHE RELEASE *****\n" + "\tdtm=" + dtm.getDocumentBaseURI()); // NOTE: This will work because this is _NOT_ a shared DTM, and thus has // only a single Document node. If it could ever be an RTF or other // shared DTM, this would require substantial rework. xctxt.getSourceTreeManager().removeDocumentFromCache(dtm.getDocument()); xctxt.release(dtm, false); } } } finally { if (transformer.getDebug()) transformer .getTraceManager() .fireSelectedEndEvent( sourceNode, this, "select", new XPath(m_selectExpression), new org.apache.xpath.objects.XNodeSet(sourceNodes)); xctxt.popSAXLocator(); xctxt.popContextNodeList(); transformer.popElemTemplateElement(); xctxt.popCurrentExpressionNode(); xctxt.popCurrentNode(); sourceNodes.detach(); } }
/** * Receive notification of the start of an element. * * @param handler non-null reference to current StylesheetHandler that is constructing the * Templates. * @param uri The Namespace URI, or an empty string. * @param localName The local name (without prefix), or empty string if not namespace processing. * @param rawName The qualified name (with prefix). * @param attributes The specified or defaulted attributes. */ public void startElement( StylesheetHandler handler, String uri, String localName, String rawName, Attributes attributes) throws org.xml.sax.SAXException { try { ElemTemplateElement p = handler.getElemTemplateElement(); boolean excludeXSLDecl = false; boolean isLREAsStyleSheet = false; if (null == p) { // Literal Result Template as stylesheet. XSLTElementProcessor lreProcessor = handler.popProcessor(); XSLTElementProcessor stylesheetProcessor = handler.getProcessorFor(Constants.S_XSLNAMESPACEURL, "stylesheet", "xsl:stylesheet"); handler.pushProcessor(lreProcessor); Stylesheet stylesheet; try { stylesheet = getStylesheetRoot(handler); } catch (TransformerConfigurationException tfe) { throw new TransformerException(tfe); } // stylesheet.setDOMBackPointer(handler.getOriginatingNode()); // ***** Note that we're assigning an empty locator. Is this necessary? SAXSourceLocator slocator = new SAXSourceLocator(); Locator locator = handler.getLocator(); if (null != locator) { slocator.setLineNumber(locator.getLineNumber()); slocator.setColumnNumber(locator.getColumnNumber()); slocator.setPublicId(locator.getPublicId()); slocator.setSystemId(locator.getSystemId()); } stylesheet.setLocaterInfo(slocator); stylesheet.setPrefixes(handler.getNamespaceSupport()); handler.pushStylesheet(stylesheet); isLREAsStyleSheet = true; AttributesImpl stylesheetAttrs = new AttributesImpl(); AttributesImpl lreAttrs = new AttributesImpl(); int n = attributes.getLength(); for (int i = 0; i < n; i++) { String attrLocalName = attributes.getLocalName(i); String attrUri = attributes.getURI(i); String value = attributes.getValue(i); if ((null != attrUri) && attrUri.equals(Constants.S_XSLNAMESPACEURL)) { stylesheetAttrs.addAttribute( null, attrLocalName, attrLocalName, attributes.getType(i), attributes.getValue(i)); } else if ((attrLocalName.startsWith("xmlns:") || attrLocalName.equals("xmlns")) && value.equals(Constants.S_XSLNAMESPACEURL)) { // ignore } else { lreAttrs.addAttribute( attrUri, attrLocalName, attributes.getQName(i), attributes.getType(i), attributes.getValue(i)); } } attributes = lreAttrs; // Set properties from the attributes, but don't throw // an error if there is an attribute defined that is not // allowed on a stylesheet. try { stylesheetProcessor.setPropertiesFromAttributes( handler, "stylesheet", stylesheetAttrs, stylesheet); } catch (Exception e) { // This is pretty ugly, but it will have to do for now. // This is just trying to append some text specifying that // this error came from a missing or invalid XSLT namespace // declaration. // If someone comes up with a better solution, please feel // free to contribute it. -mm if (stylesheet.getDeclaredPrefixes() == null || !declaredXSLNS(stylesheet)) { throw new org.xml.sax.SAXException( XSLMessages.createWarning(XSLTErrorResources.WG_OLD_XSLT_NS, null)); } else { throw new org.xml.sax.SAXException(e); } } handler.pushElemTemplateElement(stylesheet); ElemTemplate template = new ElemTemplate(); if (slocator != null) template.setLocaterInfo(slocator); appendAndPush(handler, template); XPath rootMatch = new XPath( "/", stylesheet, stylesheet, XPath.MATCH, handler.getStylesheetProcessor().getErrorListener()); template.setMatch(rootMatch); // template.setDOMBackPointer(handler.getOriginatingNode()); stylesheet.setTemplate(template); p = handler.getElemTemplateElement(); excludeXSLDecl = true; } XSLTElementDef def = getElemDef(); Class classObject = def.getClassObject(); boolean isExtension = false; boolean isComponentDecl = false; boolean isUnknownTopLevel = false; while (null != p) { // System.out.println("Checking: "+p); if (p instanceof ElemLiteralResult) { ElemLiteralResult parentElem = (ElemLiteralResult) p; isExtension = parentElem.containsExtensionElementURI(uri); } else if (p instanceof Stylesheet) { Stylesheet parentElem = (Stylesheet) p; isExtension = parentElem.containsExtensionElementURI(uri); if ((false == isExtension) && (null != uri) && (uri.equals(Constants.S_BUILTIN_EXTENSIONS_URL) || uri.equals(Constants.S_BUILTIN_OLD_EXTENSIONS_URL))) { isComponentDecl = true; } else { isUnknownTopLevel = true; } } if (isExtension) break; p = p.getParentElem(); } ElemTemplateElement elem = null; try { if (isExtension) { // System.out.println("Creating extension(1): "+uri); elem = new ElemExtensionCall(); } else if (isComponentDecl) { elem = (ElemTemplateElement) classObject.newInstance(); } else if (isUnknownTopLevel) { // TBD: Investigate, not sure about this. -sb elem = (ElemTemplateElement) classObject.newInstance(); } else { elem = (ElemTemplateElement) classObject.newInstance(); } elem.setDOMBackPointer(handler.getOriginatingNode()); elem.setLocaterInfo(handler.getLocator()); elem.setPrefixes(handler.getNamespaceSupport(), excludeXSLDecl); if (elem instanceof ElemLiteralResult) { ((ElemLiteralResult) elem).setNamespace(uri); ((ElemLiteralResult) elem).setLocalName(localName); ((ElemLiteralResult) elem).setRawName(rawName); ((ElemLiteralResult) elem).setIsLiteralResultAsStylesheet(isLREAsStyleSheet); } } catch (InstantiationException ie) { handler.error( XSLTErrorResources.ER_FAILED_CREATING_ELEMLITRSLT, null, ie); // "Failed creating ElemLiteralResult instance!", ie); } catch (IllegalAccessException iae) { handler.error( XSLTErrorResources.ER_FAILED_CREATING_ELEMLITRSLT, null, iae); // "Failed creating ElemLiteralResult instance!", iae); } setPropertiesFromAttributes(handler, rawName, attributes, elem); // bit of a hack here... if (!isExtension && (elem instanceof ElemLiteralResult)) { isExtension = ((ElemLiteralResult) elem).containsExtensionElementURI(uri); if (isExtension) { // System.out.println("Creating extension(2): "+uri); elem = new ElemExtensionCall(); elem.setLocaterInfo(handler.getLocator()); elem.setPrefixes(handler.getNamespaceSupport()); ((ElemLiteralResult) elem).setNamespace(uri); ((ElemLiteralResult) elem).setLocalName(localName); ((ElemLiteralResult) elem).setRawName(rawName); setPropertiesFromAttributes(handler, rawName, attributes, elem); } } appendAndPush(handler, elem); } catch (TransformerException te) { throw new org.xml.sax.SAXException(te); } }
/** * <meta name="usage" content="advanced"/> Perform a query if needed, and call transformNode for * each child. * * @param transformer non-null reference to the the current transform-time state. * @param template The owning template context. * @throws TransformerException Thrown in a variety of circumstances. */ public void transformSelectedNodes(TransformerImpl transformer) throws TransformerException { final XPathContext xctxt = transformer.getXPathContext(); final int sourceNode = xctxt.getCurrentNode(); DTMIterator sourceNodes = m_selectExpression.asIterator(xctxt, sourceNode); VariableStack vars = xctxt.getVarStack(); int nParams = getParamElemCount(); int thisframe = vars.getStackFrame(); StackGuard guard = transformer.getStackGuard(); boolean check = (guard.getRecursionLimit() > -1) ? true : false; try { final Vector keys = (m_sortElems == null) ? null : transformer.processSortKeys(this, sourceNode); // Sort if we need to. if (null != keys) sourceNodes = sortNodes(xctxt, keys, sourceNodes); if (TransformerImpl.S_DEBUG) { transformer .getTraceManager() .fireSelectedEvent( sourceNode, this, "select", new XPath(m_selectExpression), new org.apache.xpath.objects.XNodeSet(sourceNodes)); } final ResultTreeHandler rth = transformer.getResultTreeHandler(); ContentHandler chandler = rth.getContentHandler(); final StylesheetRoot sroot = transformer.getStylesheet(); final TemplateList tl = sroot.getTemplateListComposed(); final boolean quiet = transformer.getQuietConflictWarnings(); // Should be able to get this from the iterator but there must be a bug. DTM dtm = xctxt.getDTM(sourceNode); int argsFrame = -1; if (nParams > 0) { // This code will create a section on the stack that is all the // evaluated arguments. These will be copied into the real params // section of each called template. argsFrame = vars.link(nParams); vars.setStackFrame(thisframe); for (int i = 0; i < nParams; i++) { ElemWithParam ewp = m_paramElems[i]; XObject obj = ewp.getValue(transformer, sourceNode); vars.setLocalVariable(i, obj, argsFrame); } vars.setStackFrame(argsFrame); } xctxt.pushCurrentNode(DTM.NULL); IntStack currentNodes = xctxt.getCurrentNodeStack(); xctxt.pushCurrentExpressionNode(DTM.NULL); IntStack currentExpressionNodes = xctxt.getCurrentExpressionNodeStack(); xctxt.pushSAXLocatorNull(); xctxt.pushContextNodeList(sourceNodes); transformer.pushElemTemplateElement(null); // pushParams(transformer, xctxt); int child; while (DTM.NULL != (child = sourceNodes.nextNode())) { currentNodes.setTop(child); currentExpressionNodes.setTop(child); if (xctxt.getDTM(child) != dtm) { dtm = xctxt.getDTM(child); } final int exNodeType = dtm.getExpandedTypeID(child); final int nodeType = dtm.getNodeType(child); final QName mode = transformer.getMode(); ElemTemplate template = tl.getTemplateFast(xctxt, child, exNodeType, mode, -1, quiet, dtm); // If that didn't locate a node, fall back to a default template rule. // See http://www.w3.org/TR/xslt#built-in-rule. if (null == template) { switch (nodeType) { case DTM.DOCUMENT_FRAGMENT_NODE: case DTM.ELEMENT_NODE: template = sroot.getDefaultRule(); // %OPT% direct faster? break; case DTM.ATTRIBUTE_NODE: case DTM.CDATA_SECTION_NODE: case DTM.TEXT_NODE: // if(rth.m_elemIsPending || rth.m_docPending) // rth.flushPending(true); transformer.pushPairCurrentMatched(sroot.getDefaultTextRule(), child); transformer.setCurrentElement(sroot.getDefaultTextRule()); // dtm.dispatchCharactersEvents(child, chandler, false); dtm.dispatchCharactersEvents(child, rth, false); transformer.popCurrentMatched(); continue; case DTM.DOCUMENT_NODE: template = sroot.getDefaultRootRule(); break; default: // No default rules for processing instructions and the like. continue; } } else { transformer.setCurrentElement(template); } transformer.pushPairCurrentMatched(template, child); if (check) guard.checkForInfinateLoop(); int currentFrameBottom; // See comment with unlink, below if (template.m_frameSize > 0) { xctxt.pushRTFContext(); currentFrameBottom = vars.getStackFrame(); // See comment with unlink, below vars.link(template.m_frameSize); // You can't do the check for nParams here, otherwise the // xsl:params might not be nulled. if ( /* nParams > 0 && */ template.m_inArgsSize > 0) { int paramIndex = 0; for (ElemTemplateElement elem = template.getFirstChildElem(); null != elem; elem = elem.getNextSiblingElem()) { if (Constants.ELEMNAME_PARAMVARIABLE == elem.getXSLToken()) { ElemParam ep = (ElemParam) elem; int i; for (i = 0; i < nParams; i++) { ElemWithParam ewp = m_paramElems[i]; if (ewp.m_qnameID == ep.m_qnameID) { XObject obj = vars.getLocalVariable(i, argsFrame); vars.setLocalVariable(paramIndex, obj); break; } } if (i == nParams) vars.setLocalVariable(paramIndex, null); } else break; paramIndex++; } } } else currentFrameBottom = 0; // Fire a trace event for the template. if (TransformerImpl.S_DEBUG) transformer.getTraceManager().fireTraceEvent(template); // And execute the child templates. // Loop through the children of the template, calling execute on // each of them. for (ElemTemplateElement t = template.m_firstChild; t != null; t = t.m_nextSibling) { xctxt.setSAXLocator(t); try { transformer.pushElemTemplateElement(t); t.execute(transformer); } finally { transformer.popElemTemplateElement(); } } if (TransformerImpl.S_DEBUG) transformer.getTraceManager().fireTraceEndEvent(template); if (template.m_frameSize > 0) { // See Frank Weiss bug around 03/19/2002 (no Bugzilla report yet). // While unlink will restore to the proper place, the real position // may have been changed for xsl:with-param, so that variables // can be accessed. // of right now. // More: // When we entered this function, the current // frame buffer (cfb) index in the variable stack may // have been manually set. If we just call // unlink(), however, it will restore the cfb to the // previous link index from the link stack, rather than // the manually set cfb. So, // the only safe solution is to restore it back // to the same position it was on entry, since we're // really not working in a stack context here. (Bug4218) vars.unlink(currentFrameBottom); xctxt.popRTFContext(); } transformer.popCurrentMatched(); } // end while (DTM.NULL != (child = sourceNodes.nextNode())) } catch (SAXException se) { transformer.getErrorListener().fatalError(new TransformerException(se)); } finally { if (TransformerImpl.S_DEBUG) transformer .getTraceManager() .fireSelectedEndEvent( sourceNode, this, "select", new XPath(m_selectExpression), new org.apache.xpath.objects.XNodeSet(sourceNodes)); // Unlink to the original stack frame if (nParams > 0) vars.unlink(thisframe); xctxt.popSAXLocator(); xctxt.popContextNodeList(); transformer.popElemTemplateElement(); xctxt.popCurrentExpressionNode(); xctxt.popCurrentNode(); sourceNodes.detach(); } }
/** * Call the children visitors. * * @param visitor The visitor whose appropriate method will be called. */ protected void callChildVisitors(XSLTVisitor visitor, boolean callAttrs) { if (null != m_selectPattern) m_selectPattern.getExpression().callVisitors(m_selectPattern, visitor); super.callChildVisitors(visitor, callAttrs); }
/** * Set the parent as an ElemTemplateElement. * * @param p This node's parent as an ElemTemplateElement */ public void setParentElem(ElemTemplateElement p) { super.setParentElem(p); p.m_hasVariableDecl = true; }