📄 documentconverter.cpp
字号:
void DocumentConverter::ParseException(const VXIchar * message) const { if (message == NULL) throw SAXParseException(NULL, *locator); VXIcharToXMLCh text(message); throw SAXParseException(text.c_str(), *locator); } void DocumentConverter::startDocument() { version = -1; choiceNumber = 0; inGrammar = false; implicitPrompt = false; explicitPrompt = false; copyDepth = 0; ignoreDepth = 0; pcdataImpliesPrompt = true; documentLang=L""; if (doc != NULL) VXMLDocumentRep::Release(doc); doc = new VXMLDocumentRep(); if (doc == NULL) ParseException(L"unable to allocate memory for element"); } void DocumentConverter::endDocument() { } void DocumentConverter::ResetDocument() { if (doc != NULL) VXMLDocumentRep::Release(doc); doc = NULL; } VXMLDocumentRep * DocumentConverter::GetDocument() { VXMLDocumentRep * temp = doc; doc = NULL; return temp; } void DocumentConverter::setDocumentLocator(const Locator* const loc) { if (loc == NULL) locator = &DUMMYLOCATOR; else locator = loc; } void DocumentConverter::startElement(const XMLCh* const uri, const XMLCh* const localname, const XMLCh* const qname, const Attributes & attrs) { // (0) Just ignore this? if (ignoreDepth > 0) { ++ignoreDepth; return; } // (1) Copy this element or look it up? // (1.1) Inside a <grammar>, we can blindly copy this data. if (inGrammar) { CopyElementStart(localname, attrs); return; } // (1.2) Convert name string to integer value. XMLChToVXIchar elementName(localname); int rawElemType; bool conversionFailed = !ConvertElement(elementName.c_str(), rawElemType); // (1.3) Copy almost anything inside a <prompt>. if (explicitPrompt) { if (conversionFailed) { CopyElementStart(localname, attrs); return; } switch (rawElemType) { case NODE_AUDIO: case NODE_VALUE: case NODE_ENUMERATE: break; default: CopyElementStart(localname, attrs); return; } } // (1.4) Print errors for all other conversion failures. if (conversionFailed) { vxistring temp(L"unrecognized element - "); temp += elementName.c_str(); ParseException(temp.c_str()); } // (2) Check for ignored nodes and do version number processing. if (rawElemType == PRIV_ELEM_METADATA) { ignoreDepth = 1; return; } // (2.1) Catch illegal nodes and do version number processing. Prompt and // grammar copying flags are set in the same pass. switch (rawElemType) { case DEFAULTS_ROOT: version = 2.0f; break; case NODE_VXML: { for (unsigned int index = 0; index < attrs.getLength(); ++index) { if (!Compare(attrs.getLocalName(index), L"version")) continue; const XMLCh * attributeValue = attrs.getValue(index); if (Compare(attributeValue, L"2.0")) version = 2.0f; else ParseException(L"unsupported vxml version"); break; } } break; case NODE_GRAMMAR: // Copy grammar contents. inGrammar = true; copyDepth = 0; break; case NODE_PROMPT: // Copy prompt contents. explicitPrompt = true; copyDepth = 0; break; case NODE_SCRIPT: case NODE_CHOICE: // These may have PCDATA which is not a prompt case NODE_OPTION: case NODE_LOG: pcdataImpliesPrompt = false; break; default: break; } // (2.2) Is this the beginning or end of an implicit prompt? switch (rawElemType) { case NODE_AUDIO: case NODE_VALUE: // NOTE: A <value> may also appear in <log>. case NODE_ENUMERATE: if (pcdataImpliesPrompt && !implicitPrompt && !explicitPrompt) StartImplicitPrompt(); break; case PRIV_ELEM_BREAK: // These implicitly imply a prompt. case PRIV_ELEM_EMPHASIS: case PRIV_ELEM_MARK: case PRIV_ELEM_PARAGRAPH: case PRIV_ELEM_PHONEME: case PRIV_ELEM_PROSODY: case PRIV_ELEM_SAYAS: case PRIV_ELEM_SENTENCE: case PRIV_ELEM_VOICE: if (!implicitPrompt) StartImplicitPrompt(); CopyElementStart(localname, attrs); return; default: if (implicitPrompt) { // We require that implicit prompts contain only familiar SSML. if (copyDepth == 0) EndImplicitPrompt(); else ParseException(L"illegal prompt content"); } break; } // (2.4) Convert nodes as necessary. VXMLElementType elemType = VXMLElementType(rawElemType); switch (rawElemType) { case PRIV_ELEM_ERROR: case PRIV_ELEM_HELP: case PRIV_ELEM_NOINPUT: case PRIV_ELEM_NOMATCH: elemType = NODE_CATCH; break; default: break; } if (elemType > PRIV_ELEM_RangeStart) { vxistring temp(L"internal error for element - "); temp += elementName.c_str(); ParseException(temp.c_str()); } // (3) Create new element. try { hasContent = (elemType != NODE_SCRIPT && elemType != NODE_GRAMMAR); doc->StartElement(elemType); } catch (const VXMLDocumentModel::OutOfMemory &) { ParseException(L"unable to allocate memory for element"); } catch (const VXMLDocumentModel::InternalError &) { ParseException(L"corrupted document tree; unable to add element"); } // (4) Add attributes to element. int attrGroup1 = 0; int attrGroup2 = 0; // (4.1) Do special handling for converted nodes. switch (rawElemType) { case PRIV_ELEM_ERROR: ProcessNodeAttribute(elemType, ATTRIBUTE_EVENT, L"error"); break; case PRIV_ELEM_HELP: ProcessNodeAttribute(elemType, ATTRIBUTE_EVENT, L"help"); break; case PRIV_ELEM_NOINPUT: ProcessNodeAttribute(elemType, ATTRIBUTE_EVENT, L"noinput"); break; case PRIV_ELEM_NOMATCH: ProcessNodeAttribute(elemType, ATTRIBUTE_EVENT, L"nomatch"); break; default: break; } bool foundResourceBaseURI = false; bool foundResourceBaseLang = false; for (unsigned int index = 0; index < attrs.getLength(); ++index) { // (4.2) Convert string to integer. int attrType; XMLChToVXIchar attributeName(attrs.getLocalName(index)); #pragma message("JC: This is a temporary hack!") if (Compare(attrs.getQName(index), L"xml:lang")) attrType = ATTRIBUTE_XMLLANG; else if (!ConvertAttribute(attributeName.c_str(), attrType)) { vxistring temp(L"unrecognized attribute - "); temp += attributeName.c_str(); ParseException(temp.c_str()); } // (4.3) Impose attribute restrictions not representable in schema 1.0. switch (elemType) { case NODE_AUDIO: if (attrType == ATTRIBUTE_SRC) ++attrGroup1; if (attrType == ATTRIBUTE_EXPR) ++attrGroup1; break; case NODE_CHOICE: case NODE_LINK: if (attrType == ATTRIBUTE_NEXT) ++attrGroup1; if (attrType == ATTRIBUTE_EXPR) ++attrGroup1; if (attrType == ATTRIBUTE_EVENT) ++attrGroup1; if (attrType == ATTRIBUTE_EVENTEXPR) ++attrGroup1; // and... if (attrType == ATTRIBUTE_MESSAGE) ++attrGroup2; if (attrType == ATTRIBUTE_MESSAGEEXPR) ++attrGroup2; break; case NODE_EXIT: if (attrType == ATTRIBUTE_EXPR) ++attrGroup1; if (attrType == ATTRIBUTE_NAMELIST) ++attrGroup1; break; case NODE_GOTO: if (attrType == ATTRIBUTE_NEXT) ++attrGroup1; if (attrType == ATTRIBUTE_EXPR) ++attrGroup1; if (attrType == ATTRIBUTE_NEXTITEM) ++attrGroup1; if (attrType == ATTRIBUTE_EXPRITEM) ++attrGroup1; break; case NODE_GRAMMAR: if (attrType == ATTRIBUTE_SRC) contentForbidden = true; break; case NODE_META: if (attrType == ATTRIBUTE_NAME) ++attrGroup1; if (attrType == ATTRIBUTE_HTTP_EQUIV) ++attrGroup1; break; case NODE_PARAM: if (attrType == ATTRIBUTE_EXPR) ++attrGroup1; if (attrType == ATTRIBUTE_VALUE) ++attrGroup1; break; case NODE_RETURN: if (attrType == ATTRIBUTE_EVENT) ++attrGroup1; if (attrType == ATTRIBUTE_EVENTEXPR) ++attrGroup1; if (attrType == ATTRIBUTE_NAMELIST) ++attrGroup1; // and... if (attrType == ATTRIBUTE_MESSAGE) ++attrGroup2; if (attrType == ATTRIBUTE_MESSAGEEXPR) ++attrGroup2; break; case NODE_SCRIPT: if (attrType == ATTRIBUTE_SRC) contentForbidden = true; break; case NODE_SUBDIALOG: if (attrType == ATTRIBUTE_SRC) ++attrGroup1; if (attrType == ATTRIBUTE_SRCEXPR) ++attrGroup1; break; case NODE_SUBMIT: if (attrType == ATTRIBUTE_NEXT) ++attrGroup1; if (attrType == ATTRIBUTE_EXPR) ++attrGroup1; break; case NODE_THROW: if (attrType == ATTRIBUTE_EVENT) ++attrGroup1; if (attrType == ATTRIBUTE_EVENTEXPR) ++attrGroup1; // and... if (attrType == ATTRIBUTE_MESSAGE) ++attrGroup2; if (attrType == ATTRIBUTE_MESSAGEEXPR) ++attrGroup2; break; case NODE_TRANSFER: if (attrType == ATTRIBUTE_DEST) ++attrGroup1; if (attrType == ATTRIBUTE_DESTEXPR) ++attrGroup1; // and... if (attrType == ATTRIBUTE_AAI) ++attrGroup2; if (attrType == ATTRIBUTE_AAIEXPR) ++attrGroup2; break; } // Handle base URI resolution and xml:lang for <prompt> & <grammar> switch (elemType) { case NODE_PROMPT: case NODE_GRAMMAR: if (attrType == ATTRIBUTE_XMLLANG) foundResourceBaseLang = true; else if (attrType == ATTRIBUTE_BASE) foundResourceBaseURI = true; else if (attrType == ATTRIBUTE_TYPE) { // set grammar type for this grammar element XMLChToVXIchar attributeValue(attrs.getValue(index)); SetGrammarType(attributeValue.c_str()); } break; case NODE_VXML: if (attrType == ATTRIBUTE_BASE) { XMLChToVXIchar attributeValue(attrs.getValue(index)); SetBaseUri(attributeValue.c_str()); continue; } else if (attrType == ATTRIBUTE_XMLLANG) { XMLChToVXIchar attributeValue(attrs.getValue(index)); documentLang = attributeValue.c_str(); continue; } break; case DEFAULTS_ROOT: if (attrType == ATTRIBUTE_XMLLANG) { XMLChToVXIchar attributeValue(attrs.getValue(index)); defaultLang = attributeValue.c_str(); documentLang = defaultLang; continue; } break; } // (4.5) Handle internal values. XMLChToVXIchar attributeValue(attrs.getValue(index)); ProcessNodeAttribute(elemType, attrType, attributeValue.c_str()); } // Use the default language for this document if necessary. if (elemType == NODE_VXML && documentLang.empty()) documentLang = defaultLang; // Assign an xml:base and/or xml:lang if not already specified for every // <grammar>, <prompt>, and <field> (because of builtins). if (elemType == NODE_PROMPT || elemType == NODE_GRAMMAR || elemType == NODE_FIELD || elemType == NODE_MENU) { if (!foundResourceBaseURI) doc->AddAttribute(ATTRIBUTE_BASE, baseUri.c_str()); if (!foundResourceBaseLang) doc->AddAttribute(ATTRIBUTE_XMLLANG, documentLang.c_str()); } // (5) Generate errors for attribute restrictions. switch (elemType) { case NODE_AUDIO: if (attrGroup1 != 1) ParseException(L"exactly one of 'src' or 'expr' must be specified"); break; case NODE_CHOICE: case NODE_LINK: if (attrGroup1 != 1) ParseException(L"exactly one of 'next', 'expr', 'event' or 'eventexpr' " L"must be specified"); if (attrGroup2 > 1) ParseException(L"exactly one of 'message' or 'messageexpr' " L"may be specified"); break; case NODE_EXIT: if (attrGroup1 > 1) ParseException(L"exactly one of 'expr' or 'namelist' " L"may be specified"); break; case NODE_GOTO: if (attrGroup1 != 1) ParseException(L"exactly one of 'next', 'expr', 'nextitem' or 'expritem'" L" must be specified"); break; case NODE_META: if (attrGroup1 != 1) ParseException(L"exactly one of 'name' or 'http-equiv' " L"must be specified"); break; case NODE_PARAM: if (attrGroup1 != 1) ParseException(L"exactly one of 'expr' or 'value' must be specified"); break; case NODE_RETURN: if (attrGroup1 > 1) ParseException(L"exactly one of 'event', 'eventexpr' or 'namelist' " L"may be specified"); if (attrGroup2 > 1) ParseException(L"exactly one of 'message' or 'messageexpr' " L"may be specified"); break; case NODE_SUBDIALOG: if (attrGroup1 != 1) ParseException(L"exactly one of 'src' or 'srcexpr' must be specified"); break; case NODE_SUBMIT: if (attrGroup1 != 1) ParseException(L"exactly one of 'next' or 'expr' must be specified"); break; case NODE_THROW: if (attrGroup1 != 1) ParseException(L"exactly one of 'event' or 'eventexpr' " L"must be specified"); if (attrGroup2 > 1) ParseException(L"exactly one of 'message' or 'messageexpr' " L"may be specified"); break; case NODE_TRANSFER: if (attrGroup1 > 1) ParseException(L"exactly one of 'dest' or 'destexpr' may be specified"); if (attrGroup2 > 1)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -