#include "../config/pathan_config.h" /* * Copyright (c) 2001, DecisionSoft Limited All rights reserved. * Please see LICENSE.TXT for more information. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include const XMLCh FunctionId::name[] = { XERCES_CPP_NAMESPACE_QUALIFIER chLatin_i, XERCES_CPP_NAMESPACE_QUALIFIER chLatin_d, XERCES_CPP_NAMESPACE_QUALIFIER chNull }; /** * fn:id($arg as xs:string*) as element()* **/ FunctionId::FunctionId(const VectorOfDataItems &args, XPath2MemoryManager* memMgr) : DataItemFunction(name,1, 1, "string*", args, memMgr) { } DataItem* FunctionId::staticResolution(StaticContext *context, StaticResolutionContext *src) { src->contextItemUsed(true); return resolveDataItems(_args, context, src, false); } Sequence FunctionId::collapseTreeInternal(DynamicContext* context, int flags) const { const Item* item = context->getContextItem(); if(item==NULL || !item->isNode()) { DSLthrow(FunctionException,X("FunctionId::collapseTreeInternal"), X("No context node")); } const XERCES_CPP_NAMESPACE_QUALIFIER DOMNode *node = ((const Node*)item)->getDOMNode(); XERCES_CPP_NAMESPACE_QUALIFIER DOMDocument *doc; if((doc = node->getOwnerDocument()) == 0) { DSLthrow(FunctionException,X("FunctionId::collapseTreeInternal"), X("Current context has no owner document")); } Sequence strings = getParamNumber(1, context); if(strings.isEmpty()) return Sequence(context->getMemoryManager()); std::vector values; //get the list of id values we're looking for by iterating over each string in the sequence for (Sequence::iterator stringIt = strings.begin(); stringIt != strings.end(); ++stringIt) { const XMLCh *str = ((const ATStringOrDerived*)(*stringIt))->asString(context); std::vector idList = XPath2Utils::getVal(str, context->getMemoryManager()); //for each list obtained from a string check that each id is unique to the full list and if so add it for (std::vector::iterator listIt=idList.begin(); listIt!=idList.end(); ++listIt) { if (!XPath2Utils::containsString(values, *listIt)) values.push_back(*listIt); } } Sequence result(context->getMemoryManager()); IdNodeFilter filter(values); unsigned long whatToShow = XERCES_CPP_NAMESPACE_QUALIFIER DOMNodeFilter::SHOW_ELEMENT; //for each element in the document check if it has an id matching one in our list, if so add it to the result XERCES_CPP_NAMESPACE_QUALIFIER DOMNodeIterator *nodeIt = doc->createNodeIterator((XERCES_CPP_NAMESPACE_QUALIFIER DOMNode *)node, whatToShow, &filter, true); for (XERCES_CPP_NAMESPACE_QUALIFIER DOMNode *n = nodeIt->nextNode(); n != NULL; n = nodeIt->nextNode()){ result.addItem(context->getMemoryManager()->createNode(n)); } nodeIt->release(); return result; } FunctionId::IdNodeFilter::IdNodeFilter(std::vector list) : _values(list) { } short FunctionId::IdNodeFilter::acceptNode (const XERCES_CPP_NAMESPACE_QUALIFIER DOMNode * node) const { XERCES_CPP_NAMESPACE_QUALIFIER DOMNamedNodeMap *attrMap = node->getAttributes(); if (attrMap != 0){ int attrLen = attrMap->getLength(); const XERCES_CPP_NAMESPACE_QUALIFIER DOMAttr *attr; const XERCES_CPP_NAMESPACE_QUALIFIER DOMTypeInfo *typeInfo; //go through the attributes for (int i=0; i(attrMap->item(i)); typeInfo = attr->getTypeInfo(); if (XERCES_CPP_NAMESPACE_QUALIFIER XMLString::equals(typeInfo->getNamespace(), XERCES_CPP_NAMESPACE_QUALIFIER SchemaSymbols::fgURI_SCHEMAFORSCHEMA)) { const XMLCh* id = attr->getValue(); //if it's an ID see if the value is in the vectors of ones we want //and is not the same as one belonging to a previously accepted element (can happen in a well-formed, but invalid XML document) if (XERCES_CPP_NAMESPACE_QUALIFIER XMLString::equals(typeInfo->getName(), XERCES_CPP_NAMESPACE_QUALIFIER XMLUni::fgIDString) && XPath2Utils::containsString(_values, id) && !XPath2Utils::containsString(_returnedVals, id)) { //we add the id to our list, but must use a C style cast on this for xercesc integration -- djf ((IdNodeFilter*)this)->_returnedVals.push_back(id); return XERCES_CPP_NAMESPACE_QUALIFIER DOMNodeFilter::FILTER_ACCEPT; } } }//for } return XERCES_CPP_NAMESPACE_QUALIFIER DOMNodeFilter::FILTER_REJECT; }