void CXmlParser::ParseL(const TDesC& aDocument)
{
/*
* <xml><city name="beijing" code="010"/><person sex="boy">li ming</person></xml>
*/
if (iObserver == NULL)
{//不存在观察者
return;
}
TPtrC16 documentPtr(aDocument);
CDesCArrayFlat* tagStack = new (ELeave) CDesCArrayFlat(10);
RPointerArray<CXmlAttribute> attrArray;
while (documentPtr.Length() > 0)
{
TInt ltPos = documentPtr.Locate('<');
if (-1 == ltPos)
break;
if (ltPos > 0)
{//内容
TPtrC content(documentPtr.Left(ltPos));
if (tagStack->Count() > 0)
{//标签栈
iObserver->OnContent(content);
}
}
documentPtr.Set(documentPtr.Mid(ltPos));
TInt gtPos = documentPtr.Locate('>');
if (-1 == gtPos)
break;
if (documentPtr.Length() <= 1)
break;
TUint16 c = documentPtr[1];
switch (c)
{
case '/':
{//关闭标签
TPtrC tag(documentPtr.Mid(2, gtPos-2));
TInt count = tagStack->Count();
if (count-- > 0)
{
TPtrC tagTop((*tagStack)[count]);
if (tagTop.Compare(tag) == 0)
{
tagStack->Delete(count);
}
}
iObserver->OnElementEnd(tag);
break;
}
case '!':
{//可能是注释
break;
}
default:
{
if ((c >= 'A' && c <= 'Z' ) || (c >= 'a' && c <= 'z'))
{//以英文字母开头
TPtrC s(documentPtr.Mid(1, gtPos-1));
TPtrC tag, attribute;
attrArray.ResetAndDestroy();
TInt spacePos = s.Locate(' ');
if (-1 == spacePos)
{//没有属性
tag.Set(s);
}
else
{
tag.Set(s.Left(spacePos));
s.Set(s.Mid(spacePos));
while (s.Length() > 0)
{
if (s[0] != ' ')
{
spacePos = s.Locate(' ');
if (-1 == spacePos)
{
attribute.Set(s);
s.Set(KNullDesC);
}
else
{
attribute.Set(s.Left(spacePos));
s.Set(s.Mid(spacePos));
}
TInt equal = attribute.Locate('='),
quoteBegin = attribute.Locate('\"'),
quoteEnd = attribute.LocateReverse('\"');
if (-1 != equal &&
equal < quoteBegin &&
quoteBegin < quoteEnd)
{
CXmlAttribute* attr = new (ELeave) CXmlAttribute;
attr->SetNameL(attribute.Left(equal));
attr->SetValueL(attribute.Mid(quoteBegin+1, quoteEnd-quoteBegin-1));
attrArray.AppendL(attr);
}
}
else
{
s.Set(s.Right(s.Length()-1));
}
}
}
tagStack->AppendL(tag);
iObserver->OnElementStart(tag, attrArray);
if (documentPtr[gtPos-1] == '/')
{//关闭标签
tagStack->Delete(tagStack->Count()-1);
iObserver->OnElementEnd(tag);
}
}
break;
}
}
documentPtr.Set(documentPtr.Right(documentPtr.Length()-gtPos-1));
}
delete tagStack;
attrArray.ResetAndDestroy();
attrArray.Close();
{
/*
* <xml><city name="beijing" code="010"/><person sex="boy">li ming</person></xml>
*/
if (iObserver == NULL)
{//不存在观察者
return;
}
TPtrC16 documentPtr(aDocument);
CDesCArrayFlat* tagStack = new (ELeave) CDesCArrayFlat(10);
RPointerArray<CXmlAttribute> attrArray;
while (documentPtr.Length() > 0)
{
TInt ltPos = documentPtr.Locate('<');
if (-1 == ltPos)
break;
if (ltPos > 0)
{//内容
TPtrC content(documentPtr.Left(ltPos));
if (tagStack->Count() > 0)
{//标签栈
iObserver->OnContent(content);
}
}
documentPtr.Set(documentPtr.Mid(ltPos));
TInt gtPos = documentPtr.Locate('>');
if (-1 == gtPos)
break;
if (documentPtr.Length() <= 1)
break;
TUint16 c = documentPtr[1];
switch (c)
{
case '/':
{//关闭标签
TPtrC tag(documentPtr.Mid(2, gtPos-2));
TInt count = tagStack->Count();
if (count-- > 0)
{
TPtrC tagTop((*tagStack)[count]);
if (tagTop.Compare(tag) == 0)
{
tagStack->Delete(count);
}
}
iObserver->OnElementEnd(tag);
break;
}
case '!':
{//可能是注释
break;
}
default:
{
if ((c >= 'A' && c <= 'Z' ) || (c >= 'a' && c <= 'z'))
{//以英文字母开头
TPtrC s(documentPtr.Mid(1, gtPos-1));
TPtrC tag, attribute;
attrArray.ResetAndDestroy();
TInt spacePos = s.Locate(' ');
if (-1 == spacePos)
{//没有属性
tag.Set(s);
}
else
{
tag.Set(s.Left(spacePos));
s.Set(s.Mid(spacePos));
while (s.Length() > 0)
{
if (s[0] != ' ')
{
spacePos = s.Locate(' ');
if (-1 == spacePos)
{
attribute.Set(s);
s.Set(KNullDesC);
}
else
{
attribute.Set(s.Left(spacePos));
s.Set(s.Mid(spacePos));
}
TInt equal = attribute.Locate('='),
quoteBegin = attribute.Locate('\"'),
quoteEnd = attribute.LocateReverse('\"');
if (-1 != equal &&
equal < quoteBegin &&
quoteBegin < quoteEnd)
{
CXmlAttribute* attr = new (ELeave) CXmlAttribute;
attr->SetNameL(attribute.Left(equal));
attr->SetValueL(attribute.Mid(quoteBegin+1, quoteEnd-quoteBegin-1));
attrArray.AppendL(attr);
}
}
else
{
s.Set(s.Right(s.Length()-1));
}
}
}
tagStack->AppendL(tag);
iObserver->OnElementStart(tag, attrArray);
if (documentPtr[gtPos-1] == '/')
{//关闭标签
tagStack->Delete(tagStack->Count()-1);
iObserver->OnElementEnd(tag);
}
}
break;
}
}
documentPtr.Set(documentPtr.Right(documentPtr.Length()-gtPos-1));
}
delete tagStack;
attrArray.ResetAndDestroy();
attrArray.Close();
}