List of usage examples for org.dom4j Element getData
Object getData();
From source file:org.orbeon.oxf.transformer.xupdate.TemplatesHandlerImpl.java
License:Open Source License
private Statement[] parseStatements(List nodes) { List statements = new ArrayList(); for (Iterator i = nodes.iterator(); i.hasNext();) { Node node = (Node) i.next(); if (node.getNodeType() == Node.TEXT_NODE) { if (!"".equals(node.getText().trim())) statements.add(new Text(node.getText().trim())); } else if (node.getNodeType() == Node.ELEMENT_NODE) { Element element = (Element) node; NamespaceContext namespaceContext = new SimpleNamespaceContext( Dom4jUtils.getNamespaceContext(element)); if (XUpdateConstants.XUPDATE_NAMESPACE_URI.equals(element.getNamespaceURI())) { if (element.getName().equals("remove")) { statements.add(new Remove((LocationData) element.getData(), element.attributeValue("select"), namespaceContext)); } else if (element.getName().equals("update")) { statements//from w w w . java 2s. c om .add(new Update((LocationData) element.getData(), element.attributeValue("select"), namespaceContext, parseStatements(element.content()))); } else if (element.getName().equals("append")) { statements.add(new Append((LocationData) element.getData(), element.attributeValue("select"), namespaceContext, element.attributeValue("child"), parseStatements(element.content()))); } else if (element.getName().equals("insert-before")) { statements.add( new InsertBefore((LocationData) element.getData(), element.attributeValue("select"), namespaceContext, parseStatements(element.content()))); } else if (element.getName().equals("insert-after")) { statements.add( new InsertAfter((LocationData) element.getData(), element.attributeValue("select"), namespaceContext, parseStatements(element.content()))); } else if (element.getName().equals("for-each")) { statements .add(new ForEach((LocationData) element.getData(), element.attributeValue("select"), namespaceContext, parseStatements(element.content()))); } else if (element.getName().equals("while")) { statements.add(new While((LocationData) element.getData(), element.attributeValue("select"), namespaceContext, parseStatements(element.content()))); } else if (element.getName().equals("value-of")) { statements.add(new ValueOf((LocationData) element.getData(), element.attributeValue("select"), namespaceContext)); } else if (element.getName().equals("copy-of")) { statements.add(new CopyOf((LocationData) element.getData(), element.attributeValue("select"), namespaceContext)); } else if (element.getName().equals("node-set")) { statements.add(new NodeSet((LocationData) element.getData(), element.attributeValue("select"), namespaceContext)); } else if (element.getName().equals("attribute")) { statements.add(new Attribute((LocationData) element.getData(), parseQName(element), parseStatements(element.content()))); } else if (element.getName().equals("namespace")) { statements.add(new Namespace((LocationData) element.getData(), element.attributeValue("name"), element.attributeValue("select"), namespaceContext, parseStatements(element.content()))); } else if (element.getName().equals("element")) { statements.add(new DynamicElement((LocationData) element.getData(), parseQName(element), parseStatements(element.content()))); } else if (element.getName().equals("if")) { statements.add(new If((LocationData) element.getData(), element.attributeValue("test"), namespaceContext, parseStatements(element.content()))); } else if (element.getName().equals("choose")) { List whenTests = new ArrayList(); List whenNamespaceContext = new ArrayList(); List whenStatements = new ArrayList(); for (Iterator j = element.elements("when").iterator(); j.hasNext();) { Element whenElement = (Element) j.next(); whenTests.add(whenElement.attributeValue("test")); whenNamespaceContext .add(new SimpleNamespaceContext(Dom4jUtils.getNamespaceContext(whenElement))); whenStatements.add(parseStatements(whenElement.content())); } Element otherwiseElement = element.element("otherwise"); statements.add(new Choose((LocationData) element.getData(), (String[]) whenTests.toArray(new String[whenTests.size()]), (NamespaceContext[]) whenNamespaceContext .toArray(new NamespaceContext[whenNamespaceContext.size()]), (Statement[][]) whenStatements.toArray(new Statement[whenStatements.size()][]), otherwiseElement == null ? null : parseStatements(otherwiseElement.content()))); } else if (element.getName().equals("variable")) { statements.add(new Variable((LocationData) element.getData(), parseQName(element), element.attributeValue("select"), namespaceContext, parseStatements(element.content()))); } else if (element.getName().equals("assign")) { statements.add(new Assign((LocationData) element.getData(), parseQName(element), element.attributeValue("select"), namespaceContext, parseStatements(element.content()))); } else if (element.getName().equals("function")) { statements.add(new Function((LocationData) element.getData(), parseQName(element), parseStatements(element.content()))); } else if (element.getName().equals("param")) { statements.add(new Param((LocationData) element.getData(), parseQName(element), element.attributeValue("select"), namespaceContext, parseStatements(element.content()))); } else if (element.getName().equals("message")) { statements.add( new Message((LocationData) element.getData(), parseStatements(element.content()))); } else if (element.getName().equals("error")) { statements.add( new Error((LocationData) element.getData(), parseStatements(element.content()))); } else { throw new ValidationException( "Unsupported XUpdate element '" + element.getQualifiedName() + "'", (LocationData) element.getData()); } } else { Element staticElement = new NonLazyUserDataElement(element.getQName()); List childNodes = new ArrayList(); for (Iterator j = element.attributes().iterator(); j.hasNext();) staticElement.add((org.dom4j.Attribute) ((org.dom4j.Attribute) j.next()).clone()); for (Iterator j = element.content().iterator(); j.hasNext();) { Node child = (Node) j.next(); if (child instanceof org.dom4j.Namespace) { staticElement.add((Node) child.clone()); } else { childNodes.add(child); } } statements.add(new StaticElement((LocationData) element.getData(), staticElement, parseStatements(childNodes))); } } else if (node.getNodeType() == Node.NAMESPACE_NODE) { // Ignore namespace declarations } else { throw new OXFException("Unsupported node: " + node.getNodeTypeName()); } } return (Statement[]) statements.toArray(new Statement[statements.size()]); }
From source file:org.orbeon.oxf.transformer.xupdate.TemplatesHandlerImpl.java
License:Open Source License
/** * Parse a name / namespace attributes of <xu:element> and * <xu:attribute>/* w w w .j a v a2 s .c om*/ */ private QName parseQName(Element element) { String name = element.attributeValue("name"); String namespace = element.attributeValue("namespace"); int columnPosition = name.indexOf(':'); // Check syntax of qname if (columnPosition == 0 || columnPosition == name.length() - 1) throw new ValidationException("Invalid qname '" + name + "'", (LocationData) element.getData()); if (columnPosition == -1 && namespace == null) { // Simple name return new QName(name); } else if (columnPosition != -1 && namespace == null) { // Qualified name using namespace declaration in context String prefix = name.substring(0, columnPosition); String namespaceFromContext = (String) Dom4jUtils.getNamespaceContext(element).get(prefix); if (namespaceFromContext == null) throw new ValidationException("No namespace declared for prefix '" + prefix + "'", (LocationData) element.getData()); return new QName(name.substring(columnPosition + 1), new org.dom4j.Namespace(prefix, namespaceFromContext)); } else if (columnPosition == -1 && namespace != null) { // Non-qualified name with namespace declaration return new QName(name, new org.dom4j.Namespace("", namespace)); } else if (columnPosition != -1 && namespace != null) { // Qualified name using namespace specified return new QName(name.substring(columnPosition + 1), new org.dom4j.Namespace(name.substring(0, columnPosition), namespace)); } else { // This can't happen throw new OXFException("Invalid state"); } }
From source file:org.orbeon.oxf.xforms.action.actions.XFormsRefreshAction.java
License:Open Source License
public void execute(XFormsActionInterpreter actionInterpreter, Element actionElement, Scope actionScope, boolean hasOverriddenContext, Item overriddenContext) { final XFormsContainingDocument containingDocument = actionInterpreter.containingDocument(); final String modelId = actionElement.attributeValue(XFormsConstants.MODEL_QNAME); final XFormsModel model = actionInterpreter.resolveModel(actionElement, modelId); if (model == null) throw new ValidationException("Invalid model id: " + modelId, (LocationData) actionElement.getData()); // NOTE: We no longer need to force the refresh flag here because the refresh flag is global. If a change in any // model occurred, then the flag will be already set and we are safe. Otherwise, it is safe not to do anything. Dispatch.dispatchEvent(new XFormsRefreshEvent(containingDocument, model)); }
From source file:org.orbeon.oxf.xforms.action.XFormsActionInterpreter.java
License:Open Source License
/** * Execute an XForms action.//from w w w . j a v a 2 s. c o m */ public void runAction(ElementAnalysis actionAnalysis) { final Element actionElement = actionAnalysis.element(); final ActionTrait actionTrait = (ActionTrait) actionAnalysis; try { // Condition final String ifConditionAttribute = actionTrait.ifConditionJava(); final String whileIterationAttribute = actionTrait.whileConditionJava(); final String iterateIterationAttribute = actionTrait.iterateJava(); // Push @iterate (if present) within the @model and @context context final NamespaceMapping namespaceMapping = actionAnalysis.namespaceMapping(); // TODO: function context _actionXPathContext.pushBinding(iterateIterationAttribute, actionAnalysis.contextJava(), null, actionAnalysis.modelJava(), null, actionElement, namespaceMapping, getSourceEffectiveId(actionElement), actionAnalysis.scope(), false); // NOTE: At this point, the context has already been set to the current action element if (iterateIterationAttribute != null) { // Gotta iterate // NOTE: It's not 100% how @context and @iterate should interact here. Right now @iterate overrides @context, // i.e. @context is evaluated first, and @iterate sets a new context for each iteration { final List<Item> currentNodeset = _actionXPathContext.getCurrentNodeset(); final int iterationCount = currentNodeset.size(); for (int index = 1; index <= iterationCount; index++) { // Push iteration _actionXPathContext.pushIteration(index); final Item overriddenContextNodeInfo = currentNodeset.get(index - 1); runSingleIteration(actionAnalysis, actionElement.getQName(), ifConditionAttribute, whileIterationAttribute, true, overriddenContextNodeInfo); // Restore context _actionXPathContext.popBinding(); } } } else { // Do a single iteration run (but this may repeat over the @while condition!) runSingleIteration(actionAnalysis, actionElement.getQName(), ifConditionAttribute, whileIterationAttribute, _actionXPathContext.hasOverriddenContext(), _actionXPathContext.getContextItem()); } // Restore _actionXPathContext.popBinding(); } catch (Exception e) { throw OrbeonLocationException.wrapException(e, new ExtendedLocationData((LocationData) actionElement.getData(), "running XForms action", actionElement, new String[] { "action name", actionElement.getQName().getQualifiedName() })); } }
From source file:org.orbeon.oxf.xforms.action.XFormsActionInterpreter.java
License:Open Source License
/** * Evaluate an expression as a string. This returns "" if the result is an empty sequence. *//*from w ww .ja v a 2 s .c o m*/ public String evaluateAsString(Element actionElement, List<Item> nodeset, int position, String xpathExpression) { // Setup function context final XFormsFunction.Context functionContext = _actionXPathContext .getFunctionContext(getSourceEffectiveId(actionElement)); // @ref points to something final String result = XPathCache.evaluateAsString(nodeset, position, xpathExpression, getNamespaceMappings(actionElement), _actionXPathContext.getCurrentVariables(), XFormsContainingDocument.getFunctionLibrary(), functionContext, null, (LocationData) actionElement.getData(), containingDocument().getRequestStats().getReporter()); // Restore function context _actionXPathContext.returnFunctionContext(); return result != null ? result : ""; }
From source file:org.orbeon.oxf.xforms.action.XFormsActionInterpreter.java
License:Open Source License
public List<Item> evaluateKeepItems(Element actionElement, List<Item> nodeset, int position, String xpathExpression) { // Setup function context final XFormsFunction.Context functionContext = _actionXPathContext .getFunctionContext(getSourceEffectiveId(actionElement)); // @ref points to something final List<Item> result = XPathCache.evaluateKeepItems(nodeset, position, xpathExpression, getNamespaceMappings(actionElement), _actionXPathContext.getCurrentVariables(), XFormsContainingDocument.getFunctionLibrary(), functionContext, null, (LocationData) actionElement.getData(), containingDocument().getRequestStats().getReporter()); // Restore function context _actionXPathContext.returnFunctionContext(); return result; }
From source file:org.orbeon.oxf.xforms.action.XFormsActionInterpreter.java
License:Open Source License
/** * Resolve a value which may be an AVT./*from w ww.j a va2 s .c om*/ * * @param actionElement action element * @param attributeValue raw value to resolve * @return resolved attribute value, null if the value is null or if the XPath context item is missing */ public String resolveAVTProvideValue(Element actionElement, String attributeValue) { if (attributeValue == null) return null; // Whether this can't be an AVT final String resolvedAVTValue; if (XFormsUtils.maybeAVT(attributeValue)) { // We have to go through AVT evaluation final BindingContext bindingContext = _actionXPathContext.getCurrentBindingContext(); // We don't have an evaluation context so return // CHECK: In the future we want to allow an empty evaluation context so do we really want this check? if (bindingContext.getSingleItem() == null) return null; final NamespaceMapping namespaceMapping = getNamespaceMappings(actionElement); final LocationData locationData = (LocationData) actionElement.getData(); // Setup function context final XFormsFunction.Context functionContext = _actionXPathContext .getFunctionContext(getSourceEffectiveId(actionElement)); resolvedAVTValue = XPathCache.evaluateAsAvt(bindingContext.getNodeset(), bindingContext.getPosition(), attributeValue, namespaceMapping, _actionXPathContext.getCurrentVariables(), XFormsContainingDocument.getFunctionLibrary(), functionContext, null, locationData, containingDocument().getRequestStats().getReporter()); // Restore function context _actionXPathContext.returnFunctionContext(); } else { // We optimize as this doesn't need AVT evaluation resolvedAVTValue = attributeValue; } return resolvedAVTValue; }
From source file:org.orbeon.oxf.xforms.action.XFormsActionInterpreter.java
License:Open Source License
/** * Search a model given a static id and/or the current action element. * * @param actionElement current action element * @param modelStaticId static id of the model searched, or null if current model * @return model//ww w .j a v a2 s. c o m */ public XFormsModel resolveModel(Element actionElement, String modelStaticId) { final XFormsModel model; if (modelStaticId != null) { // Id is specified, resolve the effective object final XFormsObject o = resolveObject(actionElement, modelStaticId); if (!(o instanceof XFormsModel)) throw new ValidationException("Invalid model id: " + modelStaticId, (LocationData) actionElement.getData()); model = (XFormsModel) o; } else { // Id is not specified model = _actionXPathContext.getCurrentModel(); } if (model == null) throw new ValidationException("Invalid model id: " + modelStaticId, (LocationData) actionElement.getData()); return model; }
From source file:org.orbeon.oxf.xforms.InstanceData.java
License:Open Source License
private static InstanceData createNewInstanceData(Node node) { final InstanceData instanceData; if (node instanceof Element) { final Element element = (Element) node; instanceData = InstanceData.createNewInstanceData(element.getData()); element.setData(instanceData);/*w w w . j a va2 s . c o m*/ } else if (node instanceof Attribute) { final Attribute attribute = (Attribute) node; instanceData = InstanceData.createNewInstanceData(attribute.getData()); attribute.setData(instanceData); } else if (node instanceof Document) { // We can't store data on the Document object. Use root element instead. final Element element = ((Document) node).getRootElement(); instanceData = InstanceData.createNewInstanceData(element.getData()); element.setData(instanceData); } else { // No other node type is supported throw new OXFException("Cannot create InstanceData on node type: " + node.getNodeTypeName()); } return instanceData; }
From source file:org.orbeon.oxf.xforms.itemset.XFormsItemUtils.java
License:Open Source License
/** * Evaluate the itemset for a given xf:select or xf:select1 control. * * @param select1Control control to evaluate * @return Itemset//from w w w .j a v a 2 s .com */ public static Itemset evaluateItemset(final XFormsSelect1Control select1Control) { final SelectionControlTrait staticControl = (SelectionControlTrait) select1Control.staticControl(); // Optimize static itemsets if (staticControl.hasStaticItemset()) return staticControl.staticItemset().get(); final boolean isMultiple = staticControl.isMultiple(); final XBLContainer container = select1Control.container(); final Itemset result = new Itemset(isMultiple); // Set binding on this control, after saving the current context because the context stack must // remain unmodified. final XFormsContextStack contextStack = container.getContextStack(); final BindingContext savedBindingContext = contextStack.getCurrentBindingContext(); contextStack.setBinding(select1Control.bindingContext()); // TODO: This visits all of the control's descendants. It should only visit the top-level item|itemset|choices elements. final boolean isEncryptItemValues = select1Control.isEncryptValues(); Dom4jUtils.visitSubtree(select1Control.element(), new Dom4jUtils.VisitorListener() { private int position = 0; private ItemContainer currentContainer = result; private String getElementEffectiveId(Element element) { return XFormsUtils.getRelatedEffectiveId(select1Control.getEffectiveId(), XFormsUtils.getElementId(element)); } public void startElement(Element element) { final String localname = element.getName(); if (XFormsConstants.XFORMS_ITEM_QNAME.getName().equals(localname)) { // xf:item contextStack.pushBinding(element, getElementEffectiveId(element), select1Control.getChildElementScope(element)); final Label label = getLabelValue(element.element(XFormsConstants.LABEL_QNAME)); final String value = getValueValue(element.element(XFormsConstants.XFORMS_VALUE_QNAME)); final Map<QName, String> attributes = getAttributes(element); currentContainer.addChildItem(Item.apply(position++, isMultiple, isEncryptItemValues, attributes, label, StringUtils.defaultString(value))); } else if (XFormsConstants.XFORMS_ITEMSET_QNAME.getName().equals(localname)) { // xf:itemset contextStack.pushBinding(element, getElementEffectiveId(element), select1Control.getChildElementScope(element)); final BindingContext currentBindingContext = contextStack.getCurrentBindingContext(); //if (model == null || model == currentBindingContext.getModel()) { // it is possible to filter on a particular model final List<org.orbeon.saxon.om.Item> currentNodeSet = currentBindingContext.getNodeset(); if (currentNodeSet != null) { // Node stack tracks the relative position of the current node wrt ancestor nodes final Stack<org.orbeon.saxon.om.Item> nodeStack = new Stack<org.orbeon.saxon.om.Item>(); int currentLevel = 0; final int iterationCount = currentNodeSet.size(); for (int currentPosition = 1; currentPosition <= iterationCount; currentPosition++) { // Push iteration contextStack.pushIteration(currentPosition); { final org.orbeon.saxon.om.Item currentNodeInfo = currentNodeSet .get(currentPosition - 1); // Handle children of xf:itemset // We support relevance of items as an extension to XForms // NOTE: If a node is non-relevant, all its descendants will be non-relevant as // well. If a node is non-relevant, it should be as if it had not even been part of // the nodeset. final boolean isRelevant = (!(currentNodeInfo instanceof NodeInfo)) || InstanceData.getInheritedRelevant((NodeInfo) currentNodeInfo); if (isRelevant) { final Label label = getLabelValue(element.element(XFormsConstants.LABEL_QNAME)); final Element valueCopyElement; { final Element valueElement = element .element(XFormsConstants.XFORMS_VALUE_QNAME); valueCopyElement = (valueElement != null) ? valueElement : element.element(XFormsConstants.XFORMS_COPY_QNAME); } if (valueCopyElement == null) throw new ValidationException( "xf:itemset element must contain one xf:value or one xf:copy element.", select1Control.getLocationData()); // Update stack and containers if (nodeStack.size() != 0) { final int newLevel = getItemLevel(currentNodeInfo, nodeStack); if (newLevel == currentLevel) { // We are staying at the same level, pop old item nodeStack.pop(); } else if (newLevel < currentLevel) { // We are going down one or more levels nodeStack.pop(); for (int i = newLevel; i < currentLevel; i++) { nodeStack.pop(); currentContainer = currentContainer.parent(); } } else if (newLevel > currentLevel) { // Going up one level, set new container as last added child currentContainer = currentContainer.lastChild(); } currentLevel = newLevel; } // Handle new item if (valueCopyElement.getName() .equals(XFormsConstants.XFORMS_VALUE_QNAME.getName())) { // Handle xf:value // TODO: This could be optimized for xf:value/@ref|@value as we could get the expression from the cache only once final String value = getValueValue(valueCopyElement); // NOTE: At this point, if the value is null, we should consider the item // non-relevant if it is a leaf item. But we don't yet know if this item is // a leaf item, so we prune such non-relevant items later. final Map<QName, String> attributes = getAttributes(element); currentContainer.addChildItem(Item.apply(position++, isMultiple, isEncryptItemValues, attributes, label, value)); } else { // TODO: handle xf:copy throw new ValidationException("xf:copy is not yet supported.", select1Control.getLocationData()); } // Always push the last item to the stack nodeStack.push(currentNodeInfo); } } contextStack.popBinding(); } } } else if (XFormsConstants.XFORMS_CHOICES_QNAME.getName().equals(localname)) { // xf:choices contextStack.pushBinding(element, getElementEffectiveId(element), select1Control.getChildElementScope(element)); final Element labelElement = element.element(XFormsConstants.LABEL_QNAME); if (labelElement != null) { final Label label = getLabelValue(labelElement); // NOTE: returned label can be null in some cases final Map<QName, String> attributes = getAttributes(element); final Item newContainer = Item.apply(position++, isMultiple, isEncryptItemValues, attributes, label, null); currentContainer.addChildItem(newContainer); currentContainer = newContainer; } } } public void endElement(Element element) { final String localname = element.getName(); if (XFormsConstants.XFORMS_ITEM_QNAME.getName().equals(localname)) { contextStack.popBinding(); } else if (XFormsConstants.XFORMS_ITEMSET_QNAME.getName().equals(localname)) { contextStack.popBinding(); } else if (XFormsConstants.XFORMS_CHOICES_QNAME.getName().equals(localname)) { contextStack.popBinding(); final Element labelElement = element.element(XFormsConstants.LABEL_QNAME); if (labelElement != null) { currentContainer = currentContainer.parent(); } } } private String getValueValue(Element valueElement) { if (valueElement == null) throw new ValidationException("xf:item or xf:itemset must contain an xf:value element.", select1Control.getLocationData()); final Scope elementScope = select1Control.getChildElementScope(valueElement); final String elementEffectiveId = getElementEffectiveId(valueElement); return XFormsUtils.getChildElementValue(container, elementEffectiveId, elementScope, valueElement, false, false, null); } private Label getLabelValue(Element labelElement) { if (labelElement == null) throw new ValidationException("xf:item or xf:itemset must contain an xf:label element.", select1Control.getLocationData()); final Scope elementScope = select1Control.getChildElementScope(labelElement); final String elementEffectiveId = getElementEffectiveId(labelElement); final boolean supportsHTML = select1Control.isFullAppearance(); // Only support HTML when appearance is "full" final boolean[] containsHTML = new boolean[] { false }; // FIXME: Would be good to do this check statically final boolean defaultToHTML = LHHAAnalysis.isHTML(labelElement); final String label = XFormsUtils.getChildElementValue(container, elementEffectiveId, elementScope, labelElement, supportsHTML, defaultToHTML, containsHTML); return new Label(StringUtils.defaultString(label), containsHTML[0]); } private Map<QName, String> getAttributes(Element itemChoiceItemsetElement) { final String elementEffectiveId = getElementEffectiveId(itemChoiceItemsetElement); final Map<QName, String> result = new LinkedHashMap<QName, String>(); for (QName attributeName : ATTRIBUTES_TO_PROPAGATE) { final String attributeValue = itemChoiceItemsetElement.attributeValue(attributeName); if (attributeValue != null) addAttributeAVTValue(itemChoiceItemsetElement, attributeName, attributeValue, elementEffectiveId, result); } return result; } private void addAttributeAVTValue(Element itemChoiceItemsetElement, QName attributeName, String attributeValue, String elementEffectiveId, Map<QName, String> result) { if (!XFormsUtils.maybeAVT(attributeValue)) { // Definitely not an AVT result.put(attributeName, attributeValue); } else { // Possible AVT final BindingContext currentBindingContext = contextStack.getCurrentBindingContext(); final List<org.orbeon.saxon.om.Item> currentNodeset = currentBindingContext.getNodeset(); if (currentNodeset != null && currentNodeset.size() > 0) { String tempResult; try { tempResult = XPathCache.evaluateAsAvt(currentNodeset, currentBindingContext.getPosition(), attributeValue, container.getNamespaceMappings(itemChoiceItemsetElement), contextStack.getCurrentVariables(), XFormsContainingDocument.getFunctionLibrary(), contextStack.getFunctionContext(elementEffectiveId), null, (LocationData) itemChoiceItemsetElement.getData(), container.getContainingDocument().getRequestStats().getReporter()); } catch (Exception e) { XFormsError.handleNonFatalXPathError(container, e); tempResult = ""; } finally { contextStack.returnFunctionContext(); } result.put(attributeName, tempResult); } } } public void text(Text text) { } /** * Return the item level for the given item. If the stack is empty, the level is 0. * * @param item item to check * @param stack stack of potential ancestors * @return node level */ private int getItemLevel(org.orbeon.saxon.om.Item item, Stack<org.orbeon.saxon.om.Item> stack) { // Iterate stack from top to bottom if (item instanceof NodeInfo) { int level = stack.size(); // Only nodes can have ancestor relationship final NodeInfo nodeInfo = (NodeInfo) item; // Reverse order Collections.reverse(stack); for (Iterator<org.orbeon.saxon.om.Item> i = stack.iterator(); i.hasNext(); level--) { final org.orbeon.saxon.om.Item currentItem = i.next(); if (currentItem instanceof NodeInfo) { // Only nodes can have ancestor relationship final NodeInfo currentNode = (NodeInfo) currentItem; if (isAncestorNode(nodeInfo, currentNode)) { // Restore order Collections.reverse(stack); return level; } } } // Restore order Collections.reverse(stack); return level; } else { // If it's not a node, stay at current level return stack.size() - 1; } } /** * Whether the given node has potentialAncestor as ancestor. * * @param node node to check * @param potentialAncestor potential ancestor * @return true iif potentialAncestor is an ancestor of node */ private boolean isAncestorNode(NodeInfo node, NodeInfo potentialAncestor) { NodeInfo parent = node.getParent(); while (parent != null) { if (parent.isSameNodeInfo(potentialAncestor)) return true; parent = parent.getParent(); } return false; } }); // Make sure to restore the stack contextStack.setBinding(savedBindingContext); // Prune non-relevant children result.pruneNonRelevantChildren(); return result; }