📄 parser.cpp
字号:
ProcessElementL(lex);
// consume '>' and start parsing free text
lex.Inc();
iCoreState = ECoreParsingFreeText;
lex.Mark();
continue;
case KLeftBracket:
// consume the '['
lex.Inc();
// compare the tag parsed so far to the CDATA start string
start_offs = lex.MarkedOffset() + 1;
ptr.Set(iDocument.Mid(start_offs, lex.Offset() - start_offs));
if( ptr.Compare(KCDataSectionStart) == 0 ) {
// yes, the element is a CDATA section
ProcessCDATASectionL(lex);
}
continue;
case KDash:
// comsume the '-'
lex.Inc();
// see if this is a comment
start_offs = lex.MarkedOffset() + 1;
ptr.Set(iDocument.Mid(start_offs, lex.Offset() - start_offs));
if( ptr.Compare(KCommentSectionStart) == 0 )
{
// yes, the element is a comment section
ProcessCommentSectionL(lex);
}
continue;
case KDoubleQuote:
in_string = !in_string;
break;
case KNewline:
// increment line number and let control enter default branch
iLineNum++;
default:
break;
}
// consume the character
lex.Inc();
}
}
void CEAXPParser::ProcessCommentSectionL( TLex& aLex )
{
TInt start_offs = aLex.MarkedOffset() + 1 + KCommentSectionStart().Length();
TPtrC comment;
// find the closing "-->"
while ( !aLex.Eos() )
{
if ( aLex.Peek() == KGreaterThan )
{
if( iDocument.Mid(aLex.Offset() - 2, 2).Compare(KCommentSectionEnd) == 0 )
{
comment.Set( iDocument.Mid( start_offs,
aLex.Offset() - 2 - start_offs) );
iListener.Comment( comment );
// consume the '>' and return
aLex.Inc();
aLex.Mark();
iCoreState = ECoreParsingFreeText;
return;
}
}
// consume the character
aLex.Inc();
}
}
void CEAXPParser::ProcessCDATASectionL(TLex &aLex)
{
TInt start_offs = aLex.MarkedOffset() + 1 + KCDataSectionStart().Length();
TPtrC sect;
while( !aLex.Eos() ) {
if( aLex.Peek() == KGreaterThan ) {
if( iDocument.Mid(aLex.Offset() - 2, 2).Compare(KCDataSectionEnd) == 0 ) {
// found the end of the CDATA section
sect.Set(iDocument.Mid(start_offs,
aLex.Offset() - 2 - start_offs));
//RDebug::Print(_L("CDATA: %S"), §);
iListener.FreeText(sect);
// consume the '>' and return
aLex.Inc();
aLex.Mark();
iCoreState = ECoreParsingFreeText;
return;
}
}
// consume the character
aLex.Inc();
}
}
void CEAXPParser::IllegalCharacterMetL(TChar aChar)
{
_LIT(KIllegalChar, "Illegal character '%c' (%d) on line %d!");
iErrorReason.Format(KIllegalChar, (TInt)aChar, (TInt)aChar, iLineNum);
User::Leave(KErrParsingError);
}
void CEAXPParser::ProcessElementL(const TLex &aLex)
{
TPtrC name, ns;
TInt start_offs = aLex.MarkedOffset() + 1;
TInt end_offs = aLex.Offset();
// extract the element tag
TPtrC element = iDocument.Mid(start_offs, (end_offs - start_offs));
RAttributeList attr_list;
// parse the element name/namespace
TInt name_end_offs = 0;
TPtrC elem_name_buf = FindElementNameL(element, name_end_offs);
//##TODO## assert that name != "/" (case: </ a>)
// if the element name starts with '?', then discard it
if( elem_name_buf[0] == KQuestionMark ) {
return;
}
if( elem_name_buf[0] == KSlash ) {
// this is the end element (</element>)
elem_name_buf.Set(elem_name_buf.Right(elem_name_buf.Length() - 1));
ParseNameL(elem_name_buf, name, ns);
iListener.EndElement(name, ns);
} else {
// check if the name already contains the end element -marker '/'
TBool end_element = EFalse;
if( elem_name_buf[elem_name_buf.Length() - 1] == KSlash ) {
elem_name_buf.Set(elem_name_buf.Left(elem_name_buf.Length() - 1));
end_element = ETrue;
}
// this is the start element (<element ...>)
ParseNameL(elem_name_buf, name, ns);
// locate && parse the attribute list
if( element.Length() > name_end_offs ) {
ParseAttributeListL(element.Right(element.Length() - name_end_offs), attr_list,
end_element);
}
iListener.StartElement(name, ns, attr_list);
// deallocate attribute list
attr_list.ResetAndDestroy();
if( end_element ) {
// the element closes immediately, too (<element .... />)
iListener.EndElement(name, ns);
}
}
}
TPtrC CEAXPParser::FindElementNameL(const TPtrC &aElement, TInt &aEndOffset)
{
TLex lex(aElement);
TInt end_offs;
// make sure there is a tag name in the first place
if( lex.Peek() == KWhitespace ) {
_LIT(KNameNotFound, "Name not found in element %S on line %d!");
iErrorReason.Format(KNameNotFound, &aElement, iLineNum);
User::Leave(KErrParsingError);
}
// by default, assume the tag name extends to the end of element
end_offs = aElement.Length();
// find the extends of the element name
while( !lex.Eos() ) {
TChar peek = lex.Peek();
switch( peek ) {
case KWhitespace:
case KNewline:
case KCarriageReturn:
// found the end of the element name
end_offs = lex.Offset();
// set lex to null string to stop parsing
lex.Assign(KNullDesC);
break;
case KEquals:
case KLessThan:
case KGreaterThan:
// illegal character met!
IllegalCharacterMetL(peek);
break;
default:
// ok character - skip to the next whitespace or end of string
lex.SkipCharacters();
continue;
}
// consume the character
lex.Inc();
}
aEndOffset = end_offs;
return aElement.Left(end_offs);
}
void CEAXPParser::ParseNameL(const TPtrC &aNameBuf, TPtrC &aName, TPtrC &aNamespace)
{
TInt sep_offs = aNameBuf.Locate(KColon);
if( sep_offs == KErrNotFound ) {
// namespace not defined (form: <name>)
aNamespace.Set(KNullDesC);
aName.Set(aNameBuf);
} else {
// namespace defined (form: <ns:name>) - validate both, name and namespace
if( (sep_offs == 0) || (sep_offs == (aNameBuf.Length() - 1)) ) {
_LIT(KBadElementName, "Bad element name '%S' on line %d!");
iErrorReason.Format(KBadElementName, &aNameBuf, iLineNum);
User::Leave(KErrParsingError);
}
aNamespace.Set(aNameBuf.Left(sep_offs));
aName.Set(aNameBuf.Right(aNameBuf.Length() - sep_offs - 1));
}
}
void CEAXPParser::ParseAttributeListL(const TPtrC &aAttrBuf, RAttributeList &aAttrList,
TBool &aEndElement)
{
_LIT(KBadSyntax, "Bad syntax on line %d!");
aEndElement = EFalse;
TLex lex(aAttrBuf);
TAttrParserState state = EAttrNullState;
TPtrC ptr;
TPtrC name, ns;
while( !lex.Eos() ) {
TChar peek = lex.Peek();
//RDebug::Print(_L("PEEK: %c"), (TInt)peek);
switch( peek ) {
case KTab:
case KWhitespace:
case KCarriageReturn:
case KNewline:
if( state == EAttrParsingAttrName ) {
IllegalCharacterMetL(peek);
return;
} else if( state != EAttrParsingAttrValue ) {
lex.SkipSpace();
state = EAttrNullState;
} else {
lex.Inc();
}
continue;
case KEquals:
// check state
if( (state == EAttrNullState) ) {
IllegalCharacterMetL(peek);
return;
}
if( state == EAttrParsingAttrValue ) {
lex.Inc();
break;
}
// end parsing attribute name
ptr.Set(aAttrBuf.Mid(lex.MarkedOffset(),
lex.Offset() - lex.MarkedOffset()));
ValidateSizeAndCopyL(&iAttrName, ptr);
// consume and peek for '"'
lex.Inc();
if( lex.Peek() != KDoubleQuote ) {
IllegalCharacterMetL(lex.Peek());
return;
} else {
// consume '"'
lex.Inc();
lex.Mark();
state = EAttrParsingAttrValue;
}
break;
case KDoubleQuote:
// check state
if( (state == EAttrNullState) || (state == EAttrParsingAttrName) ) {
IllegalCharacterMetL(peek);
return;
}
// end parsing attr value - add new entry
ptr.Set(aAttrBuf.Mid(lex.MarkedOffset(),
lex.Offset() - lex.MarkedOffset()));
UnescapeL(ptr);
ParseNameL(*iAttrName, name, ns);
aAttrList.Append(CAttribute::NewL(name, ns, *iUnescapeBuffer));
lex.Inc();
state = EAttrNullState;
break;
case KSlash:
if( state == EAttrNullState ) {
// end element -marker met
aEndElement = ETrue;
return;
}
// otherwise allow control proceed to default branch
default:
if( state == EAttrNullState ) {
// start parsing attribute name
state = EAttrParsingAttrName;
lex.Mark();
}
// consume character
lex.Inc();
break;
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -