private static List<Node> doInsert( Node insertionNode, List<Node> clonedNodes, XFormsInstance modifiedInstance, boolean doDispatch) { final List<Node> insertedNodes = new ArrayList<Node>(clonedNodes.size()); if (insertionNode instanceof Element) { // Insert inside an element final Element insertContextElement = (Element) insertionNode; int otherNodeIndex = 0; for (Node clonedNode : clonedNodes) { if (clonedNode != null) { // NOTE: we allow passing some null nodes so we check on null if (clonedNode instanceof Attribute) { // Add attribute to element // 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. final Attribute clonedAttribute = (Attribute) clonedNode; final Attribute existingAttribute = insertContextElement.attribute(clonedAttribute.getQName()); if (existingAttribute != null) insertContextElement.remove(existingAttribute); insertContextElement.add(clonedAttribute); if (existingAttribute != null) { // Dispatch xxforms-replace event if required and possible // NOTE: For now, still dispatch xforms-insert for backward compatibility. if (doDispatch && modifiedInstance != null) { final DocumentWrapper documentWrapper = (DocumentWrapper) modifiedInstance.documentInfo(); Dispatch.dispatchEvent( new XXFormsReplaceEvent( modifiedInstance, documentWrapper.wrap(existingAttribute), documentWrapper.wrap(clonedAttribute))); } } insertedNodes.add(clonedAttribute); } else if (!(clonedNode instanceof Document)) { // Add other node to element insertContextElement.content().add(otherNodeIndex++, clonedNode); insertedNodes.add(clonedNode); } else { // "If a cloned node cannot be placed at the target location due to a node type // conflict, then the // insertion for that particular clone node is ignored." } } } return insertedNodes; } else if (insertionNode instanceof Document) { final Document insertContextDocument = (Document) insertionNode; // "If there is more than one cloned node to insert, only the first node that does not cause a // conflict is // considered." for (Node clonedNode : clonedNodes) { // Only an element can be inserted at the root of an instance if (clonedNode instanceof Element) { final Element formerRootElement = insertContextDocument.getRootElement(); insertContextDocument.setRootElement((Element) clonedNode); // Dispatch xxforms-replace event if required and possible // NOTE: For now, still dispatch xforms-insert for backward compatibility. if (doDispatch && modifiedInstance != null) { final DocumentWrapper documentWrapper = (DocumentWrapper) modifiedInstance.documentInfo(); Dispatch.dispatchEvent( new XXFormsReplaceEvent( modifiedInstance, documentWrapper.wrap(formerRootElement), documentWrapper.wrap(insertContextDocument.getRootElement()))); } insertedNodes.add(clonedNode); return insertedNodes; } } // NOTE: The spec does not allow inserting comments and PIs at the root of an instance // document at this // point. return insertedNodes; } else { throw new OXFException( "Unsupported insertion node type: " + insertionNode.getClass().getName()); } }