Example usage for org.dom4j Node ATTRIBUTE_NODE

List of usage examples for org.dom4j Node ATTRIBUTE_NODE

Introduction

In this page you can find the example usage for org.dom4j Node ATTRIBUTE_NODE.

Prototype

short ATTRIBUTE_NODE

To view the source code for org.dom4j Node ATTRIBUTE_NODE.

Click Source Link

Document

Matches elements nodes

Usage

From source file:org.jasig.portal.io.xml.SpELDataTemplatingStrategy.java

License:Apache License

@Override
public Source processTemplates(Document data, String filename) {

    log.trace("Processing templates for document XML={}", data.asXML());
    for (String xpath : XPATH_EXPRESSIONS) {
        @SuppressWarnings("unchecked")
        List<Node> nodes = data.selectNodes(xpath);
        for (Node n : nodes) {
            String inpt, otpt;/*  ww w. ja  v  a2  s.  c o m*/
            switch (n.getNodeType()) {
            case org.w3c.dom.Node.ATTRIBUTE_NODE:
                Attribute a = (Attribute) n;
                inpt = a.getValue();
                otpt = processText(inpt);
                if (otpt == null) {
                    throw new RuntimeException("Invalid expression '" + inpt + "' in file " + filename);
                }
                if (!otpt.equals(inpt)) {
                    a.setValue(otpt);
                }
                break;
            case org.w3c.dom.Node.TEXT_NODE:
            case org.w3c.dom.Node.CDATA_SECTION_NODE:
                inpt = n.getText();
                otpt = processText(inpt);
                if (otpt == null) {
                    throw new RuntimeException("Invalid expression '" + inpt + "' in file " + filename);
                }
                if (!otpt.equals(inpt)) {
                    n.setText(otpt);
                }
                break;
            default:
                String msg = "Unsupported node type:  " + n.getNodeTypeName();
                throw new RuntimeException(msg);
            }
        }
    }

    final SAXSource rslt = new DocumentSource(data);
    rslt.setSystemId(filename); // must be set, else import chokes
    return rslt;

}

From source file:org.jasig.portal.tenants.TemplateDataTenantOperationsListener.java

License:Apache License

@Override
public void onCreate(final ITenant tenant) {

    final StandardEvaluationContext ctx = new StandardEvaluationContext();
    ctx.setRootObject(new RootObjectImpl(tenant));

    /*/*ww  w  .j a  v a 2  s .c o m*/
     * First load dom4j Documents and sort the entity files into the proper order 
     */
    final Map<PortalDataKey, Set<Document>> importQueue = new HashMap<PortalDataKey, Set<Document>>();
    Resource rsc = null;
    try {
        for (Resource r : templateResources) {
            rsc = r;
            if (log.isDebugEnabled()) {
                log.debug("Loading template resource file for tenant " + "'" + tenant.getFname() + "':  "
                        + rsc.getFilename());
            }
            final Document doc = reader.read(rsc.getInputStream());
            final QName qname = doc.getRootElement().getQName();
            PortalDataKey atLeastOneMatchingDataKey = null;
            for (PortalDataKey pdk : dataKeyImportOrder) {
                // Matching is tougher because it's dom4j <> w3c...
                boolean matches = qname.getName().equals(pdk.getName().getLocalPart())
                        && qname.getNamespaceURI().equals(pdk.getName().getNamespaceURI());
                if (matches) {
                    // Found the right bucket...
                    atLeastOneMatchingDataKey = pdk;
                    Set<Document> bucket = importQueue.get(atLeastOneMatchingDataKey);
                    if (bucket == null) {
                        // First of these we've seen;  create the bucket;
                        bucket = new HashSet<Document>();
                        importQueue.put(atLeastOneMatchingDataKey, bucket);
                    }
                    bucket.add(doc);
                    /*
                     * At this point, we would normally add a break;
                     * statement, but group_membership.xml files need to
                     * match more than one PortalDataKey.
                     */
                }
            }
            if (atLeastOneMatchingDataKey == null) {
                // We can't proceed
                throw new RuntimeException(
                        "No PortalDataKey found for QName:  " + doc.getRootElement().getQName());
            }
        }
    } catch (Exception e) {
        throw new RuntimeException(
                "Failed to process the specified template:  " + (rsc != null ? rsc.getFilename() : ""), e);
    }

    log.trace("Ready to import data entity templates for new tenant '{}';  importQueue={}", tenant.getName(),
            importQueue);

    /*
     * Now import the identified entities each bucket in turn 
     */
    Document doc = null;
    org.w3c.dom.Document w3c = null;
    try {
        for (PortalDataKey pdk : dataKeyImportOrder) {
            Set<Document> bucket = importQueue.get(pdk);
            if (bucket != null) {
                log.debug("Importing the specified PortalDataKey tenant '{}':  {}", tenant.getName(),
                        pdk.getName());
                for (Document d : bucket) {
                    doc = d;
                    log.trace("Importing document XML={}", doc.asXML());
                    for (String xpath : XPATH_EXPRESSIONS) {
                        @SuppressWarnings("unchecked")
                        List<Node> nodes = doc.selectNodes(xpath);
                        for (Node n : nodes) {
                            String inpt, otpt;
                            switch (n.getNodeType()) {
                            case org.w3c.dom.Node.ATTRIBUTE_NODE:
                                Attribute a = (Attribute) n;
                                inpt = a.getValue();
                                otpt = processText(inpt, ctx);
                                if (!otpt.equals(inpt)) {
                                    a.setValue(otpt);
                                }
                                break;
                            case org.w3c.dom.Node.TEXT_NODE:
                                Text t = (Text) n;
                                inpt = t.getText();
                                otpt = processText(inpt, ctx);
                                if (!otpt.equals(inpt)) {
                                    t.setText(otpt);
                                }
                                break;
                            default:
                                String msg = "Unsupported node type:  " + n.getNodeTypeName();
                                throw new RuntimeException(msg);
                            }
                        }
                    }
                    w3c = writer.write(doc, domImpl);
                    Source source = new DOMSource(w3c);
                    source.setSystemId(rsc.getFilename()); // must be set, else import chokes
                    dataHandlerService.importData(source, pdk);
                }
            }
        }

    } catch (Exception e) {
        log.warn("w3c DOM=" + this.nodeToString(w3c));
        throw new RuntimeException(
                "Failed to process the specified template document:  " + (doc != null ? doc.asXML() : ""), e);
    }

}

From source file:org.openadaptor.auxil.convertor.map.Dom4JDocumentMapFacade.java

License:Open Source License

/** 
 * Extract value from a single node/*from ww  w. j a  v a2s.c o  m*/
 * <br>
 * <UL>
 *  <LI>If an Element return the element reference.
 *  <LI>If an Attribute return the attribute value
 *  <LI>If text (or CDATA) return it.
 *  <LI>If null return null.
 * @param node Node from which to extract a value
 * @return Reference to Element, or String representation of value.
 */
private Object getSingleValuedResult(Node node) {
    Object result = null;
    switch (node.getNodeType()) {
    case Node.ELEMENT_NODE:
        result = (Element) node;
        break;
    case Node.ATTRIBUTE_NODE:
        result = ((Attribute) node).getValue();
        break;
    case Node.TEXT_NODE:
    case Node.CDATA_SECTION_NODE: //Not sure about this one!
        result = node.getText();
        break;
    }
    return result;
}

From source file:org.orbeon.oxf.processor.pipeline.ast.ASTNodeContainer.java

License:Open Source License

/**
 * Use specified location if there is one.  Otherwise if a node has been provided use the
 * location of the node.  If no node and no location then return hull.
 *//*from  w ww. j  a v a2s .c  o m*/
public LocationData getLocationData() {
    final LocationData ret;
    if (locationData != null) {
        ret = locationData;
    } else if (node == null) {
        ret = null;
    } else if (node.getNodeType() == org.dom4j.Node.ELEMENT_NODE) {
        ret = (LocationData) ((org.dom4j.Element) node).getData();
    } else if (node.getNodeType() == org.dom4j.Node.ATTRIBUTE_NODE) {
        ret = (LocationData) ((org.dom4j.Attribute) node).getData();
    } else {
        ret = null;
    }
    return ret;
}

From source file:org.orbeon.oxf.xforms.action.actions.XFormsInsertAction.java

License:Open Source License

