📄 documentconverter.cpp
字号:
doc->EndElement();
}
catch (const VXMLDocumentModel::InternalError &) {
ParseException(L"corrupted document tree; unable to complete element");
}
}
void DocumentConverter::characters(const XMLCh* const chars,
const unsigned int length)
{
// (0) Just ignore this?
if (chars == NULL || length == 0 || ignoreDepth > 0) return;
// (1) Ignore non-empty prompts consisting of pure whitespace
unsigned int l;
for (l = 0; l < length; ++l) {
XMLCh c = chars[l];
if (c == ' ' || c == '\n' || c == '\r' || c == '\t') continue;
break;
}
if (l == length) return;
// (2) Is this an implicit prompt?
if (pcdataImpliesPrompt && !explicitPrompt && !implicitPrompt && !inGrammar)
StartImplicitPrompt();
// (3) Add content to the document model.
try {
// This conversion should be safe. CDATA may only contain valid XML
// characters. These are defined in the XML 1.0 specification as the set
// 0x9, 0xA, 0xD, 0x20-0xD7FF, 0xE000-0xFFFD, 0x10000-0x10FFFF.
XMLChToVXIchar data(chars);
hasContent = true;
unsigned int start = 0;
unsigned int pos = 0;
VXIchar c;
// We need to escape two characters: (<,&) -> (<, &)
if((inGrammar && (GetGrammarType().empty() || GetGrammarType() == L"application/srgs+xml")) ||
(explicitPrompt || implicitPrompt)
)
{
do {
c = *(data.c_str() + pos);
if (c == L'<') {
if (start != pos)
doc->AddContent(data.c_str() + start, pos - start);
start = pos + 1;
doc->AddContent(L"<", 4);
}
else if (c == L'&') {
if (start != pos)
doc->AddContent(data.c_str() + start, pos - start);
start = pos + 1;
doc->AddContent(L"&", 5);
}
++pos;
} while (c != L'\0');
if (pos > start)
doc->AddContent(data.c_str() + start, pos - start - 1); // -1 to kill off final \0
} else {
doc->AddContent(data.c_str(), wcslen(data.c_str()));
}
}
catch (const VXMLDocumentModel::OutOfMemory &) {
ParseException(L"unable to allocate memory for content");
}
catch (const VXMLDocumentModel::InternalError &) {
ParseException(L"corrupted document tree; unable to add content");
}
}
void DocumentConverter::ignorableWhitespace(const XMLCh* const chars,
const unsigned int l)
{ }
void DocumentConverter::processingInstruction(const XMLCh* const target,
const XMLCh* const data)
{ }
//#############################################################################
void DocumentConverter::ProcessNodeAttribute(VXMLElementType elemType,
int attrType,
const VXIchar* const value)
{
// This shouldn't ever happen, if it does, we'll just ignore it.
if (value == NULL) return;
switch (elemType) {
case NODE_BLOCK:
case NODE_FIELD:
case NODE_INITIAL:
case NODE_OBJECT:
case NODE_RECORD:
case NODE_TRANSFER:
// We associate a hidden interal name with this element.
if (attrType == ATTRIBUTE_NAME) attrType = ATTRIBUTE__ITEMNAME;
break;
case NODE_CLEAR:
if (attrType == ATTRIBUTE_NAMELIST && !value[0])
ParseException(L"the namelist attribute on clear cannot be empty");
break;
case NODE_FORM:
case NODE_MENU:
// We associate a hidden interal name with this element.
if (attrType == ATTRIBUTE_ID) attrType = ATTRIBUTE__ITEMNAME;
break;
case NODE_FILLED:
if (doc->GetParentType() != NODE_FORM)
ParseException(L"attributes valid on filled only at form level");
if (attrType == ATTRIBUTE_NAMELIST && !value[0])
ParseException(L"the namelist attribute on filled cannot be empty");
break;
case NODE_GRAMMAR:
if (doc->GetParentType() != NODE_FORM && attrType == ATTRIBUTE_SCOPE)
ParseException(L"the scope attribute is valid only on grammars at form "
L"level");
break;
case NODE_SUBDIALOG:
// We associate a hidden interal name with this element.
if (attrType == ATTRIBUTE_NAME) attrType = ATTRIBUTE__ITEMNAME;
// modal was dropped in 2.0.
if (attrType == ATTRIBUTE_MODAL && version != 1.0f)
ParseException(L"the modal attribute on subdialog was dropped after "
L"1.0");
break;
case NODE_VALUE:
if (attrType == ATTRIBUTE_EXPR) break;
if (doc->GetParentType() == NODE_LOG)
ParseException(L"only the expr attribute is valid on value elements "
L"within a log element");
// #pragma message("JC: Obsolete???")
/*
if (doc->GetParentType() == NODE_SAYAS)
ParseException(L"only the expr attribute is valid on value elements "
L"within a say-as element");
*/
break;
case NODE_VXML:
// version is processed elsewhere and may be ignored.
if (attrType == ATTRIBUTE_VERSION) return;
if (attrType == PRIV_ATTRIB_SCHEMALOC) return;
break;
default:
break;
}
// (4.3) Add the attribute to the element.
if (attrType > PRIV_ATTRIB_RangeStart)
ParseException(L"internal error during attribute processing");
doc->AddAttribute(VXMLAttributeType(attrType), value);
}
void DocumentConverter::ProcessNodeFinal(VXMLElementType elemType)
{
// Convert attributes.
vxistring attr;
switch (elemType) {
case NODE_BLOCK:
case NODE_FIELD:
case NODE_FORM:
case NODE_INITIAL:
case NODE_MENU:
case NODE_OBJECT:
case NODE_RECORD:
case NODE_SUBDIALOG:
case NODE_TRANSFER:
// Name the 'unnamed' elements as neccessary.
if (!doc->GetAttribute(ATTRIBUTE__ITEMNAME, attr)) {
vxistring variable;
VXMLDocumentModel::CreateHiddenVariable(variable);
doc->AddAttribute(ATTRIBUTE__ITEMNAME, variable);
}
break;
case NODE_FILLED:
if (!doc->GetAttribute(ATTRIBUTE_MODE, attr))
doc->AddAttribute(ATTRIBUTE_MODE, L"all");
break;
case NODE_VXML:
case DEFAULTS_ROOT:
VXMLDocumentModel::CreateHiddenVariable(attr);
doc->AddAttribute(ATTRIBUTE__ITEMNAME, attr);
break;
default:
break;
}
// Generate DTMF sequences for <choice> elements in <menu> if necessary.
if (elemType == NODE_MENU) {
if (doc->GetAttribute(ATTRIBUTE_DTMF, attr) && attr == L"true")
choiceNumber = 1;
else
choiceNumber = 0;
}
if (elemType == NODE_CHOICE && choiceNumber > 0 && choiceNumber < 10 &&
!doc->GetAttribute(ATTRIBUTE_DTMF, attr))
{
std::basic_stringstream<VXIchar> countString;
countString << choiceNumber;
doc->AddAttribute(ATTRIBUTE_DTMF, countString.str());
++choiceNumber;
}
if (elemType == NODE_PROMPT) {
vxistring base, lang;
doc->GetAttribute(ATTRIBUTE_BASE, base);
doc->GetAttribute(ATTRIBUTE_XMLLANG, lang);
doc->AddContent(L"<?xml version='1.0'?><speak version='1.0' xmlns="
L"'http://www.w3.org/2001/10/synthesis' xml:base='", 96);
doc->AddContent(base.c_str(), base.length());
doc->AddContent(L"' xml:lang='", 12);
doc->AddContent(lang.c_str(), lang.length());
doc->AddContent(L"'>", 2);
}
}
void DocumentConverter::CopyElementStart(const XMLCh* const localname,
const Attributes &attrs)
{
++copyDepth;
doc->AddContent(L"<", 1);
XMLChToVXIchar data(localname);
doc->AddContent(data.c_str(), wcslen(data.c_str()));
for (unsigned int index = 0; index < attrs.getLength(); ++index) {
doc->AddContent(L" ", 1);
// Determine the attribute name
if (Compare(attrs.getQName(index), L"xml:lang"))
doc->AddContent(L"xml:lang", 8);
else {
XMLChToVXIchar name(attrs.getLocalName(index));
doc->AddContent(name.c_str(), wcslen(name.c_str()));
}
doc->AddContent(L"=\"", 2);
XMLChToVXIchar value(attrs.getValue(index));
unsigned int start = 0;
unsigned int pos = 0;
VXIchar c;
// We need to escape three characters: (<,>,&) -> (<,>,&)
do {
c = *(value.c_str() + pos);
if (c == L'<') {
if (start != pos)
doc->AddContent(value.c_str() + start, pos - start);
start = pos + 1;
doc->AddContent(L"<", 4);
}
else if (c == L'>') {
if (start != pos)
doc->AddContent(value.c_str() + start, pos - start);
start = pos + 1;
doc->AddContent(L">", 4);
}
else if (c == L'&') {
if (start != pos)
doc->AddContent(value.c_str() + start, pos - start);
start = pos + 1;
doc->AddContent(L"&", 5);
}
++pos;
} while (c != L'\0');
if (pos > start)
doc->AddContent(value.c_str() + start, pos - start - 1); // -1 to kill off final \0
doc->AddContent(L"\"", 1);
}
doc->AddContent(L">", 1);
}
void DocumentConverter::CopyElementClose(const XMLCh* const localname)
{
doc->AddContent(L"</", 2);
XMLChToVXIchar data(localname);
doc->AddContent(data.c_str(), wcslen(data.c_str()));
doc->AddContent(L">", 1);
--copyDepth;
}
void DocumentConverter::StartImplicitPrompt()
{
implicitPrompt = true;
doc->StartElement(NODE_PROMPT);
doc->AddContent(L"<?xml version='1.0'?><speak version='1.0' xmlns="
L"'http://www.w3.org/2001/10/synthesis' xml:base='", 96);
doc->AddContent(baseUri.c_str(), baseUri.length());
doc->AddContent(L"' xml:lang='", 12);
doc->AddContent(documentLang.c_str(), documentLang.length());
doc->AddContent(L"'>", 2);
copyDepth = 0;
}
void DocumentConverter::EndImplicitPrompt()
{
doc->AddContent(L"</speak>", 8);
doc->EndElement();
implicitPrompt = false;
}
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -