void XercesUpdateFactory::applyReplaceElementContent(const PendingUpdate &update, DynamicContext *context) { const XercesNodeImpl *nodeImpl = (const XercesNodeImpl*)update.getTarget()->getInterface(Item::gXQilla); DOMElement *domnode = (DOMElement*)nodeImpl->getDOMNode(); // 1. For each node $C that is a child of $target, the parent property of $C is set to empty. DOMNode *child = domnode->getFirstChild(); while(child != 0) { forDeletion_.insert(child); child = child->getNextSibling(); } const XMLCh *value = update.getValue().first()->asString(context); if(value != 0 && *value != 0) { // 2. The parent property of $text is set to $target. // 3a. children is set to consist exclusively of $text. If $text is an empty sequence, then $target has // no children. // 3b. typed-value and string-value are set to the content property of $text. If $text is an empty sequence, // then typed-value is an empty sequence and string-value is an empty string. domnode->appendChild(domnode->getOwnerDocument()->createTextNode(value)); } // 3c. upd:removeType($target) is invoked. removeType(domnode); addToPutSet(update.getTarget(), &update, context); }
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); }
Override::Override(const DOMElement* e, Category& log, const Override* base) : m_base(base), m_acl(NULL) { try { // Load the property set. load(e,log,this); // Load any AccessControl provider. loadACL(e,log); // Handle nested Paths. DOMElement* path = XMLHelper::getFirstChildElement(e,Path); for (int i=1; path; ++i, path=XMLHelper::getNextSiblingElement(path,Path)) { const XMLCh* n=path->getAttributeNS(NULL,name); // Skip any leading slashes. while (n && *n==chForwardSlash) n++; // Check for empty name. if (!n || !*n) { log.warn("skipping Path element (%d) with empty name attribute", i); continue; } // Check for an embedded slash. int slash=XMLString::indexOf(n,chForwardSlash); if (slash>0) { // Copy the first path segment. XMLCh* namebuf=new XMLCh[slash + 1]; for (int pos=0; pos < slash; pos++) namebuf[pos]=n[pos]; namebuf[slash]=chNull; // Move past the slash in the original pathname. n=n+slash+1; // Skip any leading slashes again. while (*n==chForwardSlash) n++; if (*n) { // Create a placeholder Path element for the first path segment and replant under it. DOMElement* newpath=path->getOwnerDocument()->createElementNS(shibspconstants::SHIB2SPCONFIG_NS,Path); newpath->setAttributeNS(NULL,name,namebuf); path->setAttributeNS(NULL,name,n); path->getParentNode()->replaceChild(newpath,path); newpath->appendChild(path); // Repoint our locals at the new parent. path=newpath; n=path->getAttributeNS(NULL,name); } else { // All we had was a pathname with trailing slash(es), so just reset it without them. path->setAttributeNS(NULL,name,namebuf); n=path->getAttributeNS(NULL,name); } delete[] namebuf; } Override* o=new Override(path,log,this); pair<bool,const char*> name=o->getString("name"); char* dup=strdup(name.second); for (char* pch=dup; *pch; pch++) *pch=tolower(*pch); if (m_map.count(dup)) { log.warn("Skipping duplicate Path element (%s)",dup); free(dup); delete o; continue; } m_map[dup]=o; free(dup); } } catch (exception&) { delete m_acl; for_each(m_map.begin(),m_map.end(),xmltooling::cleanup_pair<string,Override>()); throw; } }