public static List<NodeInfo> doInsert(XFormsContainingDocument containingDocument,
        IndentedLogger indentedLogger, String positionAttribute, List collectionToBeUpdated,
        NodeInfo insertContextNodeInfo, List<Item> originItems, int insertionIndex, boolean doClone,
        boolean doDispatch) {

    final boolean isEmptyNodesetBinding = collectionToBeUpdated == null || collectionToBeUpdated.size() == 0;

    // "3. The origin node-set is determined."
    // "5. Each node in the origin node-set is cloned in the order it appears in the origin node-set."
    final List<Node> sourceNodes;
    final List<Node> clonedNodes;
    {/*from   ww w .  j a v  a  2  s.  c om*/
        final List<Node> clonedNodesTemp;
        if (originItems == null) {
            // There are no explicitly specified origin objects, use node from Node Set Binding node-set

            // "If the origin attribute is not given and the Node Set Binding node-set is empty, then the origin
            // node-set is the empty node-set. [...] The insert action is terminated with no effect if the
            // origin node-set is the empty node-set."

            if (isEmptyNodesetBinding) {
                if (indentedLogger != null && indentedLogger.isDebugEnabled())
                    indentedLogger.logDebug("xf:insert",
                            "origin node-set from node-set binding is empty, terminating");
                return Collections.EMPTY_LIST;
            }

            // "Otherwise, if the origin attribute is not given, then the origin node-set consists of the last
            // node of the Node Set Binding node-set."
            final Node singleSourceNode = XFormsUtils.getNodeFromNodeInfoConvert(
                    (NodeInfo) collectionToBeUpdated.get(collectionToBeUpdated.size() - 1));
            // TODO: check namespace handling might be incorrect. Should use copyElementCopyParentNamespaces() instead?
            final Node singleClonedNode = Dom4jUtils.createCopy(singleSourceNode);

            sourceNodes = Collections.singletonList(singleSourceNode);
            clonedNodesTemp = Collections.singletonList(singleClonedNode);
        } else {
            // There are explicitly specified origin objects

            // "The insert action is terminated with no effect if the origin node-set is the empty node-set."
            if (originItems.size() == 0) {
                if (indentedLogger != null && indentedLogger.isDebugEnabled())
                    indentedLogger.logDebug("xf:insert", "origin node-set is empty, terminating");
                return Collections.EMPTY_LIST;
            }

            // "Each node in the origin node-set is cloned in the order it appears in the origin node-set."

            sourceNodes = new ArrayList<Node>(originItems.size()); // set to max possible size
            clonedNodesTemp = new ArrayList<Node>(originItems.size());

            for (final Object currentObject : originItems) {
                if (currentObject instanceof NodeInfo) {
                    // This is the regular case covered by XForms 1.1 / XPath 1.0

                    // NOTE: Don't clone nodes if doClone == false
                    final Node sourceNode = XFormsUtils.getNodeFromNodeInfoConvert((NodeInfo) currentObject);
                    final Node clonedNode = doClone
                            ? (sourceNode instanceof Element) ? ((Element) sourceNode).createCopy()
                                    : (Node) sourceNode.clone()
                            : sourceNode;

                    sourceNodes.add(sourceNode);
                    clonedNodesTemp.add(clonedNode);

                } else if (currentObject instanceof AtomicValue) {
                    // This is an extension: support sequences containing atomic values

                    // Convert the result to a text node
                    final String stringValue = ((Item) currentObject).getStringValue();
                    final Text textNode = Dom4jUtils.createText(stringValue);

                    sourceNodes.add(null); // there is no source node for this cloned node, it's a source item
                    clonedNodesTemp.add(textNode);
                } else
                    throw new IllegalStateException();
            }
        }

        // Remove instance data from cloned nodes and perform Document node adjustment
        for (int i = 0; i < clonedNodesTemp.size(); i++) {
            final Node clonedNodeTemp = clonedNodesTemp.get(i);

            if (clonedNodeTemp instanceof Element) {
                // Element node
                InstanceData.remove(clonedNodeTemp);
                clonedNodeTemp.detach();
            } else if (clonedNodeTemp instanceof Attribute) {
                // Attribute node
                InstanceData.remove(clonedNodeTemp);
                clonedNodeTemp.detach();
            } else if (clonedNodeTemp instanceof Document) {
                // Document node
                final Element clonedNodeTempRootElement = clonedNodeTemp.getDocument().getRootElement();

                if (clonedNodeTempRootElement == null) {
                    // Can be null in rare cases of documents without root element
                    clonedNodesTemp.set(i, null); // we support having a null node further below, so set this to null
                } else {
                    InstanceData.remove(clonedNodeTempRootElement);
                    // We can never really insert a document into anything at this point, but we assume that this means the root element
                    clonedNodesTemp.set(i, clonedNodeTempRootElement.detach());
                }
            } else {
                // Other nodes
                clonedNodeTemp.detach();
            }
        }
        clonedNodes = clonedNodesTemp;
    }

    // "6. The target location of each cloned node or nodes is determined"
    // "7. The cloned node or nodes are inserted in the order they were cloned at their target location
    // depending on their node type."

    // Identify the instance that actually changes
    final XFormsInstance modifiedInstance;
    // Find actual insertion point and insert
    final NodeInfo insertLocationNodeInfo;
    final List<Node> insertedNodes;
    final String beforeAfterInto;
    if (isEmptyNodesetBinding) {
        // Insert INTO a node

        // "If the Node Set Binding node-set is not specified or empty, the insert location node is the insert
        // context node."

        // "a. If the Node Set Binding node-set is not specified or empty, the target location depends on the
        // node type of the cloned node. If the cloned node is an attribute, then the target location is before
        // the first attribute of the insert location node. If the cloned node is not an attribute, then the
        // target location is before the first child of the insert location node."

        modifiedInstance = (containingDocument != null)
                ? containingDocument.getInstanceForNode(insertContextNodeInfo)
                : null;
        insertLocationNodeInfo = insertContextNodeInfo;
        final Node insertLocationNode = XFormsUtils.getNodeFromNodeInfo(insertContextNodeInfo,
                CANNOT_INSERT_READONLY_MESSAGE);
        insertedNodes = doInsert(insertLocationNode, clonedNodes, modifiedInstance, doDispatch);
        beforeAfterInto = "into";

        // Normalize text nodes if needed to respect XPath 1.0 constraint
        {
            boolean hasTextNode = false;
            for (Node clonedNode : clonedNodes) {
                hasTextNode |= clonedNode != null && clonedNode.getNodeType() == Node.TEXT_NODE;
            }
            if (hasTextNode)
                Dom4jUtils.normalizeTextNodes(insertLocationNode);
        }
    } else {
        // Insert BEFORE or AFTER a node
        insertLocationNodeInfo = (NodeInfo) collectionToBeUpdated.get(insertionIndex - 1);
        final Node insertLocationNode = XFormsUtils.getNodeFromNodeInfo(insertLocationNodeInfo,
                CANNOT_INSERT_READONLY_MESSAGE);
        modifiedInstance = (containingDocument != null)
                ? containingDocument.getInstanceForNode(insertLocationNodeInfo)
                : null;

        final Document insertLocationNodeDocument = insertLocationNode.getDocument();
        if (insertLocationNodeDocument != null
                && insertLocationNodeDocument.getRootElement() == insertLocationNode) {

            // "c. if insert location node is the root element of an instance, then that instance root element
            // location is the target location. If there is more than one cloned node to insert, only the
            // first node that does not cause a conflict is considered."

            insertedNodes = doInsert(insertLocationNode.getDocument(), clonedNodes, modifiedInstance,
                    doDispatch);
            beforeAfterInto = positionAttribute; // TODO: ideally normalize to "into document node"?

            // NOTE: Don't need to normalize text nodes in this case, as no new text node is inserted
        } else {
            // "d. Otherwise, the target location is immediately before or after the insert location
            // node, based on the position attribute setting or its default."

            if (insertLocationNode.getNodeType() == Node.ATTRIBUTE_NODE) {
                // Special case for "next to an attribute"

                // NOTE: In XML, attributes are unordered. dom4j handles them as a list so has order, but
                // the XForms spec shouldn't rely on attribute order. We could try to keep the order, but it
                // is harder as we have to deal with removing duplicate attributes and find a reasonable
                // insertion strategy.

                // TODO: Don't think we should even do this now in XForms 1.1
                insertedNodes = doInsert(insertLocationNode.getParent(), clonedNodes, modifiedInstance,
                        doDispatch);

            } else {
                // Other node types
                final Element parentNode = insertLocationNode.getParent();
                final List<Node> siblingElements = Dom4jUtils.content(parentNode);
                final int actualIndex = siblingElements.indexOf(insertLocationNode);

                // Prepare insertion of new element
                final int actualInsertionIndex;
                if ("before".equals(positionAttribute)) {
                    actualInsertionIndex = actualIndex;
                } else {
                    // "after"
                    actualInsertionIndex = actualIndex + 1;
                }

                // "7. The cloned node or nodes are inserted in the order they were cloned at their target
                // location depending on their node type."

                boolean hasTextNode = false;
                int addIndex = 0;
                insertedNodes = new ArrayList<Node>(clonedNodes.size());
                for (Node clonedNode : clonedNodes) {

                    if (clonedNode != null) {// NOTE: we allow passing some null nodes so we check on null
                        if (!(clonedNode instanceof Attribute || clonedNode instanceof Namespace)) {
                            // Element, text, comment, processing instruction node
                            siblingElements.add(actualInsertionIndex + addIndex, clonedNode);
                            insertedNodes.add(clonedNode);
                            hasTextNode |= clonedNode.getNodeType() == Node.TEXT_NODE;
                            addIndex++;
                        } else {
                            // We never insert attributes or namespace nodes as siblings
                            if (indentedLogger != null && indentedLogger.isDebugEnabled())
                                indentedLogger.logDebug("xf:insert",
                                        "skipping insertion of node as sibling in element content", "type",
                                        clonedNode.getNodeTypeName(), "node",
                                        clonedNode instanceof Attribute
                                                ? Dom4jUtils.attributeToDebugString((Attribute) clonedNode)
                                                : clonedNode.toString());
                        }
                    }
                }

                // Normalize text nodes if needed to respect XPath 1.0 constraint
                if (hasTextNode)
                    Dom4jUtils.normalizeTextNodes(parentNode);
            }

            beforeAfterInto = positionAttribute;
        }
    }

    // Whether some nodes were inserted
    final boolean didInsertNodes = insertedNodes != null && insertedNodes.size() > 0;

    // Log stuff
    if (indentedLogger != null && indentedLogger.isDebugEnabled()) {
        if (didInsertNodes)
            indentedLogger.logDebug("xf:insert", "inserted nodes", "count",
                    Integer.toString(insertedNodes.size()), "instance",
                    (modifiedInstance != null) ? modifiedInstance.getEffectiveId() : null);
        else
            indentedLogger.logDebug("xf:insert", "no node inserted");
    }

    // "XForms Actions that change the tree structure of instance data result in setting all four flags to true"
    if (didInsertNodes && modifiedInstance != null) {
        // NOTE: Can be null if document into which delete is performed is not in an instance, e.g. in a variable
        modifiedInstance.markModified();
        modifiedInstance.model().markStructuralChange(modifiedInstance);
    }

    // Gather list of modified nodes
    final List<NodeInfo> insertedNodeInfos;
    if (didInsertNodes && modifiedInstance != null) {
        // Can be null if document into which delete is performed is not in an instance, e.g. in a variable
        final DocumentWrapper documentWrapper = (DocumentWrapper) modifiedInstance.documentInfo();
        insertedNodeInfos = new ArrayList<NodeInfo>(insertedNodes.size());
        for (Object insertedNode : insertedNodes)
            insertedNodeInfos.add(documentWrapper.wrap(insertedNode));
    } else {
        insertedNodeInfos = Collections.emptyList();
    }

    // "4. If the insert is successful, the event xforms-insert is dispatched."
    // XFormsInstance handles index and repeat items updates 
    if (doDispatch && didInsertNodes && modifiedInstance != null) {

        // Adjust insert location node and before/after/into in case the root element was replaced
        final NodeInfo adjustedInsertLocationNodeInfo;
        final String adjustedBeforeAfterInto;

        final NodeInfo parent = insertedNodeInfos.get(0).getNodeKind() == org.w3c.dom.Node.ELEMENT_NODE
                ? insertedNodeInfos.get(0).getParent()
                : null;
        if (parent != null && parent.equals(parent.getDocumentRoot())) {
            // Node was inserted under document node
            adjustedInsertLocationNodeInfo = parent.getDocumentRoot();
            adjustedBeforeAfterInto = "into";
        } else {
            adjustedInsertLocationNodeInfo = insertLocationNodeInfo;
            adjustedBeforeAfterInto = beforeAfterInto;
        }

        Dispatch.dispatchEvent(new XFormsInsertEvent(modifiedInstance, insertedNodeInfos, originItems,
                adjustedInsertLocationNodeInfo, adjustedBeforeAfterInto));
    }

    return insertedNodeInfos;
}

