#include "../config/pathan_config.h" /* * Copyright (c) 2001, DecisionSoft Limited All rights reserved. * Please see LICENSE.TXT for more information. */ #include #include #include #include "../exceptions/InvalidLexicalSpaceException.hpp" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include const XMLCh FunctionIdref::name[] = { XERCES_CPP_NAMESPACE_QUALIFIER chLatin_i, XERCES_CPP_NAMESPACE_QUALIFIER chLatin_d, XERCES_CPP_NAMESPACE_QUALIFIER chLatin_r, XERCES_CPP_NAMESPACE_QUALIFIER chLatin_e, XERCES_CPP_NAMESPACE_QUALIFIER chLatin_f, XERCES_CPP_NAMESPACE_QUALIFIER chNull }; /** * fn:idref($arg as xs:string*) as node()* **/ FunctionIdref::FunctionIdref(const VectorOfDataItems &args, XPath2MemoryManager* memMgr) : DataItemFunction(name,1, 1, "string*", args, memMgr) { } DataItem* FunctionIdref::staticResolution(StaticContext *context, StaticResolutionContext *src) { src->contextItemUsed(true); return resolveDataItems(_args, context, src, false); } Sequence FunctionIdref::collapseTreeInternal(DynamicContext* context, int flags) const { const Item* item = context->getContextItem(); if(item==NULL || !item->isNode()) { DSLthrow(FunctionException,X("FunctionIdref::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("FunctionIdref::collapseTreeInternal"), X("No context document.")); } Sequence strings = getParamNumber(1, context); if(strings.isEmpty()) return Sequence(context->getMemoryManager()); std::vector values; //get the list of idref 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); //for each string check that it is lexically a xs:ID, if not ignore it bool validID = true; try { DatatypeFactory::STR2AT::createStringOrDerived(context->getMemoryManager(), XERCES_CPP_NAMESPACE_QUALIFIER SchemaSymbols::fgURI_SCHEMAFORSCHEMA, XERCES_CPP_NAMESPACE_QUALIFIER XMLUni::fgIDString, str, context); } catch (InvalidLexicalSpaceException &e) { validID = false; } if (validID) { values.push_back(str); } } Sequence result(context->getMemoryManager()); IdrefNodeFilter filter(values); unsigned long whatToShow = XERCES_CPP_NAMESPACE_QUALIFIER DOMNodeFilter::SHOW_ELEMENT; //for each element in the document check if it has idref values that reference one or more of the ID values 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; } FunctionIdref::IdrefNodeFilter::IdrefNodeFilter(std::vector list) : _values(list) { } short FunctionIdref::IdrefNodeFilter::acceptNode (const XERCES_CPP_NAMESPACE_QUALIFIER DOMNode * node) const{ XPath2MemoryManagerImpl memMgr; const XERCES_CPP_NAMESPACE_QUALIFIER DOMElement *element = static_cast(node); const XERCES_CPP_NAMESPACE_QUALIFIER DOMTypeInfo *typeInfo = element->getTypeInfo(); XERCES_CPP_NAMESPACE_QUALIFIER DOMNamedNodeMap *attrMap = node->getAttributes(); //check if the element is of type IDREF(S) and if so if it has a value matching one in the list if (XERCES_CPP_NAMESPACE_QUALIFIER XMLString::equals(typeInfo->getNamespace(), XERCES_CPP_NAMESPACE_QUALIFIER SchemaSymbols::fgURI_SCHEMAFORSCHEMA)) { //if it's an IDREF see if the value is in the vectors of ones we want if (XERCES_CPP_NAMESPACE_QUALIFIER XMLString::equals(typeInfo->getName(), XERCES_CPP_NAMESPACE_QUALIFIER XMLUni::fgIDRefString) && XPath2Utils::containsString(_values, element->getTextContent())){ return XERCES_CPP_NAMESPACE_QUALIFIER DOMNodeFilter::FILTER_ACCEPT; //if it's an IDREFS see if any of the values are in the ones we want } else if (XERCES_CPP_NAMESPACE_QUALIFIER XMLString::equals(typeInfo->getName(), XERCES_CPP_NAMESPACE_QUALIFIER XMLUni::fgIDRefsString)){ std::vector idVals=XPath2Utils::getVal(element->getTextContent(), &memMgr); for (std::vector::iterator it=idVals.begin();it!=idVals.end();it++) { if (XPath2Utils::containsString(_values, *it)) { return XERCES_CPP_NAMESPACE_QUALIFIER DOMNodeFilter::FILTER_ACCEPT; } } //for } } //if the node has attributes, search through them if (attrMap != 0) { const XERCES_CPP_NAMESPACE_QUALIFIER DOMAttr *attr; int attrLen = attrMap->getLength(); //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)) { //if it's an IDREF see if the value is in the vectors of ones we want if (XERCES_CPP_NAMESPACE_QUALIFIER XMLString::equals(typeInfo->getName(), XERCES_CPP_NAMESPACE_QUALIFIER XMLUni::fgIDRefString) && XPath2Utils::containsString(_values, attr->getValue())){ return XERCES_CPP_NAMESPACE_QUALIFIER DOMNodeFilter::FILTER_ACCEPT; //if it's an IDREFS see if any of the values are in the ones we want }else if (XERCES_CPP_NAMESPACE_QUALIFIER XMLString::equals(typeInfo->getName(), XERCES_CPP_NAMESPACE_QUALIFIER XMLUni::fgIDRefsString)){ std::vector idVals=XPath2Utils::getVal(attr->getValue(), &memMgr); for (std::vector::iterator it=idVals.begin();it!=idVals.end();it++) { if (XPath2Utils::containsString(_values, *it)) { return XERCES_CPP_NAMESPACE_QUALIFIER DOMNodeFilter::FILTER_ACCEPT; } } } } }//for } return XERCES_CPP_NAMESPACE_QUALIFIER DOMNodeFilter::FILTER_REJECT; }