/** * Execute the function. The function must return a valid object. * * @param xctxt The current execution context. * @return A valid XObject. * @throws javax.xml.transform.TransformerException */ public XObject execute(XPathContext xctxt) throws javax.xml.transform.TransformerException { String prefix; String namespace; String methName; String fullName = m_arg0.execute(xctxt).str(); int indexOfNSSep = fullName.indexOf(':'); if (indexOfNSSep < 0) { prefix = ""; namespace = Constants.S_XSLNAMESPACEURL; methName = fullName; } else { prefix = fullName.substring(0, indexOfNSSep); namespace = xctxt.getNamespaceContext().getNamespaceForPrefix(prefix); if (null == namespace) return XBoolean.S_FALSE; methName = fullName.substring(indexOfNSSep + 1); } if (namespace.equals(Constants.S_XSLNAMESPACEURL)) { try { return Keywords.functionAvailable(methName) ? XBoolean.S_TRUE : XBoolean.S_FALSE; } catch (Exception e) { return XBoolean.S_FALSE; } } else { // dml ExtensionsProvider extProvider = (ExtensionsProvider) xctxt.getOwnerObject(); return extProvider.functionAvailable(namespace, methName) ? XBoolean.S_TRUE : XBoolean.S_FALSE; } }
/** * For support of literal objects in xpaths. * * @param xctxt The XPath execution context. * @return This object. * @throws javax.xml.transform.TransformerException */ public XObject execute(XPathContext xctxt) throws javax.xml.transform.TransformerException { if (!m_doneEval) { this.m_transformer .getMsgMgr() .error( xctxt.getSAXLocator(), XSLTErrorResources.ER_REFERENCING_ITSELF, new Object[] {((ElemVariable) this.object()).getName().getLocalName()}); } VariableStack vars = xctxt.getVarStack(); // These three statements need to be combined into one operation. int currentFrame = vars.getStackFrame(); //// vars.setStackFrame(m_varStackPos); ElemVariable velem = (ElemVariable) m_obj; try { m_doneEval = false; if (-1 != velem.m_frameSize) vars.link(velem.m_frameSize); XObject var = velem.getValue(m_transformer, m_context); m_doneEval = true; return var; } finally { // These two statements need to be combined into one operation. // vars.setStackFrame(currentFrame); if (-1 != velem.m_frameSize) vars.unlink(currentFrame); } }
/** * Create a NodeSetDTM, and copy the members of the given DTMIterator into it. * * @param iterator Iterator which yields Nodes to be made members of the new set. */ public NodeSetDTM(NodeIterator iterator, XPathContext xctxt) { super(); Node node; m_manager = xctxt.getDTMManager(); while (null != (node = iterator.nextNode())) { int handle = xctxt.getDTMHandleFromNode(node); addNodeInDocOrder(handle, xctxt); } }
/** * Execute the first argument expression that is expected to return a string. If the argument is * null, then get the string value from the current context node. * * @param xctxt Runtime XPath context. * @return The string value of the first argument, or the string value of the current context node * if the first argument is null. * @throws javax.xml.transform.TransformerException if an error occurs while executing the * argument expression. */ protected XMLString getArg0AsString(XPathContext xctxt) throws javax.xml.transform.TransformerException { if (null == m_arg0) { int currentNode = xctxt.getCurrentNode(); if (DTM.NULL == currentNode) return XString.EMPTYSTRING; else { DTM dtm = xctxt.getDTM(currentNode); return dtm.getStringValue(currentNode); } } else return m_arg0.execute(xctxt).xstr(); }
/** Create a NodeSetDTM, and copy the members of the given DTMIterator into it. */ public NodeSetDTM(NodeList nodeList, XPathContext xctxt) { super(); m_manager = xctxt.getDTMManager(); int n = nodeList.getLength(); for (int i = 0; i < n; i++) { Node node = nodeList.item(i); int handle = xctxt.getDTMHandleFromNode(node); // Do not reorder or strip duplicate nodes from the given DOM nodelist addNode(handle); // addNodeInDocOrder(handle, xctxt); } }
/** * Execute the first argument expression that is expected to return a number. If the argument is * null, then get the number value from the current context node. * * @param xctxt Runtime XPath context. * @return The number value of the first argument, or the number value of the current context node * if the first argument is null. * @throws javax.xml.transform.TransformerException if an error occurs while executing the * argument expression. */ protected double getArg0AsNumber(XPathContext xctxt) throws javax.xml.transform.TransformerException { if (null == m_arg0) { int currentNode = xctxt.getCurrentNode(); if (DTM.NULL == currentNode) return 0; else { DTM dtm = xctxt.getDTM(currentNode); XMLString str = dtm.getStringValue(currentNode); return str.toDouble(); } } else return m_arg0.execute(xctxt).num(); }
/** * Get the XObject representation of the variable. * * @param transformer non-null reference to the the current transform-time state. * @param sourceNode non-null reference to the <a * href="http://www.w3.org/TR/xslt#dt-current-node">current source node</a>. * @return the XObject representation of the variable. * @throws javax.xml.transform.TransformerException */ public XObject getValue(TransformerImpl transformer, int sourceNode) throws TransformerException { XObject var; XPathContext xctxt = transformer.getXPathContext(); xctxt.pushCurrentNode(sourceNode); try { if (null != m_selectPattern) { var = m_selectPattern.execute(xctxt, sourceNode, this); var.allowDetachToRelease(false); if (transformer.getDebug()) transformer .getTraceManager() .fireSelectedEvent(sourceNode, this, "select", m_selectPattern, var); } else if (null == getFirstChildElem()) { var = XString.EMPTYSTRING; } else { // Use result tree fragment. // Global variables may be deferred (see XUnresolvedVariable) and hence // need to be assigned to a different set of DTMs than local variables // so they aren't popped off the stack on return from a template. int df; // Bugzilla 7118: A variable set via an RTF may create local // variables during that computation. To keep them from overwriting // variables at this level, push a new variable stack. ////// PROBLEM: This is provoking a variable-used-before-set ////// problem in parameters. Needs more study. try { ////////// xctxt.getVarStack().link(0); if (m_parentNode instanceof Stylesheet) // Global variable df = transformer.transformToGlobalRTF(this); else df = transformer.transformToRTF(this); } finally { ////////////// xctxt.getVarStack().unlink(); } var = new XRTreeFrag(df, xctxt, this); } } finally { xctxt.popCurrentNode(); } return var; }
/** * Return the XPathContext to be used for evaluating expressions. * * <p>If the child is nested withing a forEach tag its iteration context is used. Otherwise, a new * context is created based on an empty Document. * * @param child the tag whose context should be returned * @param pageContext the current page context * @return the XPath evaluation context */ public static XPathContext getContext(Tag child, PageContext pageContext) { // if within a forEach tag, use its context ForEachTag forEachTag = (ForEachTag) TagSupport.findAncestorWithClass(child, ForEachTag.class); if (forEachTag != null) { return forEachTag.getContext(); } // otherwise, create a new context referring to an empty document XPathContext context = new XPathContext(false); VariableStack variableStack = new JSTLVariableStack(pageContext); context.setVarStack(variableStack); int dtm = context.getDTMHandleFromNode(newEmptyDocument()); context.pushCurrentNodeAndExpression(dtm, dtm); return context; }
/** * Try and find a node that was previously counted. If found, return a positive integer that * corresponds to the count. * * @param support The XPath context to use * @param node The node to be counted. * @return The count of the node, or -1 if not found. */ int getPreviouslyCounted(XPathContext support, int node) { int n = m_countNodes.size(); m_countResult = 0; for (int i = n - 1; i >= 0; i--) { int countedNode = m_countNodes.elementAt(i); if (node == countedNode) { // Since the list is in backwards order, the count is // how many are in the rest of the list. m_countResult = i + 1 + m_countNodesStartCount; break; } DTM dtm = support.getDTM(countedNode); // Try to see if the given node falls after the counted node... // if it does, don't keep searching backwards. if (dtm.isNodeAfter(countedNode, node)) break; } return m_countResult; }
/** * Sort given nodes * * @param xctxt The XPath runtime state for the sort. * @param keys Vector of sort keyx * @param sourceNodes Iterator of nodes to sort * @return iterator of sorted nodes * @throws TransformerException */ public DTMIterator sortNodes(XPathContext xctxt, Vector keys, DTMIterator sourceNodes) throws TransformerException { NodeSorter sorter = new NodeSorter(xctxt); sourceNodes.setShouldCacheNodes(true); sourceNodes.runTo(-1); xctxt.pushContextNodeList(sourceNodes); try { sorter.sort(sourceNodes, keys, xctxt); sourceNodes.setCurrentPos(0); } finally { xctxt.popContextNodeList(); } return sourceNodes; }
/** * Tell what the test score is for the given node. * * @param xctxt XPath runtime context. * @param context The node being tested. * @return {@link org.apache.xpath.patterns.NodeTest#SCORE_NODETEST}, {@link * org.apache.xpath.patterns.NodeTest#SCORE_NONE}, {@link * org.apache.xpath.patterns.NodeTest#SCORE_NSWILD}, {@link * org.apache.xpath.patterns.NodeTest#SCORE_QNAME}, or {@link * org.apache.xpath.patterns.NodeTest#SCORE_OTHER}. * @throws javax.xml.transform.TransformerException */ public XObject execute(XPathContext xctxt, int context) throws javax.xml.transform.TransformerException { DTM dtm = xctxt.getDTM(context); short nodeType = dtm.getNodeType(context); if (m_whatToShow == DTMFilter.SHOW_ALL) return m_score; int nodeBit = (m_whatToShow & (0x00000001 << (nodeType - 1))); switch (nodeBit) { case DTMFilter.SHOW_DOCUMENT_FRAGMENT: case DTMFilter.SHOW_DOCUMENT: return SCORE_OTHER; case DTMFilter.SHOW_COMMENT: return m_score; case DTMFilter.SHOW_CDATA_SECTION: case DTMFilter.SHOW_TEXT: // was: // return (!xctxt.getDOMHelper().shouldStripSourceNode(context)) // ? m_score : SCORE_NONE; return m_score; case DTMFilter.SHOW_PROCESSING_INSTRUCTION: return subPartMatch(dtm.getNodeName(context), m_name) ? m_score : SCORE_NONE; // From the draft: "Two expanded names are equal if they // have the same local part, and either both have no URI or // both have the same URI." // "A node test * is true for any node of the principal node type. // For example, child::* will select all element children of the // context node, and attribute::* will select all attributes of // the context node." // "A node test can have the form NCName:*. In this case, the prefix // is expanded in the same way as with a QName using the context // namespace declarations. The node test will be true for any node // of the principal type whose expanded name has the URI to which // the prefix expands, regardless of the local part of the name." case DTMFilter.SHOW_NAMESPACE: { String ns = dtm.getNodeValue(context); return (subPartMatch(ns, m_name)) ? m_score : SCORE_NONE; } case DTMFilter.SHOW_ATTRIBUTE: case DTMFilter.SHOW_ELEMENT: { return (m_isTotallyWild || (subPartMatchNS(dtm.getNamespaceURI(context), m_namespace) && subPartMatch(dtm.getLocalName(context), m_name))) ? m_score : SCORE_NONE; } default: return SCORE_NONE; } // end switch(testType) }
/** * Add the node into a vector of nodes where it should occur in document order. * * @param node The node to be added. * @param test true if we should test for doc order * @param support The XPath runtime context. * @return insertIndex. * @throws RuntimeException thrown if this NodeSetDTM is not of a mutable type. */ public int addNodeInDocOrder(int node, boolean test, XPathContext support) { if (!m_mutable) throw new RuntimeException( XSLMessages.createXPATHMessage( XPATHErrorResources.ER_NODESETDTM_NOT_MUTABLE, null)); // "This NodeSetDTM is not mutable!"); int insertIndex = -1; if (test) { // This needs to do a binary search, but a binary search // is somewhat tough because the sequence test involves // two nodes. int size = size(), i; for (i = size - 1; i >= 0; i--) { int child = elementAt(i); if (child == node) { i = -2; // Duplicate, suppress insert break; } DTM dtm = support.getDTM(node); if (!dtm.isNodeAfter(node, child)) { break; } } if (i != -2) { insertIndex = i + 1; insertElementAt(node, insertIndex); } } else { insertIndex = this.size(); boolean foundit = false; for (int i = 0; i < insertIndex; i++) { if (i == node) { foundit = true; break; } } if (!foundit) addElement(node); } // checkDups(); return insertIndex; } // end addNodeInDocOrder(Vector v, Object obj)
/** * Execute the function. The function must return a valid object. * * @param xctxt The current execution context. * @return A valid XObject. * @throws javax.xml.transform.TransformerException */ public XObject execute(XPathContext xctxt) throws javax.xml.transform.TransformerException { SubContextList subContextList = xctxt.getCurrentNodeList(); int currentNode = DTM.NULL; if (null != subContextList) { if (subContextList instanceof PredicatedNodeTest) { LocPathIterator iter = ((PredicatedNodeTest) subContextList).getLocPathIterator(); currentNode = iter.getCurrentContextNode(); } else if (subContextList instanceof StepPattern) { throw new RuntimeException( XSLMessages.createMessage(XSLTErrorResources.ER_PROCESSOR_ERROR, null)); } } else { // not predicate => ContextNode == CurrentNode currentNode = xctxt.getContextNode(); } return new XNodeSet(currentNode, xctxt.getDTMManager()); }
public XNodeSetForDOM(NodeIterator nodeIter, XPathContext xctxt) { m_dtmMgr = xctxt.getDTMManager(); m_origObj = nodeIter; // JKESS 20020514: Longer-term solution is to force // folks to request length through an accessor, so we can defer this // retrieval... but that requires an API change. // m_obj = new org.apache.xpath.NodeSetDTM(nodeIter, xctxt); org.apache.xpath.NodeSetDTM nsdtm = new org.apache.xpath.NodeSetDTM(nodeIter, xctxt); m_last = nsdtm.getLength(); m_obj = nsdtm; }
/** * Evaluate XPath string to an XObject. XPath namespace prefixes are resolved from the * namespaceNode. The implementation of this is a little slow, since it creates a number of * objects each time it is called. This could be optimized to keep the same objects around, but * then thread-safety issues would arise. * * @param contextNode The node to start searching from. * @param xpathnode * @param str * @param namespaceNode The node from which prefixes in the XPath will be resolved to namespaces. * @return An XObject, which can be used to obtain a string, number, nodelist, etc, should never * be null. * @see org.apache.xpath.objects.XObject * @see org.apache.xpath.objects.XNull * @see org.apache.xpath.objects.XBoolean * @see org.apache.xpath.objects.XNumber * @see org.apache.xpath.objects.XString * @see org.apache.xpath.objects.XRTreeFrag * @throws TransformerException */ public XObject eval(Node contextNode, Node xpathnode, String str, Node namespaceNode) throws TransformerException { // Create the XPath object. // String str = CachedXPathFuncHereAPI.getStrFromNode(xpathnode); // Since we don't have a XML Parser involved here, install some default support // for things like namespaces, etc. // (Changed from: XPathContext xpathSupport = new XPathContext(); // because XPathContext is weak in a number of areas... perhaps // XPathContext should be done away with.) if (this._funcHereContext == null) { this._funcHereContext = new FuncHereContext(xpathnode, this._dtmManager); } // Create an object to resolve namespace prefixes. // XPath namespaces are resolved from the input context node's document element // if it is a root node, or else the current context node (for lack of a better // resolution space, given the simplicity of this sample code). PrefixResolverDefault prefixResolver = new PrefixResolverDefault( (namespaceNode.getNodeType() == Node.DOCUMENT_NODE) ? ((Document) namespaceNode).getDocumentElement() : namespaceNode); // only check if string points to different object (for performance) if (str != xpathStr) { if (str.indexOf("here()") > 0) { _context.reset(); _dtmManager = _context.getDTMManager(); } xpath = createXPath(str, prefixResolver); xpathStr = str; } // Execute the XPath, and have it return the result // return xpath.execute(xpathSupport, contextNode, prefixResolver); int ctxtNode = this._funcHereContext.getDTMHandleFromNode(contextNode); return xpath.execute(this._funcHereContext, ctxtNode, prefixResolver); }
/** * Evaluate XPath string to an XObject. XPath namespace prefixes are resolved from the * namespaceNode. The implementation of this is a little slow, since it creates a number of * objects each time it is called. This could be optimized to keep the same objects around, but * then thread-safety issues would arise. * * @param contextNode The node to start searching from. * @param xpathnode * @param str * @param prefixResolver Will be called if the parser encounters namespace prefixes, to resolve * the prefixes to URLs. * @return An XObject, which can be used to obtain a string, number, nodelist, etc, should never * be null. * @see org.apache.xpath.objects.XObject * @see org.apache.xpath.objects.XNull * @see org.apache.xpath.objects.XBoolean * @see org.apache.xpath.objects.XNumber * @see org.apache.xpath.objects.XString * @see org.apache.xpath.objects.XRTreeFrag * @throws TransformerException */ public XObject eval(Node contextNode, Node xpathnode, String str, PrefixResolver prefixResolver) throws TransformerException { // Since we don't have a XML Parser involved here, install some default support // for things like namespaces, etc. // (Changed from: XPathContext xpathSupport = new XPathContext(); // because XPathContext is weak in a number of areas... perhaps // XPathContext should be done away with.) // Create the XPath object. // String str = CachedXPathFuncHereAPI.getStrFromNode(xpathnode); // only check if string points to different object (for performance) if (str != xpathStr) { if (str.indexOf("here()") > 0) { _context.reset(); _dtmManager = _context.getDTMManager(); } try { xpath = createXPath(str, prefixResolver); } catch (TransformerException ex) { // Try to see if it is a problem with the classloader. Throwable th = ex.getCause(); if (th instanceof ClassNotFoundException) { if (th.getMessage().indexOf("FuncHere") > 0) { throw new RuntimeException(I18n.translate("endorsed.jdk1.4.0") /*,*/ + ex); } } throw ex; } xpathStr = str; } // Execute the XPath, and have it return the result if (this._funcHereContext == null) { this._funcHereContext = new FuncHereContext(xpathnode, this._dtmManager); } int ctxtNode = this._funcHereContext.getDTMHandleFromNode(contextNode); return xpath.execute(this._funcHereContext, ctxtNode, prefixResolver); }
/** * Get a local variable or parameter in the current stack frame. * * @param xctxt The XPath context, which must be passed in order to lazy evaluate variables. * @param index Local variable index relative to the current stack frame bottom. * @return The value of the variable. * @throws TransformerException */ public XObject getLocalVariable(XPathContext xctxt, int index) throws TransformerException { index += _currentFrameBottom; XObject val = _stackFrames[index]; if (null == val) throw new TransformerException( XSLMessages.createXPATHMessage( XPATHErrorResources.ER_VARIABLE_ACCESSED_BEFORE_BIND, null), xctxt.getSAXLocator()); // "Variable accessed before it is bound!", xctxt.getSAXLocator()); // Lazy execution of variables. if (val.getType() == XObject.CLASS_UNRESOLVEDVARIABLE) return (_stackFrames[index] = val.execute(xctxt)); return val; }
/** * 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); }
/** * Execute the first argument expression that is expected to return a nodeset. If the argument is * null, then return the current context node. * * @param xctxt Runtime XPath context. * @return The first node of the executed nodeset, or the current context node if the first * argument is null. * @throws javax.xml.transform.TransformerException if an error occurs while executing the * argument expression. */ protected int getArg0AsNode(XPathContext xctxt) throws javax.xml.transform.TransformerException { return (null == m_arg0) ? xctxt.getCurrentNode() : m_arg0.asNode(xctxt); }
/** * Invoke a named template. * * @see <a href="http://www.w3.org/TR/xslt#named-templates">named-templates in XSLT * Specification</a> * @param transformer non-null reference to the the current transform-time state. * @throws TransformerException */ public void execute(TransformerImpl transformer) throws TransformerException { if (null != m_template) { XPathContext xctxt = transformer.getXPathContext(); VariableStack vars = xctxt.getVarStack(); int thisframe = vars.getStackFrame(); int nextFrame = vars.link(m_template.m_frameSize); // We have to clear the section of the stack frame that has params // so that the default param evaluation will work correctly. if (m_template.m_inArgsSize > 0) { vars.clearLocalSlots(0, m_template.m_inArgsSize); if (null != m_paramElems) { int currentNode = xctxt.getCurrentNode(); vars.setStackFrame(thisframe); int size = m_paramElems.length; for (int i = 0; i < size; i++) { ElemWithParam ewp = m_paramElems[i]; if (ewp.m_index >= 0) { XObject obj = ewp.getValue(transformer, currentNode); // Note here that the index for ElemWithParam must have been // statically made relative to the xsl:template being called, // NOT this xsl:template. vars.setLocalVariable(ewp.m_index, obj, nextFrame); } } vars.setStackFrame(nextFrame); } } SourceLocator savedLocator = xctxt.getSAXLocator(); try { xctxt.setSAXLocator(m_template); // template.executeChildTemplates(transformer, sourceNode, mode, true); transformer.pushElemTemplateElement(m_template); m_template.execute(transformer); } finally { transformer.popElemTemplateElement(); xctxt.setSAXLocator(savedLocator); // 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(thisframe); } } else { transformer .getMsgMgr() .error( this, XSLTErrorResources.ER_TEMPLATE_NOT_FOUND, new Object[] { m_templateName }); // "Could not find template named: '"+templateName+"'"); } }
/** * Execute the function. The function must return a valid object. * * @param xctxt The current execution context. * @return A valid XObject. * @throws javax.xml.transform.TransformerException */ public XObject execute(XPathContext xctxt) throws javax.xml.transform.TransformerException { String fullName = m_arg0.execute(xctxt).str(); int indexOfNSSep = fullName.indexOf(':'); String result = null; String propName = ""; // List of properties where the name of the // property argument is to be looked for. Properties xsltInfo = new Properties(); loadPropertyFile(XSLT_PROPERTIES, xsltInfo); if (indexOfNSSep > 0) { String prefix = (indexOfNSSep >= 0) ? fullName.substring(0, indexOfNSSep) : ""; String namespace; namespace = xctxt.getNamespaceContext().getNamespaceForPrefix(prefix); propName = (indexOfNSSep < 0) ? fullName : fullName.substring(indexOfNSSep + 1); if (namespace.startsWith("http://www.w3.org/XSL/Transform") || namespace.equals("http://www.w3.org/1999/XSL/Transform")) { result = xsltInfo.getProperty(propName); if (null == result) { warn( xctxt, XPATHErrorResources.WG_PROPERTY_NOT_SUPPORTED, new Object[] {fullName}); // "XSL Property not supported: "+fullName); return XString.EMPTYSTRING; } } else { warn( xctxt, XPATHErrorResources.WG_DONT_DO_ANYTHING_WITH_NS, new Object[] { namespace, fullName }); // "Don't currently do anything with namespace "+namespace+" in property: // "+fullName); try { // if secure procession is enabled only handle required properties do not not map any // valid system property if (!xctxt.isSecureProcessing()) { result = System.getProperty(propName); } else { warn( xctxt, XPATHErrorResources.WG_SECURITY_EXCEPTION, new Object[] { fullName }); // "SecurityException when trying to access XSL system property: "+fullName); } if (null == result) { return XString.EMPTYSTRING; } } catch (SecurityException se) { warn( xctxt, XPATHErrorResources.WG_SECURITY_EXCEPTION, new Object[] { fullName }); // "SecurityException when trying to access XSL system property: "+fullName); return XString.EMPTYSTRING; } } } else { try { // if secure procession is enabled only handle required properties do not not map any valid // system property if (!xctxt.isSecureProcessing()) { result = System.getProperty(fullName); } else { warn( xctxt, XPATHErrorResources.WG_SECURITY_EXCEPTION, new Object[] { fullName }); // "SecurityException when trying to access XSL system property: "+fullName); } if (null == result) { return XString.EMPTYSTRING; } } catch (SecurityException se) { warn( xctxt, XPATHErrorResources.WG_SECURITY_EXCEPTION, new Object[] { fullName }); // "SecurityException when trying to access XSL system property: "+fullName); return XString.EMPTYSTRING; } } if (propName.equals("version") && result.length() > 0) { try { // Needs to return the version number of the spec we conform to. return new XString("1.0"); } catch (Exception ex) { return new XString(result); } } else return new XString(result); }
/** * <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(); } }
/** * Return the first node out of the nodeset, if this expression is a nodeset expression. This is * the default implementation for nodesets. Derived classes should try and override this and * return a value without having to do a clone operation. * * @param xctxt The XPath runtime context. * @return the first node out of the nodeset, or DTM.NULL. */ public int asNode(XPathContext xctxt) throws javax.xml.transform.TransformerException { return xctxt.getCurrentNode(); }
/** * Test the current node to see if it matches the given node test. * * @param xctxt XPath runtime context. * @return {@link org.apache.xpath.patterns.NodeTest#SCORE_NODETEST}, {@link * org.apache.xpath.patterns.NodeTest#SCORE_NONE}, {@link * org.apache.xpath.patterns.NodeTest#SCORE_NSWILD}, {@link * org.apache.xpath.patterns.NodeTest#SCORE_QNAME}, or {@link * org.apache.xpath.patterns.NodeTest#SCORE_OTHER}. * @throws javax.xml.transform.TransformerException */ public XObject execute(XPathContext xctxt) throws javax.xml.transform.TransformerException { return execute(xctxt, xctxt.getCurrentNode()); }
/** * 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(); } }
/** * Extension element for piping an XML document through a series of 1 or more transformations. * * <pre>Common usage pattern: A stylesheet transforms a listing of documents to be * transformed into a TOC. For each document in the listing calls the pipeDocument * extension element to pipe that document through a series of 1 or more stylesheets * to the desired output document. * * Syntax: * <xsl:stylesheet version="1.0" * xmlns:xsl="http://www.w3.org/1999/XSL/Transform" * xmlns:pipe="http://xml.apache.org/xalan/PipeDocument" * extension-element-prefixes="pipe"> * ... * <pipe:pipeDocument source="source.xml" target="target.xml"> * <stylesheet href="ss1.xsl"> * <param name="param1" value="value1"/> * </stylesheet> * <stylesheet href="ss2.xsl"> * <param name="param1" value="value1"/> * <param name="param2" value="value2"/> * </stylesheet> * <stylesheet href="ss1.xsl"/> * </pipe:pipeDocument> * * Notes:</pre> * * <ul> * <li>The base URI for the source attribute is the XML "listing" document. * <li/> * <li>The target attribute is taken as is (base is the current user directory). * <li/> * <li>The stylsheet containg the extension element is the base URI for the stylesheet hrefs. * <li/> * </ul> */ public void pipeDocument(XSLProcessorContext context, ElemExtensionCall elem) throws TransformerException, TransformerConfigurationException, SAXException, IOException, FileNotFoundException { SAXTransformerFactory saxTFactory = (SAXTransformerFactory) TransformerFactory.newInstance(); // XML doc to transform. String source = elem.getAttribute("source", context.getContextNode(), context.getTransformer()); TransformerImpl transImpl = context.getTransformer(); // Base URI for input doc, so base for relative URI to XML doc to transform. String baseURLOfSource = transImpl.getBaseURLOfSource(); // Absolute URI for XML doc to transform. String absSourceURL = SystemIDResolver.getAbsoluteURI(source, baseURLOfSource); // Transformation target String target = elem.getAttribute("target", context.getContextNode(), context.getTransformer()); XPathContext xctxt = context.getTransformer().getXPathContext(); int xt = xctxt.getDTMHandleFromNode(context.getContextNode()); // Get System Id for stylesheet; to be used to resolve URIs to other stylesheets. String sysId = elem.getSystemId(); NodeList ssNodes = null; NodeList paramNodes = null; Node ssNode = null; Node paramNode = null; if (elem.hasChildNodes()) { ssNodes = elem.getChildNodes(); // Vector to contain TransformerHandler for each stylesheet. Vector vTHandler = new Vector(ssNodes.getLength()); // The child nodes of an extension element node are instances of // ElemLiteralResult, which requires does not fully support the standard // Node interface. Accordingly, some special handling is required (see below) // to get attribute values. for (int i = 0; i < ssNodes.getLength(); i++) { ssNode = ssNodes.item(i); if (ssNode.getNodeType() == Node.ELEMENT_NODE && ((Element) ssNode).getTagName().equals("stylesheet") && ssNode instanceof ElemLiteralResult) { AVT avt = ((ElemLiteralResult) ssNode).getLiteralResultAttribute("href"); String href = avt.evaluate(xctxt, xt, elem); String absURI = SystemIDResolver.getAbsoluteURI(href, sysId); Templates tmpl = saxTFactory.newTemplates(new StreamSource(absURI)); TransformerHandler tHandler = saxTFactory.newTransformerHandler(tmpl); Transformer trans = tHandler.getTransformer(); // AddTransformerHandler to vector vTHandler.addElement(tHandler); paramNodes = ssNode.getChildNodes(); for (int j = 0; j < paramNodes.getLength(); j++) { paramNode = paramNodes.item(j); if (paramNode.getNodeType() == Node.ELEMENT_NODE && ((Element) paramNode).getTagName().equals("param") && paramNode instanceof ElemLiteralResult) { avt = ((ElemLiteralResult) paramNode).getLiteralResultAttribute("name"); String pName = avt.evaluate(xctxt, xt, elem); avt = ((ElemLiteralResult) paramNode).getLiteralResultAttribute("value"); String pValue = avt.evaluate(xctxt, xt, elem); trans.setParameter(pName, pValue); } } } } usePipe(vTHandler, absSourceURL, target); } }
/** * Constructor CachedXPathFuncHereAPI * * @param existingXPathContext */ public CachedXPathFuncHereAPI(XPathContext existingXPathContext) { this._dtmManager = existingXPathContext.getDTMManager(); this._context = existingXPathContext; }
/** * Execute the function. The function must return a valid object. * * @param xctxt The current execution context. * @return A valid XObject. * @throws javax.xml.transform.TransformerException */ public XObject execute(XPathContext xctxt) throws javax.xml.transform.TransformerException { // TransformerImpl transformer = (TransformerImpl)xctxt; TransformerImpl transformer = (TransformerImpl) xctxt.getOwnerObject(); XNodeSet nodes = null; int context = xctxt.getCurrentNode(); DTM dtm = xctxt.getDTM(context); int docContext = dtm.getDocumentRoot(context); if (DTM.NULL == docContext) { // path.error(context, XPATHErrorResources.ER_CONTEXT_HAS_NO_OWNERDOC); //"context does not // have an owner document!"); } String xkeyname = getArg0().execute(xctxt).str(); QName keyname = new QName(xkeyname, xctxt.getNamespaceContext()); XObject arg = getArg1().execute(xctxt); boolean argIsNodeSetDTM = (XObject.CLASS_NODESET == arg.getType()); KeyManager kmgr = transformer.getKeyManager(); // Don't bother with nodeset logic if the thing is only one node. if (argIsNodeSetDTM) { XNodeSet ns = (XNodeSet) arg; ns.setShouldCacheNodes(true); int len = ns.getLength(); if (len <= 1) argIsNodeSetDTM = false; } if (argIsNodeSetDTM) { Hashtable usedrefs = null; DTMIterator ni = arg.iter(); int pos; UnionPathIterator upi = new UnionPathIterator(); upi.exprSetParent(this); while (DTM.NULL != (pos = ni.nextNode())) { dtm = xctxt.getDTM(pos); XMLString ref = dtm.getStringValue(pos); if (null == ref) continue; if (null == usedrefs) usedrefs = new Hashtable(); if (usedrefs.get(ref) != null) { continue; // We already have 'em. } else { // ISTRUE being used as a dummy value. usedrefs.put(ref, ISTRUE); } XNodeSet nl = kmgr.getNodeSetDTMByKey(xctxt, docContext, keyname, ref, xctxt.getNamespaceContext()); nl.setRoot(xctxt.getCurrentNode(), xctxt); // try // { upi.addIterator(nl); // } // catch(CloneNotSupportedException cnse) // { // // will never happen. // } // mnodeset.addNodesInDocOrder(nl, xctxt); needed?? } int current = xctxt.getCurrentNode(); upi.setRoot(current, xctxt); nodes = new XNodeSet(upi); } else { XMLString ref = arg.xstr(); nodes = kmgr.getNodeSetDTMByKey(xctxt, docContext, keyname, ref, xctxt.getNamespaceContext()); nodes.setRoot(xctxt.getCurrentNode(), xctxt); } return nodes; }
/** * Copy a Literal Result Element into the Result tree, copy the non-excluded namespace attributes, * copy the attributes not of the XSLT namespace, and execute the children of the LRE. * * @see <a href="http://www.w3.org/TR/xslt#literal-result-element">literal-result-element in XSLT * Specification</a> * @param transformer non-null reference to the the current transform-time state. * @throws TransformerException */ public void execute(TransformerImpl transformer) throws TransformerException { SerializationHandler rhandler = transformer.getSerializationHandler(); try { // JJK Bugzilla 3464, test namespace85 -- make sure LRE's // namespace is asserted even if default, since xsl:element // may have changed the context. rhandler.startPrefixMapping(getPrefix(), getNamespace()); // Add namespace declarations. executeNSDecls(transformer); rhandler.startElement(getNamespace(), getLocalName(), getRawName()); } catch (SAXException se) { throw new TransformerException(se); } /* * If we make it to here we have done a successful startElement() * we will do an endElement() call for balance, no matter what happens * in the middle. */ // tException remembers if we had an exception "in the middle" TransformerException tException = null; try { // Process any possible attributes from xsl:use-attribute-sets first super.execute(transformer); // xsl:version, excludeResultPrefixes??? // Process the list of avts next if (null != m_avts) { int nAttrs = m_avts.size(); for (int i = (nAttrs - 1); i >= 0; i--) { AVT avt = (AVT) m_avts.get(i); XPathContext xctxt = transformer.getXPathContext(); int sourceNode = xctxt.getCurrentNode(); String stringedValue = avt.evaluate(xctxt, sourceNode, this); if (null != stringedValue) { // Important Note: I'm not going to check for excluded namespace // prefixes here. It seems like it's too expensive, and I'm not // even sure this is right. But I could be wrong, so this needs // to be tested against other implementations. rhandler.addAttribute( avt.getURI(), avt.getName(), avt.getRawName(), "CDATA", stringedValue, false); } } // end for } // Now process all the elements in this subtree // TODO: Process m_extensionElementPrefixes && m_attributeSetsNames transformer.executeChildTemplates(this, true); } catch (TransformerException te) { // thrown in finally to prevent original exception consumed by subsequent exceptions tException = te; } catch (SAXException se) { tException = new TransformerException(se); } try { /* we need to do this endElement() to balance the * successful startElement() call even if * there was an exception in the middle. * Otherwise an exception in the middle could cause a system to hang. */ rhandler.endElement(getNamespace(), getLocalName(), getRawName()); } catch (SAXException se) { /* we did call endElement(). If thee was an exception * in the middle throw that one, otherwise if there * was an exception from endElement() throw that one. */ if (tException != null) throw tException; else throw new TransformerException(se); } /* If an exception was thrown in the middle but not with startElement() or * or endElement() then its time to let it percolate. */ if (tException != null) throw tException; unexecuteNSDecls(transformer); // JJK Bugzilla 3464, test namespace85 -- balance explicit start. try { rhandler.endPrefixMapping(getPrefix()); } catch (SAXException se) { throw new TransformerException(se); } }