From source file:org.orbeon.oxf.xforms.xbl.XBLTransformer.java

License:Open Source License

/**
 * Apply an XBL transformation, i.e. apply xbl:content, xbl:attr, etc.
 *
 * NOTE: This mutates shadowTreeDocument.
 *///from   w ww  .j av  a  2 s  .  c  om
public static Document transform(final Document shadowTreeDocument, final Element boundElement,
        final boolean excludeNestedHandlers, final boolean excludeNestedLHHA) {

    final DocumentWrapper documentWrapper = new DocumentWrapper(boundElement.getDocument(), null,
            XPathCache.getGlobalConfiguration());

    Dom4jUtils.visitSubtree(shadowTreeDocument.getRootElement(), new Dom4jUtils.VisitorListener() {

        boolean isNestedHandler(Element e) {
            return e.getParent() == boundElement && EventHandlerImpl.isEventHandler(e);
        }

        boolean isNestedLHHA(Element e) {
            return e.getParent() == boundElement && LHHA.isLHHA(e);
        }

        boolean mustFilterOut(Element e) {
            return excludeNestedHandlers && isNestedHandler(e) || excludeNestedLHHA && isNestedLHHA(e);
        }

        public void startElement(Element element) {

            // Handle xbl:content

            final boolean isXBLContent = element.getQName().equals(XBL_CONTENT_QNAME);
            final List<Node> resultingNodes;
            if (isXBLContent) {
                final String includesAttribute = element.attributeValue(XFormsConstants.INCLUDES_QNAME);
                final String scopeAttribute = element.attributeValue(XFormsConstants.XXBL_SCOPE_QNAME);
                final List<Node> contentToInsert;
                if (includesAttribute == null) {
                    // All bound node content must be copied over (except nested handlers if requested)
                    final List<Node> elementContent = Dom4jUtils.content(boundElement);
                    final List<Node> clonedContent = new ArrayList<Node>();
                    for (final Node node : elementContent) {
                        if (node instanceof Element) {
                            final Element currentElement = (Element) node;
                            if (!mustFilterOut(currentElement))
                                clonedContent.add(Dom4jUtils.copyElementCopyParentNamespaces(currentElement));
                        } else if (!(node instanceof Namespace)) {
                            clonedContent.add(Dom4jUtils.createCopy(node));
                        }
                    }

                    contentToInsert = clonedContent;
                } else {
                    // Apply CSS selector

                    // Convert CSS to XPath
                    final String xpathExpression = CSSParser.toXPath(includesAttribute);

                    final NodeInfo boundElementInfo = documentWrapper.wrap(boundElement);

                    // TODO: don't use getNamespaceContext() as this is already computed for the bound element
                    final List<Object> elements = XPathCache.evaluate(boundElementInfo, xpathExpression,
                            new NamespaceMapping(Dom4jUtils.getNamespaceContext(element)), null, null, null,
                            null, null, null);// TODO: locationData

                    if (elements.size() > 0) {
                        // Clone all the resulting elements
                        contentToInsert = new ArrayList<Node>(elements.size());
                        for (Object o : elements) {
                            final NodeInfo currentNodeInfo = (NodeInfo) o;
                            final Element currentElement = (Element) ((VirtualNode) currentNodeInfo)
                                    .getUnderlyingNode();

                            if (!mustFilterOut(currentElement))
                                contentToInsert.add(Dom4jUtils.copyElementCopyParentNamespaces(currentElement));
                        }
                    } else {
                        // Clone all the element's children if any
                        // See: http://www.w3.org/TR/xbl/#the-content
                        contentToInsert = new ArrayList<Node>(element.nodeCount());
                        for (Object o : element.elements()) {
                            final Element currentElement = (Element) o;
                            if (!mustFilterOut(currentElement))
                                contentToInsert.add(Dom4jUtils.copyElementCopyParentNamespaces(currentElement));
                        }
                    }
                }

                // Insert content if any
                if (contentToInsert != null && contentToInsert.size() > 0) {
                    final List<Node> parentContent = Dom4jUtils.content(element.getParent());
                    final int elementIndex = parentContent.indexOf(element);
                    parentContent.addAll(elementIndex, contentToInsert);
                }

                // Remove <xbl:content> from shadow tree
                element.detach();

                resultingNodes = contentToInsert;

                if (!StringUtils.isBlank(scopeAttribute)) {
                    // If author specified scope attribute, use it
                    setAttribute(resultingNodes, XFormsConstants.XXBL_SCOPE_QNAME, scopeAttribute, null);
                } else {
                    // By default, set xxbl:scope="outer" on resulting elements
                    setAttribute(resultingNodes, XFormsConstants.XXBL_SCOPE_QNAME, "outer", null);
                }
            } else {
                // Element is simply kept
                resultingNodes = Collections.singletonList((Node) element);
            }

            // Handle attribute forwarding
            final Attribute xblAttr = element.attribute(XBL_ATTR_QNAME); // standard xbl:attr (custom syntax)
            final Attribute xxblAttr = element.attribute(XXBL_ATTR_QNAME); // extension xxbl:attr (XPath expression)
            if (xblAttr != null) {
                // Detach attribute (not strictly necessary?)
                xblAttr.detach();
                // Get attribute value
                final String xblAttrString = xblAttr.getValue();
                final StringTokenizer st = new StringTokenizer(xblAttrString);
                while (st.hasMoreTokens()) {
                    final String currentValue = st.nextToken();

                    final int equalIndex = currentValue.indexOf('=');
                    if (equalIndex == -1) {
                        // No a=b pair, just a single QName
                        final QName valueQName = Dom4jUtils.extractTextValueQName(element, currentValue, true);
                        if (!valueQName.getNamespaceURI().equals(XFormsConstants.XBL_NAMESPACE_URI)) {
                            // This is not xbl:text, copy the attribute
                            setAttribute(resultingNodes, valueQName, boundElement.attributeValue(valueQName),
                                    boundElement);
                        } else {
                            // This is xbl:text
                            // "The xbl:text value cannot occur by itself in the list"
                        }

                    } else {
                        // a=b pair
                        final QName leftSideQName;
                        {
                            final String leftSide = currentValue.substring(0, equalIndex);
                            leftSideQName = Dom4jUtils.extractTextValueQName(element, leftSide, true);
                        }
                        final QName rightSideQName;
                        {
                            final String rightSide = currentValue.substring(equalIndex + 1);
                            rightSideQName = Dom4jUtils.extractTextValueQName(element, rightSide, true);
                        }

                        final boolean isLeftSideXBLText = leftSideQName.getNamespaceURI()
                                .equals(XFormsConstants.XBL_NAMESPACE_URI);
                        final boolean isRightSideXBLText = rightSideQName.getNamespaceURI()
                                .equals(XFormsConstants.XBL_NAMESPACE_URI);

                        final String rightSideValue;
                        final Element namespaceElement;
                        if (!isRightSideXBLText) {
                            // Get attribute value
                            rightSideValue = boundElement.attributeValue(rightSideQName);
                            namespaceElement = boundElement;
                        } else {
                            // Get text value

                            // "any text nodes (including CDATA nodes and whitespace text nodes) that are
                            // explicit children of the bound element must have their data concatenated"
                            rightSideValue = boundElement.getText();// must use getText() and not stringValue()
                            namespaceElement = null;
                        }

                        if (rightSideValue != null) {
                            // NOTE: XBL doesn't seem to says what should happen if the source attribute is not
                            // found! We assume the rule is ignored in this case.
                            if (!isLeftSideXBLText) {
                                // Set attribute value
                                setAttribute(resultingNodes, leftSideQName, rightSideValue, namespaceElement);
                            } else {
                                // Set text value

                                // "value of the attribute on the right-hand side are to be represented as text
                                // nodes underneath the shadow element"

                                // TODO: "If the element has any child nodes in the DOM (any nodes, including
                                // comment nodes, whitespace text nodes, or even empty CDATA nodes) then the pair
                                // is in error and UAs must ignore it, meaning the attribute value is not forwarded"

                                setText(resultingNodes, rightSideValue);
                            }
                        }
                    }
                    // TODO: handle xbl:lang?
                    // TODO: handle type specifiers?
                }
            } else if (xxblAttr != null) {
                // Detach attribute (not strictly necessary?)
                xxblAttr.detach();
                // Get attribute value
                final String xxblAttrString = xxblAttr.getValue();

                final NodeInfo boundElementInfo = documentWrapper.wrap(boundElement);

                // TODO: don't use getNamespaceContext() as this is already computed for the bound element
                final List<Object> nodeInfos = XPathCache.evaluate(boundElementInfo, xxblAttrString,
                        new NamespaceMapping(Dom4jUtils.getNamespaceContext(element)), null, null, null, null,
                        null, null);// TODO: locationData

                if (nodeInfos.size() > 0) {
                    for (Object nodeInfo : nodeInfos) {
                        final NodeInfo currentNodeInfo = (NodeInfo) nodeInfo;
                        if (currentNodeInfo.getNodeKind() == org.w3c.dom.Node.ATTRIBUTE_NODE) {
                            // This is an attribute
                            final Attribute currentAttribute = (Attribute) ((VirtualNode) currentNodeInfo)
                                    .getUnderlyingNode();
                            setAttribute(resultingNodes, currentAttribute.getQName(),
                                    currentAttribute.getValue(), currentAttribute.getParent());
                        }
                    }
                }
            }

            // Prefix resulting xhtml:*/(@id |@for)

            // NOTE: We could also do the prefixing in the handlers, when the page is output.
            //
            // * Benefit of prefixing here: done statically
            // * Drawback of prefixing here: in the future if we try to reuse simple shadow trees this won't work

            //                    {
            //                        if (resultingNodes != null && resultingNodes.size() > 0) {
            //                            for (Iterator i = resultingNodes.iterator(); i.hasNext();) {
            //                                final Node node = (Node) i.next();
            //                                if (node instanceof Element) {
            //                                    Dom4jUtils.visitSubtree((Element) node, new Dom4jUtils.VisitorListener() {
            //                                        public void startElement(Element element) {
            //                                            if (XMLConstants.XHTML_NAMESPACE_URI.equals(element.getNamespaceURI())) {
            //                                                // Found XHTML element
            //
            //                                                // Update @id and @for if any
            //                                                final Attribute idAttribute = element.attribute("id");
            //                                                if (idAttribute != null) {
            //                                                    idAttribute.setValue(prefix + idAttribute.getValue());
            //                                                }
            //                                                final Attribute forAttribute = element.attribute("for");
            //                                                if (forAttribute != null) {
            //                                                    forAttribute.setValue(prefix + forAttribute.getValue());
            //                                                }
            //                                            }
            //                                        }
            //
            //                                        public void endElement(Element element) {
            //                                        }
            //
            //                                        public void text(Text text) {
            //                                        }
            //                                    });
            //                                }
            //                            }
            //                        }
            //                    }
        }

        private void setAttribute(List<Node> nodes, QName attributeQName, String attributeValue,
                Element namespaceElement) {
            if (nodes != null && nodes.size() > 0) {
                for (final Node node : nodes) {
                    if (node instanceof Element) {
                        final Element element = ((Element) node);
                        // Copy missing namespaces, so that copying things like ref="foo:bar" work as expected
                        Dom4jUtils.copyMissingNamespaces(namespaceElement, element);
                        element.addAttribute(attributeQName, attributeValue);
                    }
                }
            }
        }

        private void setText(List<Node> nodes, String value) {
            if (nodes != null && nodes.size() > 0) {
                for (final Node node : nodes) {
                    if (node instanceof Element) {
                        node.setText(value);
                    }
                }
            }
        }

        public void endElement(Element element) {
        }

        public void text(Text text) {
        }
    }, true);

    return shadowTreeDocument;
}

