void XercesUpdateFactory::completeDeletions(DynamicContext *context) { // e. Finally, for each node marked for deletion by one of the update primitives listed above, let $N be the node that is marked // for deletion, and let $P be its parent node. The following actions are applied: // i. The parent property of $N is set to empty. // ii. If $N is an attribute node, the attributes property of $P is modified to remove $N. // iii. If $N is a non-attribute node, the children property of $P is modified to remove $N. // iv. If $N is an element, attribute, or text node, and $P is an element node, then upd:removeType($P) is invoked. for(DOMNodeSet::iterator i = forDeletion_.begin(); i != forDeletion_.end(); ++i) { DOMNode *domnode = *i; if(domnode->getNodeType() == DOMNode::ATTRIBUTE_NODE) { DOMAttr *attr = (DOMAttr*)domnode; DOMElement *owner = attr->getOwnerElement(); if(owner != 0) { owner->removeAttributeNode(attr); removeType(owner); } } else { DOMNode *parent = domnode->getParentNode(); if(parent != 0) { parent->removeChild(domnode); if(domnode->getNodeType() == DOMNode::ELEMENT_NODE || domnode->getNodeType() == DOMNode::TEXT_NODE || domnode->getNodeType() == DOMNode::CDATA_SECTION_NODE) { removeType(parent); } } } } }
void XercesUpdateFactory::applyReplaceAttribute(const PendingUpdate &update, DynamicContext *context) { const XercesNodeImpl *nodeImpl = (const XercesNodeImpl*)update.getTarget()->getInterface(Item::gXQilla); DOMAttr *domnode = (DOMAttr*)nodeImpl->getDOMNode(); Node::Ptr parentNode = nodeImpl->dmParent(context); DOMElement *element = domnode->getOwnerElement(); DOMDocument *doc = element->getOwnerDocument(); bool untyped = parentNode->dmNodeKind() == Node::element_string && XPath2Utils::equals(parentNode->getTypeName(), DocumentCache::g_szUntyped) && XPath2Utils::equals(parentNode->getTypeURI(), SchemaSymbols::fgURI_SCHEMAFORSCHEMA); Result children = update.getValue(); Item::Ptr item; while((item = children->next(context)).notNull()) { const XercesNodeImpl *childImpl = (const XercesNodeImpl*)item->getInterface(Item::gXQilla); DOMNode *newChild = importNodeFix(doc, const_cast<DOMNode*>(childImpl->getDOMNode()), /*deep*/true); // 1. Error checks: // a. If the QNames of any two attribute nodes in $replacement have implied namespace bindings that conflict with // each other, a dynamic error is raised [err:XUDY0024]. // b. If the QName of any attribute node in $replacement has an implied namespace binding that conflicts with a // namespace binding in the "namespaces" property of parent($target), a dynamic error is raised [err:XUDY0024]. // Checks performed by UpdateFactory // 2b. If the type-name property of parent($target) is xs:untyped, then upd:setToUntyped() is invoked // on each element node in $replacement. if(!untyped) setTypes(newChild, childImpl->getDOMNode()); // 2a. For each node in $replacement, the parent property is set to parent($target). // 4a. If $target is an attribute node, the attributes property of parent($target) is modified by removing $target // and adding the nodes in $replacement (if any). // 4b. If $target is an attribute node, the namespaces property of parent($target) is modified to include namespace // bindings for any attribute namespace prefixes in $replacement that did not already have bindings. element->setAttributeNode((DOMAttr*)newChild); } // 3a. $target is marked for deletion. forDeletion_.insert(domnode); // 4d. upd:removeType(parent($target)) is invoked. removeType(element); // Use parentNode, since the attr replace could have removed the original attr addToPutSet(parentNode, &update, context); }