diff options
Diffstat (limited to 'src/uscxml/interpreter/BasicContentExecutor.cpp')
-rw-r--r-- | src/uscxml/interpreter/BasicContentExecutor.cpp | 230 |
1 files changed, 82 insertions, 148 deletions
diff --git a/src/uscxml/interpreter/BasicContentExecutor.cpp b/src/uscxml/interpreter/BasicContentExecutor.cpp index 5344957..9ea2b6a 100644 --- a/src/uscxml/interpreter/BasicContentExecutor.cpp +++ b/src/uscxml/interpreter/BasicContentExecutor.cpp @@ -593,155 +593,89 @@ void BasicContentExecutor::processParams(std::multimap<std::string, Data>& param paramMap.insert(make_pair(name, d)); } } - + Data BasicContentExecutor::elementAsData(XERCESC_NS::DOMElement* element, bool asExpression) { - if (HAS_ATTR(element, kXMLCharExpr)) { -// return _callbacks->evalAsData(ATTR(element, "expr")); -#if 0 - if (LOCALNAME(element) == "content") { - // test 528 - return _callbacks->evalAsData(ATTR(element, kXMLCharExpr)); - } else { - // test 326 - return Data(ATTR(element, kXMLCharExpr), Data::INTERPRETED); - } -#endif - if (asExpression) // test 453 - return Data(ATTR(element, kXMLCharExpr), Data::INTERPRETED); - return _callbacks->evalAsData(ATTR(element, kXMLCharExpr)); - } - - if (HAS_ATTR(element, kXMLCharSource)) { - // remote content from URL - - // test 446, test 552, test 558 - std::string src = ATTR(element, kXMLCharSource); - URL url(ATTR(element, kXMLCharSource)); - if (!url.isAbsolute()) { - url = URL::resolve(url, _callbacks->getBaseURL()); - } - - std::string content = url.getInContent(); - - // make an attempt to parse as XML - try { -#if 0 - XERCESC_NS::XercesDOMParser parser; - parser.setValidationScheme(XERCESC_NS::XercesDOMParser::Val_Never); - parser.setDoNamespaces(true); - parser.useScanner(XERCESC_NS::XMLUni::fgWFXMLScanner); - - XERCESC_NS::HandlerBase errHandler; - parser.setErrorHandler(&errHandler); - - std::string tmp = url; - XERCESC_NS::MemBufInputSource is((XMLByte*)content.c_str(), content.size(), X("fake")); - - parser.parse(is); - - Data d; - XERCESC_NS::DOMDocument* doc = parser.adoptDocument(); - d.adoptedDoc = std::shared_ptr<XERCESC_NS::DOMDocument>(doc); - d.node = doc->getDocumentElement(); - return d; -#else - std::unique_ptr<XERCESC_NS::XercesDOMParser> parser(new XERCESC_NS::XercesDOMParser()); - parser->setValidationScheme(XERCESC_NS::XercesDOMParser::Val_Always); - parser->setDoNamespaces(true); - parser->useScanner(XERCESC_NS::XMLUni::fgWFXMLScanner); - - std::unique_ptr<XERCESC_NS::ErrorHandler> errHandler(new XERCESC_NS::HandlerBase()); - parser->setErrorHandler(errHandler.get()); - - try { - std::string tmp = url; - parser->parse(tmp.c_str()); - - XERCESC_NS::DOMNode* newNode = element->getOwnerDocument()->importNode(parser->getDocument()->getDocumentElement(), true); - - // remove any old child elements - while(element->getFirstElementChild() != NULL) { - element->removeChild(element->getFirstElementChild()); - } - // we need to save the DOM somewhere .. Data::adoptedDoc was not good enough - element->appendChild(newNode); - - Data d; -// d.adoptedDoc = std::shared_ptr<XERCESC_NS::DOMDocument>(parser->adoptDocument()); - d.node = newNode; - return d; - } - - catch (const XERCESC_NS::SAXParseException& toCatch) { - ERROR_PLATFORM_THROW(X(toCatch.getMessage()).str()); - } catch (const XERCESC_NS::RuntimeException& toCatch) { - ERROR_PLATFORM_THROW(X(toCatch.getMessage()).str()); - } catch (const XERCESC_NS::XMLException& toCatch) { - ERROR_PLATFORM_THROW(X(toCatch.getMessage()).str()); - } catch (const XERCESC_NS::DOMException& toCatch) { - ERROR_PLATFORM_THROW(X(toCatch.getMessage()).str()); - } - -#endif - - } catch (...) { - // just ignore and return as an interpreted string below - } - try { - Data d = _callbacks->getAsData(content); - if (!d.empty()) - return d; - } catch(...) {} - - return Data(spaceNormalize(content), Data::VERBATIM); - - } else { - // local content in document - - std::list<DOMNode*> elementChildren = DOMUtils::filterChildType(DOMNode::ELEMENT_NODE, element); - if (elementChildren.size() > 0) { - // always return parent element, even with a single child node - return Data(static_cast<DOMNode*>(element)); - } - - std::list<DOMNode*> textChildren = DOMUtils::filterChildType(DOMNode::TEXT_NODE, element); - if (textChildren.size() > 0) { - std::stringstream contentSS; - for (auto textIter = textChildren.begin(); textIter != textChildren.end(); textIter++) { - contentSS << X((*textIter)->getNodeValue()); - } - - // this must be handled in getAsData - // test294, test562 - if (LOCALNAME(element) == "content") { - // need first try getAsData because how to pass 179 ? - try { - // test153, we need to throw for test150 in promela - Data d = _callbacks->getAsData(contentSS.str()); - if (!d.empty()) - return d; - } catch (ErrorEvent &) { - return Data(spaceNormalize(contentSS.str()), Data::VERBATIM); - } - } - - if (asExpression) // not actually used, but likely expected - return Data(contentSS.str(), Data::INTERPRETED); - - // test153, we need to throw for test150 in promela, but we need to space normalize for test558 - try { - Data d = _callbacks->getAsData(contentSS.str()); - if (!d.empty()) - return d; - } catch ( ... ) {} - - // test558 - return Data(spaceNormalize(contentSS.str()), Data::VERBATIM); - } - } - -// LOG(USCXML_WARN) << "Element " << DOMUtils::xPathForNode(element) << " did not yield any data"; - return Data(); + // element with expr + if (HAS_ATTR(element, kXMLCharExpr)) { + std::string expr = ATTR(element, kXMLCharExpr); + if (_callbacks->isLegalDataValue(expr)) { + return Data(expr, Data::INTERPRETED); + } else { + ERROR_EXECUTION_THROW2("Expression '" + expr + "' is not a legal data value", element); + } + } + + // element with external src - this ought to behave just as with child nodes below + if (HAS_ATTR(element, kXMLCharSource)) { + + // remove any old child elements + while(element->getFirstElementChild() != NULL) { + element->removeChild(element->getFirstElementChild()); + } + + std::string src = ATTR(element, kXMLCharSource); + URL url(ATTR(element, kXMLCharSource)); + if (!url.isAbsolute()) { + url = URL::resolve(url, _callbacks->getBaseURL()); + } + std::string content = url.getInContent(); + + // append as XML? + try { + std::unique_ptr<XERCESC_NS::XercesDOMParser> parser(new XERCESC_NS::XercesDOMParser()); + parser->setValidationScheme(XERCESC_NS::XercesDOMParser::Val_Always); + parser->setDoNamespaces(true); + parser->useScanner(XERCESC_NS::XMLUni::fgWFXMLScanner); + + std::unique_ptr<XERCESC_NS::ErrorHandler> errHandler(new XERCESC_NS::HandlerBase()); + parser->setErrorHandler(errHandler.get()); + + XERCESC_NS::MemBufInputSource is((XMLByte*)content.c_str(), content.size(), X("fake")); + is.setPublicId(X(url)); + + parser->parse(is); + XERCESC_NS::DOMNode* newNode = element->getOwnerDocument()->importNode(parser->getDocument()->getDocumentElement(), true); + + // we need to save the DOM somewhere .. Data::adoptedDoc was not good enough + element->appendChild(newNode); + goto SOURCE_APPEND_DONE; + } catch (...) { + } + + // append as text (are we leaking?) + XERCESC_NS::DOMText* textNode = element->getOwnerDocument()->createTextNode(X(content)); + element->appendChild(textNode); + } +SOURCE_APPEND_DONE: + + if (element->hasChildNodes()) { + // XML elements e.g. for content with invoke + std::list<DOMNode*> elementChildren = DOMUtils::filterChildType(DOMNode::ELEMENT_NODE, element); + if (elementChildren.size() > 0) { + // always return parent element, even with a single child node + return Data(static_cast<DOMNode*>(element)); + } + + // expression in text element + std::list<DOMNode*> textChildren = DOMUtils::filterChildType(DOMNode::TEXT_NODE, element); + if (textChildren.size() > 0) { + std::stringstream contentSS; + for (auto textIter = textChildren.begin(); textIter != textChildren.end(); textIter++) { + contentSS << X((*textIter)->getNodeValue()); + } + + try { + Data d = _callbacks->getAsData(contentSS.str()); + if (!d.empty()) + return d; + } catch(...) {} + + // anything else is considered verbatim - space normalize? + return Data(spaceNormalize(contentSS.str()), Data::VERBATIM); + } + } + + return Data(); } } |