From source file:org.orbeon.oxf.xforms.XFormsUtils.java

License:Open Source License

/**
 * Return the underlying Node from the given NodeInfo, possibly converting it to a Dom4j Node. Changes to the returned Node may or may not
 * reflect on the original, depending on its type.
 *
 * @param nodeInfo      NodeInfo to process
 * @return              Node/* www  .j a v  a  2 s .c  om*/
 */
public static Node getNodeFromNodeInfoConvert(NodeInfo nodeInfo) {
    if (nodeInfo instanceof VirtualNode)
        return (Node) ((VirtualNode) nodeInfo).getUnderlyingNode();
    else if (nodeInfo.getNodeKind() == org.w3c.dom.Node.ATTRIBUTE_NODE) {
        return Dom4jUtils.createAttribute(
                new QName(nodeInfo.getLocalPart(), new Namespace(nodeInfo.getPrefix(), nodeInfo.getURI())),
                nodeInfo.getStringValue());
    } else
        return TransformerUtils.tinyTreeToDom4j(
                (nodeInfo.getParent() instanceof DocumentInfo) ? nodeInfo.getParent() : nodeInfo);
}

From source file:org.zenonpagetemplates.onePhaseImpl.PageTemplateImpl.java

License:Open Source License

@SuppressWarnings({ "unchecked" })
private void defaultContent(Element element, ContentHandler contentHandler, LexicalHandler lexicalHandler,
        EvaluationHelper evaluationHelper, Stack<Map<String, Slot>> slotStack)
        throws SAXException, PageTemplateException, IOException, EvaluationException {
    // Use default template content
    for (Iterator<Node> i = element.nodeIterator(); i.hasNext();) {
        Node node = i.next();/*from   ww w . j a va 2 s .c  om*/
        switch (node.getNodeType()) {
        case Node.ELEMENT_NODE:
            processElement((Element) node, contentHandler, lexicalHandler, evaluationHelper, slotStack);
            break;

        case Node.TEXT_NODE:
            char[] text = node.getText().toCharArray();
            contentHandler.characters(text, 0, text.length);
            break;

        case Node.COMMENT_NODE:
            char[] comment = node.getText().toCharArray();
            lexicalHandler.comment(comment, 0, comment.length);
            break;

        case Node.CDATA_SECTION_NODE:
            lexicalHandler.startCDATA();
            char[] cdata = node.getText().toCharArray();
            contentHandler.characters(cdata, 0, cdata.length);
            lexicalHandler.endCDATA();
            break;

        case Node.NAMESPACE_NODE:
            Namespace declared = (Namespace) node;
            //System.err.println( "Declared namespace: " + declared.getPrefix() + ":" + declared.getURI() );
            this.namespaces.put(declared.getPrefix(), declared.getURI());
            //if ( declared.getURI().equals( TAL_NAMESPACE_URI ) ) {
            //    this.talNamespacePrefix = declared.getPrefix();
            //} 
            //else if (declared.getURI().equals( METAL_NAMESPACE_URI ) ) {
            //    this.metalNamespacePrefix = declared.getPrefix();
            //}
            break;

        case Node.ATTRIBUTE_NODE:
            // Already handled
            break;

        case Node.DOCUMENT_TYPE_NODE:
        case Node.ENTITY_REFERENCE_NODE:
        case Node.PROCESSING_INSTRUCTION_NODE:
        default:
            //System.err.println( "WARNING: Node type not supported: " + node.getNodeTypeName() );       
        }
    }
}

From source file:org.zenonpagetemplates.twoPhasesImpl.ZPTDocumentFactory.java

License:Open Source License

@SuppressWarnings({ "unchecked" })
static private void mapContent(Element element, ZPTElement zptElement, ZPTDocument zptDocument,
        Stack<Map<String, Slot>> slotStack) throws SAXException, PageTemplateException, IOException {

    // Use default template content
    for (Iterator<Node> i = element.nodeIterator(); i.hasNext();) {
        Node node = i.next();//www.  j  a v a  2 s. co  m
        switch (node.getNodeType()) {
        case Node.ELEMENT_NODE:
            zptElement.addContent(getNewZPTElement((Element) node, zptDocument, slotStack));
            break;

        case Node.TEXT_NODE:
            zptElement.addContent(new TextNode(node.getText()));
            break;

        case Node.CDATA_SECTION_NODE:
            zptElement.addContent(new CDATANode(node.getText()));
            break;

        case Node.NAMESPACE_NODE: // Already handled
            /*
             Namespace declared = (Namespace)node;
             if (zptDocument.isNamespaceToDeclare(declared)){
                zptDocument.addNamespace(declared);
             } else {
                zptElement.addNamespaceStaticAttribute(declared);
             }
             break;*/

        case Node.ATTRIBUTE_NODE: // Already handled
        case Node.COMMENT_NODE: // Remove all comments
        case Node.DOCUMENT_TYPE_NODE:
        case Node.ENTITY_REFERENCE_NODE:
        case Node.PROCESSING_INSTRUCTION_NODE:
        default:
            // Nothing to do
        }
    }
}