|
1 /* |
|
2 * Copyright (c) 2003 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: Implementation of CXmlPullParser. |
|
15 * |
|
16 */ |
|
17 |
|
18 |
|
19 |
|
20 #include <eikenv.h> |
|
21 #include <e32std.h> |
|
22 #include <e32des8.h> |
|
23 #include "XppImpl.h" |
|
24 |
|
25 const TInt KExtraPunctuation = 5; |
|
26 const TInt KBufSizeIncrement = 1024; |
|
27 const TInt KBufInitSize = 2048; |
|
28 |
|
29 // |
|
30 // Common literal text |
|
31 // |
|
32 _LIT8(KOpenBracket, "<"); |
|
33 _LIT8(KCloseBracket, ">"); |
|
34 //_LIT8(KStartEndTag, "</"); |
|
35 //_LIT8(KCloseTag, "/>"); |
|
36 _LIT8(KSpace, " "); |
|
37 _LIT8(KEquals, "="); |
|
38 _LIT8(KSlash, "/"); |
|
39 _LIT8(KSingleQuote, "\'"); |
|
40 _LIT8(KDoubleQuote, "\""); |
|
41 //_LIT8(KQuestionMark, "?"); |
|
42 //_LIT8(KExclamationMark, "!"); |
|
43 //_LIT8(KOpenCurlyBracket, "{"); |
|
44 //_LIT8(KCloseCurlyBracket, "}"); |
|
45 //_LIT8(KHyphen, "-"); |
|
46 _LIT8(KOpenAngleBracket , "["); |
|
47 _LIT8(KCloseAngleBracket, "]"); |
|
48 |
|
49 _LIT8(KAmpersand, "&"); |
|
50 _LIT8(KAmpersandHash, "&#"); |
|
51 _LIT8(KSemicolon, ";"); |
|
52 |
|
53 // XML special marks |
|
54 //_LIT8(KStartXmlProlog, "<?xml"); |
|
55 //_LIT8(KStartComment, "<!--"); |
|
56 _LIT8(KEndComment, "-->"); |
|
57 //_LIT8(KStartProcessingInstructions, "<?"); |
|
58 _LIT8(KEndPIAndProlog, "?>"); |
|
59 _LIT8(KStartCData, "<![CDATA["); |
|
60 _LIT8(KEndCData, "]]>"); |
|
61 //_LIT8(KStartDocType, "<!DOCTYPE"); |
|
62 //_LIT8(KStartElement, "<!ELEMENT"); |
|
63 //_LIT8(KStartAttList, "<!ATTLIST"); |
|
64 //_LIT8(KStartEntity, "<!ENTITY"); |
|
65 //_LIT8(KStartNotation, "<!NOTATION"); |
|
66 //_LIT8(KEndCdata, "]]>"); |
|
67 |
|
68 _LIT8(KEntityLowerThan, "<"); // < |
|
69 _LIT8(KEntityGreaterThan, ">"); // > |
|
70 _LIT8(KEntityAmpersand, "&"); // & |
|
71 _LIT8(KEntityApostrophe, "'"); // ' |
|
72 _LIT8(KEntityQuotation, """); // " |
|
73 |
|
74 |
|
75 //////////////////////////////////////////////////////////////////////////////////////// |
|
76 // |
|
77 //////////////////////////////////////////////////////////////////////////////////////// |
|
78 CXmlPullParser::CXmlPullParser() |
|
79 : iState(EStateStartDocument), iCurrentElementPos(0), iPathBufPtr(NULL, 0), iDepth(0), |
|
80 iIsEmptyElement(EFalse), iCdataStartFound(EFalse), iCdataSectionText(EFalse), |
|
81 iStringValuePtr(NULL, 0), iStringValueArray(NULL) |
|
82 { |
|
83 } |
|
84 |
|
85 //////////////////////////////////////////////////////////////////////////////////////// |
|
86 // |
|
87 //////////////////////////////////////////////////////////////////////////////////////// |
|
88 // NewLC with two stage construction |
|
89 EXPORT_C CXmlPullParser* CXmlPullParser::NewLC(CDesC8ArrayFlat& aStringValueArray) |
|
90 { |
|
91 // get new, leave if can't |
|
92 CXmlPullParser* self = new (ELeave) CXmlPullParser(); |
|
93 // push onto cleanup stack in case self->ConstructL leaves |
|
94 CleanupStack::PushL(self); |
|
95 // complete construction with second phase constructor |
|
96 self->ConstructL(aStringValueArray); |
|
97 return self; |
|
98 } |
|
99 |
|
100 //////////////////////////////////////////////////////////////////////////////////////// |
|
101 // |
|
102 //////////////////////////////////////////////////////////////////////////////////////// |
|
103 EXPORT_C CXmlPullParser* CXmlPullParser::NewL(CDesC8ArrayFlat& aStringValueArray) |
|
104 { |
|
105 CXmlPullParser* self=NewLC(aStringValueArray); |
|
106 CleanupStack::Pop(); |
|
107 return self; |
|
108 } |
|
109 |
|
110 //////////////////////////////////////////////////////////////////////////////////////// |
|
111 // |
|
112 //////////////////////////////////////////////////////////////////////////////////////// |
|
113 void CXmlPullParser::ConstructL(CDesC8ArrayFlat& aStringValueArray) |
|
114 { |
|
115 iPathBuf = HBufC8::NewMaxL(KBufInitSize); |
|
116 iPathBufPtr.Set(iPathBuf->Des()); |
|
117 iPathBufPtr.SetLength(0); // Otherwise the Length is set to KBufInitSize |
|
118 iCAttrDataArray = new (ELeave) CArrayFixFlat<TAttrData>(1); |
|
119 iStringValue = HBufC8::NewMaxL(KBufInitSize); |
|
120 iStringValuePtr.Set(iStringValue->Des()); |
|
121 iStringValuePtr.SetLength(0); // Otherwise the Length is set to KBufInitSize |
|
122 //iStringValueArray = new (ELeave) CDesC8ArrayFlat(1); |
|
123 iStringValueArray = &aStringValueArray; |
|
124 } |
|
125 |
|
126 //////////////////////////////////////////////////////////////////////////////////////// |
|
127 // |
|
128 //////////////////////////////////////////////////////////////////////////////////////// |
|
129 CXmlPullParser::~CXmlPullParser() |
|
130 { |
|
131 delete (iPathBuf); |
|
132 delete iCAttrDataArray; |
|
133 delete (iStringValue); |
|
134 //delete iStringValueArray; |
|
135 } |
|
136 |
|
137 |
|
138 //////////////////////////////////////////////////////////////////////////////////////// |
|
139 // |
|
140 //////////////////////////////////////////////////////////////////////////////////////// |
|
141 void CXmlPullParser::CheckSpaceL(const TDesC8& aText) |
|
142 { |
|
143 TInt spaceLeft = iPathBufPtr.MaxLength() - iPathBufPtr.Length() - KExtraPunctuation; |
|
144 if (aText.Length() > spaceLeft) |
|
145 { |
|
146 TInt newMaxLength = iPathBufPtr.MaxLength() + aText.Length() + KBufSizeIncrement; |
|
147 iPathBuf = iPathBuf->ReAllocL(newMaxLength); |
|
148 iPathBufPtr.Set(iPathBuf->Des()); |
|
149 } |
|
150 } |
|
151 |
|
152 |
|
153 //////////////////////////////////////////////////////////////////////////////////////// |
|
154 // |
|
155 //////////////////////////////////////////////////////////////////////////////////////// |
|
156 EXPORT_C void CXmlPullParser::SetInput(const TDesC8& aInput) |
|
157 { |
|
158 iState = EStateStartDocument; |
|
159 iText.Set(KNullDesC8); |
|
160 iCAttrDataArray->Delete(0, iCAttrDataArray->Count()); |
|
161 iDocument.Set(aInput); |
|
162 iDocPart.Set(KNullDesC8); |
|
163 iLexer.Assign(aInput); // Assigns a string to this object from a descriptor |
|
164 iCurrentElementPos = 0; |
|
165 iPathBufPtr.Zero(); |
|
166 iElement.Set(KNullDesC8); |
|
167 iDepth = 0; |
|
168 iIsEmptyElement = EFalse; |
|
169 iCdataStartFound = EFalse; |
|
170 iCdataSectionText = EFalse; |
|
171 } |
|
172 |
|
173 //////////////////////////////////////////////////////////////////////////////////////// |
|
174 // |
|
175 //////////////////////////////////////////////////////////////////////////////////////// |
|
176 EXPORT_C TInt CXmlPullParser::NextL() |
|
177 { |
|
178 TInt rv; |
|
179 |
|
180 switch (iState) |
|
181 { |
|
182 case EStateStartDocument: |
|
183 // skip |
|
184 if ((rv = SkipLeadingNonRelevantElements()) == ERcDocumentError) |
|
185 { |
|
186 return rv; |
|
187 } |
|
188 else |
|
189 { |
|
190 iCurrentElementPos = iLexer.Offset(); |
|
191 rv = GetElementStartTagL(); |
|
192 return rv; |
|
193 } |
|
194 //break; |
|
195 |
|
196 case EStateStartTag: |
|
197 // skip |
|
198 if ((rv = SkipNonRelevantElements()) == ERcDocumentError) |
|
199 { |
|
200 return rv; |
|
201 } |
|
202 else |
|
203 { |
|
204 iCurrentElementPos = iLexer.Offset(); |
|
205 if (iIsEmptyElement) |
|
206 { |
|
207 // delete /end tag from the iPathBuf |
|
208 // this is done by subtracting the length of the buffer |
|
209 iPathBufPtr.SetLength(iPathBufPtr.LocateReverse('/')); |
|
210 |
|
211 // decrement iDepth |
|
212 iDepth--; |
|
213 |
|
214 // if we have an XML-document that is only one empty-element |
|
215 // then we must check if we are already in the end of the document |
|
216 if (CheckIfEndOfFile()) |
|
217 { |
|
218 return KErrNone; |
|
219 } |
|
220 } |
|
221 if (CheckIfNextEndTag()) // Check iState!! |
|
222 { |
|
223 if (iState == EStateError) |
|
224 { |
|
225 return ERcDocumentError; |
|
226 } |
|
227 else |
|
228 { |
|
229 rv = GetElementEndTag(); |
|
230 return rv; |
|
231 } |
|
232 } |
|
233 else if (CheckIfNextStartTag()) // Check iState!! |
|
234 { |
|
235 if (iState == EStateError) |
|
236 { |
|
237 return ERcDocumentError; |
|
238 } |
|
239 else |
|
240 { |
|
241 rv = GetElementStartTagL(); |
|
242 return rv; |
|
243 } |
|
244 } |
|
245 else // etext |
|
246 { |
|
247 rv = GetElementText(); |
|
248 return rv; |
|
249 } |
|
250 } |
|
251 //break; |
|
252 |
|
253 case EStateText: |
|
254 // skip |
|
255 if ((rv = SkipNonRelevantElements()) == ERcDocumentError) |
|
256 { |
|
257 return rv; |
|
258 } |
|
259 else |
|
260 { |
|
261 iCurrentElementPos = iLexer.Offset(); |
|
262 if (iState == EStateEndDocument) |
|
263 { |
|
264 // in EStateText we can not be in the end of the xml-document |
|
265 iState = EStateError; |
|
266 return ERcDocumentError; |
|
267 } |
|
268 |
|
269 if (iCdataStartFound) |
|
270 { |
|
271 rv = GetElementText(); |
|
272 return rv; |
|
273 } |
|
274 else |
|
275 { |
|
276 if (CheckIfNextEndTag()) // Check iState!! |
|
277 { |
|
278 if (iState == EStateError) |
|
279 { |
|
280 return ERcDocumentError; |
|
281 } |
|
282 else |
|
283 { |
|
284 // get end tag |
|
285 rv = GetElementEndTag(); |
|
286 return rv; |
|
287 } |
|
288 } |
|
289 else if (CheckIfNextStartTag()) // Check iState!! |
|
290 { |
|
291 if (iState == EStateError) |
|
292 { |
|
293 return ERcDocumentError; |
|
294 } |
|
295 else |
|
296 { |
|
297 // get start tag |
|
298 rv = GetElementStartTagL(); |
|
299 return rv; |
|
300 } |
|
301 } |
|
302 else // etext |
|
303 { |
|
304 // get text |
|
305 rv = GetElementText(); |
|
306 return rv; |
|
307 } |
|
308 } |
|
309 } |
|
310 //break; |
|
311 |
|
312 case EStateEndTag: |
|
313 // after end tag can be end of file, new start tag, new end tag or etext |
|
314 // skip |
|
315 if ((rv = SkipNonRelevantElements()) == ERcDocumentError) |
|
316 { |
|
317 return rv; |
|
318 } |
|
319 else |
|
320 { |
|
321 iCurrentElementPos = iLexer.Offset(); |
|
322 if (CheckIfEndOfFile()) |
|
323 { |
|
324 return KErrNone; |
|
325 } |
|
326 else |
|
327 { |
|
328 if (CheckIfNextStartTag()) // Check iState |
|
329 { |
|
330 if (iState == EStateError) |
|
331 { |
|
332 return ERcDocumentError; |
|
333 } |
|
334 else |
|
335 { |
|
336 rv = GetElementStartTagL(); |
|
337 return rv; |
|
338 } |
|
339 } |
|
340 else if (CheckIfNextEndTag()) // Check iState!! |
|
341 { |
|
342 if (iState == EStateError) |
|
343 { |
|
344 return ERcDocumentError; |
|
345 } |
|
346 else |
|
347 { |
|
348 rv = GetElementEndTag(); |
|
349 return rv; |
|
350 } |
|
351 } |
|
352 else // etext |
|
353 { |
|
354 // get text |
|
355 rv = GetElementText(); |
|
356 return rv; |
|
357 } |
|
358 } |
|
359 } |
|
360 |
|
361 //break; |
|
362 case EStateEndDocument: |
|
363 return ERcWrongParserState; |
|
364 //break; |
|
365 case EStateError: |
|
366 return ERcWrongParserState; |
|
367 //break; |
|
368 default: |
|
369 return ERcUnknown; // all the States are handled above |
|
370 //break; |
|
371 } |
|
372 } |
|
373 |
|
374 //////////////////////////////////////////////////////////////////////////////////////// |
|
375 // |
|
376 //////////////////////////////////////////////////////////////////////////////////////// |
|
377 EXPORT_C CXmlPullParser::TParserState CXmlPullParser::State() |
|
378 { |
|
379 return iState; |
|
380 } |
|
381 |
|
382 //////////////////////////////////////////////////////////////////////////////////////// |
|
383 // |
|
384 //////////////////////////////////////////////////////////////////////////////////////// |
|
385 EXPORT_C TInt CXmlPullParser::Name(TPtrC8& aName) |
|
386 { |
|
387 if ((iState == EStateStartTag) || |
|
388 (iState == EStateText) || |
|
389 (iState == EStateEndTag) || |
|
390 (iState == EStateEndDocument)) |
|
391 { |
|
392 aName.Set(iElement); |
|
393 return KErrNone; |
|
394 } |
|
395 else |
|
396 { |
|
397 return ERcWrongParserState; |
|
398 } |
|
399 } |
|
400 |
|
401 //////////////////////////////////////////////////////////////////////////////////////// |
|
402 // |
|
403 //////////////////////////////////////////////////////////////////////////////////////// |
|
404 EXPORT_C TInt CXmlPullParser::PathL(TPtrC8& aPath) |
|
405 { |
|
406 if ((iState == EStateStartTag) || |
|
407 (iState == EStateText) || |
|
408 (iState == EStateEndTag)) |
|
409 { |
|
410 aPath.Set(iPathBufPtr); |
|
411 return KErrNone; |
|
412 } |
|
413 else |
|
414 { |
|
415 return ERcWrongParserState; |
|
416 } |
|
417 } |
|
418 |
|
419 //////////////////////////////////////////////////////////////////////////////////////// |
|
420 // |
|
421 //////////////////////////////////////////////////////////////////////////////////////// |
|
422 EXPORT_C TInt CXmlPullParser::Depth(TInt& aDepth) |
|
423 { |
|
424 if ((iState == EStateStartTag) || |
|
425 (iState == EStateText) || |
|
426 (iState == EStateEndTag)) |
|
427 { |
|
428 aDepth = iDepth; |
|
429 return KErrNone; |
|
430 } |
|
431 else |
|
432 { |
|
433 return ERcWrongParserState; |
|
434 } |
|
435 } |
|
436 |
|
437 //////////////////////////////////////////////////////////////////////////////////////// |
|
438 // |
|
439 //////////////////////////////////////////////////////////////////////////////////////// |
|
440 EXPORT_C TInt CXmlPullParser::AttributeCount(TInt& aCount) |
|
441 { |
|
442 if (iState == EStateStartTag) |
|
443 { |
|
444 aCount = iCAttrDataArray->Count(); |
|
445 return KErrNone; |
|
446 } |
|
447 else |
|
448 { |
|
449 return ERcWrongParserState; |
|
450 } |
|
451 } |
|
452 |
|
453 //////////////////////////////////////////////////////////////////////////////////////// |
|
454 // |
|
455 //////////////////////////////////////////////////////////////////////////////////////// |
|
456 EXPORT_C TInt CXmlPullParser::AttributeName(TInt aIndex, TPtrC8& aName) |
|
457 { |
|
458 if (iState == EStateStartTag) |
|
459 { |
|
460 if ((aIndex < iCAttrDataArray->Count()) && (aIndex >= 0)) |
|
461 { |
|
462 aName.Set(iCAttrDataArray->At(aIndex).iName); |
|
463 return KErrNone; |
|
464 } |
|
465 else |
|
466 { |
|
467 return KErrNotFound; |
|
468 } |
|
469 } |
|
470 else |
|
471 { |
|
472 return ERcWrongParserState; |
|
473 } |
|
474 } |
|
475 |
|
476 //////////////////////////////////////////////////////////////////////////////////////// |
|
477 // |
|
478 //////////////////////////////////////////////////////////////////////////////////////// |
|
479 EXPORT_C TInt CXmlPullParser::AttributeValuePredefEntitiesNotEscaped(TInt aIndex, TPtrC8& aValue) |
|
480 { |
|
481 if (iState == EStateStartTag) |
|
482 { |
|
483 if ((aIndex < iCAttrDataArray->Count()) && (aIndex >= 0)) |
|
484 { |
|
485 aValue.Set(iCAttrDataArray->At(aIndex).iValue); |
|
486 return KErrNone; |
|
487 } |
|
488 else |
|
489 { |
|
490 return KErrNotFound; |
|
491 } |
|
492 } |
|
493 else |
|
494 { |
|
495 return ERcWrongParserState; |
|
496 } |
|
497 } |
|
498 |
|
499 //////////////////////////////////////////////////////////////////////////////////////// |
|
500 // |
|
501 //////////////////////////////////////////////////////////////////////////////////////// |
|
502 EXPORT_C TInt CXmlPullParser::AttributeValuePredefEntitiesNotEscaped(const TDesC8& aName, TPtrC8& aValue) |
|
503 { |
|
504 TInt count; |
|
505 TInt index = 0; |
|
506 if (iState == EStateStartTag) |
|
507 { |
|
508 count = iCAttrDataArray->Count(); |
|
509 while (index < count) |
|
510 { |
|
511 if (iCAttrDataArray->At(index).iName == aName) |
|
512 { |
|
513 aValue.Set(iCAttrDataArray->At(index).iValue); |
|
514 return KErrNone; |
|
515 } |
|
516 else |
|
517 { |
|
518 index ++; |
|
519 } |
|
520 } |
|
521 return KErrNotFound; |
|
522 } |
|
523 else |
|
524 { |
|
525 return ERcWrongParserState; |
|
526 } |
|
527 } |
|
528 |
|
529 |
|
530 //////////////////////////////////////////////////////////////////////////////////////// |
|
531 // |
|
532 //////////////////////////////////////////////////////////////////////////////////////// |
|
533 EXPORT_C TInt CXmlPullParser::AttributeValueL(TInt aIndex, TPtrC8& aValue) |
|
534 { |
|
535 TInt ret; |
|
536 ret = AttributeValuePredefEntitiesNotEscaped(aIndex, aValue); |
|
537 |
|
538 if (ret == KErrNone) |
|
539 { |
|
540 CheckStringValueBufferSpaceL(aValue); |
|
541 |
|
542 iStringValuePtr = aValue; |
|
543 |
|
544 if ( (ret = EscapeCharRefAndPreDefEntities()) != KErrNone ) |
|
545 { |
|
546 return ret; |
|
547 } |
|
548 else |
|
549 { |
|
550 iStringValueArray->AppendL(iStringValuePtr); |
|
551 aValue.Set(iStringValueArray->MdcaPoint(iStringValueArray->MdcaCount()-1)); |
|
552 return KErrNone; |
|
553 } |
|
554 } |
|
555 else |
|
556 { |
|
557 return ret; |
|
558 } |
|
559 } |
|
560 |
|
561 |
|
562 //////////////////////////////////////////////////////////////////////////////////////// |
|
563 // |
|
564 //////////////////////////////////////////////////////////////////////////////////////// |
|
565 EXPORT_C TInt CXmlPullParser::AttributeValueL(const TDesC8& aName, TPtrC8& aValue) |
|
566 { |
|
567 TInt ret; |
|
568 ret = AttributeValuePredefEntitiesNotEscaped(aName, aValue); |
|
569 |
|
570 if (ret == KErrNone) |
|
571 { |
|
572 CheckStringValueBufferSpaceL(aValue); |
|
573 |
|
574 iStringValuePtr = aValue; |
|
575 |
|
576 if ( (ret = EscapeCharRefAndPreDefEntities()) != KErrNone ) |
|
577 { |
|
578 return ret; |
|
579 } |
|
580 else |
|
581 { |
|
582 iStringValueArray->AppendL(iStringValuePtr); |
|
583 aValue.Set(iStringValueArray->MdcaPoint(iStringValueArray->MdcaCount()-1)); |
|
584 return KErrNone; |
|
585 } |
|
586 } |
|
587 else |
|
588 { |
|
589 return ret; |
|
590 } |
|
591 } |
|
592 |
|
593 //////////////////////////////////////////////////////////////////////////////////////// |
|
594 // |
|
595 //////////////////////////////////////////////////////////////////////////////////////// |
|
596 void CXmlPullParser::CheckStringValueBufferSpaceL(const TDesC8& aValue) |
|
597 { |
|
598 TInt newLength = aValue.Length(); |
|
599 if ( newLength > (iStringValuePtr.MaxLength()) ) |
|
600 { |
|
601 iStringValue = iStringValue->ReAllocL(newLength); |
|
602 iStringValuePtr.Set(iStringValue->Des()); |
|
603 } |
|
604 } |
|
605 |
|
606 //////////////////////////////////////////////////////////////////////////////////////// |
|
607 // |
|
608 //////////////////////////////////////////////////////////////////////////////////////// |
|
609 EXPORT_C TInt CXmlPullParser::IsEmptyElement(TBool& aIsEmptyElement) |
|
610 { |
|
611 if (iState == EStateStartTag) |
|
612 { |
|
613 aIsEmptyElement = iIsEmptyElement; |
|
614 return KErrNone; |
|
615 } |
|
616 else |
|
617 { |
|
618 return ERcWrongParserState; |
|
619 } |
|
620 } |
|
621 |
|
622 //////////////////////////////////////////////////////////////////////////////////////// |
|
623 // |
|
624 //////////////////////////////////////////////////////////////////////////////////////// |
|
625 EXPORT_C TInt CXmlPullParser::TextPredefEntitiesNotEscaped(TPtrC8& aText) |
|
626 { |
|
627 if (iState == EStateText) |
|
628 { |
|
629 aText.Set(iText); |
|
630 return KErrNone; |
|
631 } |
|
632 else |
|
633 { |
|
634 return ERcWrongParserState; |
|
635 } |
|
636 } |
|
637 |
|
638 //////////////////////////////////////////////////////////////////////////////////////// |
|
639 // |
|
640 //////////////////////////////////////////////////////////////////////////////////////// |
|
641 EXPORT_C TInt CXmlPullParser::TextL(TPtrC8& aText) |
|
642 { |
|
643 TInt ret; |
|
644 ret = TextPredefEntitiesNotEscaped(aText); |
|
645 |
|
646 if (ret == KErrNone) |
|
647 { |
|
648 CheckStringValueBufferSpaceL(aText); |
|
649 |
|
650 iStringValuePtr = aText; |
|
651 |
|
652 if ( !(iCdataSectionText) ) |
|
653 { |
|
654 if ( (ret = EscapeCharRefAndPreDefEntities()) != KErrNone ) |
|
655 { |
|
656 return ret; |
|
657 } |
|
658 else |
|
659 { |
|
660 iStringValueArray->AppendL(iStringValuePtr); |
|
661 aText.Set(iStringValueArray->MdcaPoint(iStringValueArray->MdcaCount()-1)); |
|
662 } |
|
663 } |
|
664 return KErrNone; |
|
665 } |
|
666 else |
|
667 { |
|
668 return ret; |
|
669 } |
|
670 } |
|
671 |
|
672 |
|
673 //////////////////////////////////////////////////////////////////////////////////////// |
|
674 // |
|
675 //////////////////////////////////////////////////////////////////////////////////////// |
|
676 EXPORT_C TInt CXmlPullParser::Pos() |
|
677 { |
|
678 return iLexer.Offset(); |
|
679 } |
|
680 |
|
681 //////////////////////////////////////////////////////////////////////////////////////// |
|
682 // |
|
683 //////////////////////////////////////////////////////////////////////////////////////// |
|
684 EXPORT_C TInt CXmlPullParser::CurrentElementPos() |
|
685 { |
|
686 return iCurrentElementPos; |
|
687 } |
|
688 |
|
689 //////////////////////////////////////////////////////////////////////////////////////// |
|
690 // |
|
691 //////////////////////////////////////////////////////////////////////////////////////// |
|
692 EXPORT_C TInt CXmlPullParser::Length() |
|
693 { |
|
694 return iDocument.Length(); |
|
695 } |
|
696 |
|
697 //////////////////////////////////////////////////////////////////////////////////////// |
|
698 // |
|
699 //////////////////////////////////////////////////////////////////////////////////////// |
|
700 EXPORT_C TPtrC8 CXmlPullParser::DocPart(TInt aStartPos, TInt aEndPos) |
|
701 { |
|
702 iDocPart.Set(iDocument.Mid(aStartPos, (aEndPos - aStartPos + 1))); |
|
703 return iDocPart; |
|
704 } |
|
705 |
|
706 //////////////////////////////////////////////////////////////////////////////////////// |
|
707 // |
|
708 //////////////////////////////////////////////////////////////////////////////////////// |
|
709 TInt CXmlPullParser::SkipLeadingNonRelevantElements() |
|
710 { |
|
711 TPtrC8 token; |
|
712 TInt endStringOffset; |
|
713 TBool prologFound = ETrue; |
|
714 TBool commentFound = ETrue; |
|
715 TBool piFound = ETrue; |
|
716 TBool dtdFound = ETrue; |
|
717 |
|
718 iLexer.SkipSpaceAndMark(iMarkPosition); // Remember where we are |
|
719 |
|
720 if (iLexer.Eos()) |
|
721 { |
|
722 iState = EStateEndDocument; |
|
723 return KErrNone; |
|
724 } |
|
725 else |
|
726 { |
|
727 token.Set(iLexer.Remainder()); // pointer to the rest of the xml document |
|
728 |
|
729 while (prologFound || commentFound || piFound || dtdFound) |
|
730 { |
|
731 // check for prolog: if prolog found skip it |
|
732 if (iLexer.Get() == '<' && iLexer.Get() == '?' && |
|
733 iLexer.Get() == 'x' && iLexer.Get() == 'm' && iLexer.Get() == 'l') |
|
734 { |
|
735 token.Set(iLexer.Remainder()); // pointer to the rest of the xml document |
|
736 if (token.Find(KEndPIAndProlog) != KErrNotFound) |
|
737 { |
|
738 endStringOffset = token.Find(KEndPIAndProlog) + KEndPIAndProlog().Length(); |
|
739 iLexer.Inc(endStringOffset); |
|
740 iLexer.SkipSpaceAndMark(iMarkPosition); // Remember where we are |
|
741 prologFound = ETrue; |
|
742 } |
|
743 else |
|
744 { |
|
745 iState = EStateError; |
|
746 return ERcDocumentError; // no end string found |
|
747 } |
|
748 } |
|
749 else |
|
750 { |
|
751 iLexer.UnGetToMark(iMarkPosition); |
|
752 prologFound = EFalse; |
|
753 } |
|
754 |
|
755 // check for comment: if found skip it |
|
756 if (iLexer.Get() == '<' && iLexer.Get() == '!' && |
|
757 iLexer.Get() == '-' && iLexer.Get() == '-') |
|
758 { |
|
759 token.Set(iLexer.Remainder()); // pointer to the rest of the xml document |
|
760 if (token.Find(KEndComment) != KErrNotFound) |
|
761 { |
|
762 endStringOffset = token.Find(KEndComment) + KEndComment().Length(); |
|
763 iLexer.Inc(endStringOffset); |
|
764 iLexer.SkipSpaceAndMark(iMarkPosition); // Remember where we are |
|
765 commentFound = ETrue; |
|
766 } |
|
767 else |
|
768 { |
|
769 iState = EStateError; |
|
770 return ERcDocumentError; // no end string found |
|
771 } |
|
772 } |
|
773 else |
|
774 { |
|
775 iLexer.UnGetToMark(iMarkPosition); |
|
776 commentFound = EFalse; |
|
777 } |
|
778 |
|
779 // check for processing instructions: if found skip it |
|
780 if (iLexer.Get() == '<' && iLexer.Get() == '?') |
|
781 { |
|
782 token.Set(iLexer.Remainder()); // pointer to the rest of the xml document |
|
783 if (token.Find(KEndPIAndProlog) != KErrNotFound) |
|
784 { |
|
785 endStringOffset = token.Find(KEndPIAndProlog) + KEndPIAndProlog().Length(); |
|
786 iLexer.Inc(endStringOffset); |
|
787 iLexer.SkipSpaceAndMark(iMarkPosition); // Remember where we are |
|
788 piFound = ETrue; |
|
789 } |
|
790 else |
|
791 { |
|
792 iState = EStateError; |
|
793 return ERcDocumentError; // no end string found |
|
794 } |
|
795 } |
|
796 else |
|
797 { |
|
798 iLexer.UnGetToMark(iMarkPosition); |
|
799 piFound = EFalse; |
|
800 } |
|
801 |
|
802 // check for document type declaration: if found skip it |
|
803 if (iLexer.Get() == '<' && iLexer.Get() == '!' && |
|
804 iLexer.Get() == 'D' && iLexer.Get() == 'O' && |
|
805 iLexer.Get() == 'C' && iLexer.Get() == 'T' && |
|
806 iLexer.Get() == 'Y' && iLexer.Get() == 'P' && |
|
807 iLexer.Get() == 'E') |
|
808 { |
|
809 token.Set(iLexer.Remainder()); // pointer to the rest of the xml document |
|
810 // if '[' found skip to ']' and then search for '>' (= end of doctype) |
|
811 if (token.Find(KOpenAngleBracket) != KErrNotFound) |
|
812 { |
|
813 iLexer.Inc(token.Find(KOpenAngleBracket) |
|
814 + KOpenAngleBracket().Length()); |
|
815 token.Set(iLexer.Remainder()); |
|
816 // Search for ']' |
|
817 if (token.Find(KCloseAngleBracket) != KErrNotFound) |
|
818 { |
|
819 iLexer.Inc(token.Find(KCloseAngleBracket) + KCloseAngleBracket().Length()); |
|
820 token.Set(iLexer.Remainder()); |
|
821 } |
|
822 else |
|
823 { |
|
824 iState = EStateError; |
|
825 return ERcDocumentError; // no end string found |
|
826 } |
|
827 } |
|
828 if (token.Find(KCloseBracket) != KErrNotFound) |
|
829 { |
|
830 endStringOffset = token.Find(KCloseBracket) + KCloseBracket().Length(); |
|
831 iLexer.Inc(endStringOffset); |
|
832 iLexer.SkipSpaceAndMark(iMarkPosition); // Remember where we are |
|
833 dtdFound = ETrue; |
|
834 } |
|
835 else |
|
836 { |
|
837 iState = EStateError; |
|
838 return ERcDocumentError; // no end string found |
|
839 } |
|
840 } |
|
841 else |
|
842 { |
|
843 iLexer.UnGetToMark(iMarkPosition); |
|
844 dtdFound = EFalse; |
|
845 } |
|
846 } |
|
847 } |
|
848 return KErrNone; |
|
849 } |
|
850 |
|
851 //////////////////////////////////////////////////////////////////////////////////////// |
|
852 // |
|
853 //////////////////////////////////////////////////////////////////////////////////////// |
|
854 TInt CXmlPullParser::SkipNonRelevantElements() |
|
855 { |
|
856 TPtrC8 token; |
|
857 TInt endStringOffset; |
|
858 TBool prologFound = ETrue; |
|
859 TBool commentFound = ETrue; |
|
860 TBool piFound = ETrue; |
|
861 TBool dtdFound = ETrue; |
|
862 |
|
863 iLexer.Mark(iMarkPosition); // Remember where we are |
|
864 |
|
865 if (iLexer.Eos()) |
|
866 { |
|
867 iState = EStateEndDocument; |
|
868 return KErrNone; |
|
869 } |
|
870 else |
|
871 { |
|
872 token.Set(iLexer.Remainder()); // pointer to the rest of the xml document |
|
873 |
|
874 while (prologFound || commentFound || piFound || dtdFound) |
|
875 { |
|
876 // check for prolog: if prolog found -> error |
|
877 // Spec says: "The document type declaration must appear before |
|
878 // the first element in the document." |
|
879 if (iLexer.Get() == '<' && iLexer.Get() == '?' && |
|
880 iLexer.Get() == 'x' && iLexer.Get() == 'm' && iLexer.Get() == 'l') |
|
881 { |
|
882 prologFound = ETrue; |
|
883 iState = EStateError; |
|
884 return ERcDocumentError; |
|
885 } |
|
886 else |
|
887 { |
|
888 iLexer.UnGetToMark(iMarkPosition); |
|
889 prologFound = EFalse; |
|
890 } |
|
891 |
|
892 // check for comment: if found skip it |
|
893 if (iLexer.Get() == '<' && iLexer.Get() == '!' && |
|
894 iLexer.Get() == '-' && iLexer.Get() == '-') |
|
895 { |
|
896 token.Set(iLexer.Remainder()); // pointer to the rest of the xml document |
|
897 if (token.Find(KEndComment) != KErrNotFound) |
|
898 { |
|
899 endStringOffset = token.Find(KEndComment) + KEndComment().Length(); |
|
900 iLexer.Inc(endStringOffset); |
|
901 iLexer.Mark(iMarkPosition); // Remember where we are |
|
902 commentFound = ETrue; |
|
903 } |
|
904 else |
|
905 { |
|
906 iState = EStateError; |
|
907 return ERcDocumentError; // no end string found |
|
908 } |
|
909 } |
|
910 else |
|
911 { |
|
912 iLexer.UnGetToMark(iMarkPosition); |
|
913 commentFound = EFalse; |
|
914 } |
|
915 |
|
916 // check for processing instructions: if found skip it |
|
917 if (iLexer.Get() == '<' && iLexer.Get() == '?') |
|
918 { |
|
919 token.Set(iLexer.Remainder()); // pointer to the rest of the xml document |
|
920 if (token.Find(KEndPIAndProlog) != KErrNotFound) |
|
921 { |
|
922 endStringOffset = token.Find(KEndPIAndProlog) + KEndPIAndProlog().Length(); |
|
923 iLexer.Inc(endStringOffset); |
|
924 iLexer.Mark(iMarkPosition); // Remember where we are |
|
925 piFound = ETrue; |
|
926 } |
|
927 else |
|
928 { |
|
929 iState = EStateError; |
|
930 return ERcDocumentError; // no end string found |
|
931 } |
|
932 } |
|
933 else |
|
934 { |
|
935 iLexer.UnGetToMark(iMarkPosition); |
|
936 piFound = EFalse; |
|
937 } |
|
938 |
|
939 // check for document type declaration: if found skip it |
|
940 if (iLexer.Get() == '<' && iLexer.Get() == '!' && |
|
941 iLexer.Get() == 'D' && iLexer.Get() == 'O' && |
|
942 iLexer.Get() == 'C' && iLexer.Get() == 'T' && |
|
943 iLexer.Get() == 'Y' && iLexer.Get() == 'P' && |
|
944 iLexer.Get() == 'E') |
|
945 { |
|
946 token.Set(iLexer.Remainder()); // pointer to the rest of the xml document |
|
947 // if '[' found skip to ']' and then search for '>' (= end of doctype) |
|
948 if (token.Find(KOpenAngleBracket) != KErrNotFound) |
|
949 { |
|
950 iLexer.Inc(token.Find(KOpenAngleBracket) |
|
951 + KOpenAngleBracket().Length()); |
|
952 token.Set(iLexer.Remainder()); |
|
953 // Search for ']' |
|
954 if (token.Find(KCloseAngleBracket) != KErrNotFound) |
|
955 { |
|
956 iLexer.Inc(token.Find(KCloseAngleBracket) + KCloseAngleBracket().Length()); |
|
957 token.Set(iLexer.Remainder()); |
|
958 } |
|
959 else |
|
960 { |
|
961 iState = EStateError; |
|
962 return ERcDocumentError; // no end string found |
|
963 } |
|
964 } |
|
965 if (token.Find(KCloseBracket) != KErrNotFound) |
|
966 { |
|
967 endStringOffset = token.Find(KCloseBracket) + KCloseBracket().Length(); |
|
968 iLexer.Inc(endStringOffset); |
|
969 iLexer.SkipSpaceAndMark(iMarkPosition); // Remember where we are |
|
970 dtdFound = ETrue; |
|
971 } |
|
972 else |
|
973 { |
|
974 iState = EStateError; |
|
975 return ERcDocumentError; // no end string found |
|
976 } |
|
977 |
|
978 } |
|
979 else |
|
980 { |
|
981 iLexer.UnGetToMark(iMarkPosition); |
|
982 dtdFound = EFalse; |
|
983 } |
|
984 } |
|
985 } |
|
986 return KErrNone; |
|
987 } |
|
988 |
|
989 //////////////////////////////////////////////////////////////////////////////////////// |
|
990 // |
|
991 //////////////////////////////////////////////////////////////////////////////////////// |
|
992 TInt CXmlPullParser::GetElementStartTagL() |
|
993 { |
|
994 TPtrC8 token; |
|
995 TPtrC8 startTag; |
|
996 TInt offset; |
|
997 TInt eqpos; |
|
998 TInt spacepos; |
|
999 TInt attrValueLen; |
|
1000 TLex8 tokenLexer; |
|
1001 TChar ch; |
|
1002 |
|
1003 |
|
1004 iLexer.Mark(iMarkPosition); // Remember where we are |
|
1005 |
|
1006 if (iLexer.Eos()) |
|
1007 { |
|
1008 iState = EStateError; // we can not be in the end of the doc when |
|
1009 // we should have Start Tag |
|
1010 return ERcDocumentError; |
|
1011 } |
|
1012 else |
|
1013 { |
|
1014 |
|
1015 // Delete attributes from iCAttrDataArray |
|
1016 iCAttrDataArray->Delete(0, iCAttrDataArray->Count()); |
|
1017 |
|
1018 |
|
1019 if (iLexer.Get() == '<' && iLexer.Peek().IsAlpha()) |
|
1020 { |
|
1021 iLexer.Mark(iMarkPosition); // start of the element |
|
1022 token.Set(iLexer.Remainder()); |
|
1023 offset = token.Find(KCloseBracket); |
|
1024 |
|
1025 // start tag and possible attribute(s) |
|
1026 startTag.Set(token.Left(offset)); |
|
1027 tokenLexer.Assign(startTag); |
|
1028 |
|
1029 // Start tag format: '<' Name (S Attribute)* S?'>' |
|
1030 // tag name -> iElement |
|
1031 if (startTag.Find(KSpace) == KErrNotFound) |
|
1032 { |
|
1033 // case: no attributes/space in the start tag |
|
1034 iElement.Set(startTag.Left(offset)); |
|
1035 if (iElement[iElement.Length() - 1] == '/') |
|
1036 { |
|
1037 iElement.Set(iElement.Left(iElement.Length() - 1)); |
|
1038 } |
|
1039 } |
|
1040 else |
|
1041 { |
|
1042 // case: space after tag name or |
|
1043 // case: at least one attribute in the start tag |
|
1044 iElement.Set(startTag.Left(startTag.Find(KSpace))); |
|
1045 } |
|
1046 |
|
1047 // set state |
|
1048 iState = EStateStartTag; |
|
1049 |
|
1050 // Add /tag name to iPathBuf |
|
1051 CheckSpaceL(iElement); // Check that there is enough space in iPathBuf |
|
1052 |
|
1053 iPathBufPtr.Append(KSlash); // '/' |
|
1054 iPathBufPtr.Append(iElement); // tag name |
|
1055 |
|
1056 // increment iDepth |
|
1057 iDepth++; |
|
1058 |
|
1059 while ((eqpos = startTag.Find(KEquals)) != KErrNotFound) |
|
1060 { |
|
1061 TAttrData startTagAttr; |
|
1062 // get attribute(s) |
|
1063 spacepos = startTag.Find(KSpace); |
|
1064 tokenLexer.Inc(spacepos); |
|
1065 startTagAttr.iName.Set(startTag.Mid(spacepos + KSpace().Length(), |
|
1066 eqpos - spacepos - KEquals().Length())); |
|
1067 // rest of the start tag and attributes |
|
1068 startTag.Set(startTag.Right(startTag.Length() - eqpos - KEquals().Length())); |
|
1069 tokenLexer.Inc(eqpos - spacepos + KEquals().Length()); |
|
1070 ch = tokenLexer.Get(); |
|
1071 if (ch == '\'' || ch == '\"') // this should be ' or " |
|
1072 { |
|
1073 startTag.Set(startTag.Right(startTag.Length() - 1)); |
|
1074 // if attribute ending ' or " not found return error |
|
1075 if ((attrValueLen = startTag.Locate(ch)) != KErrNotFound) |
|
1076 { |
|
1077 startTagAttr.iValue.Set(startTag.Left(attrValueLen)); |
|
1078 iCAttrDataArray->AppendL(startTagAttr); |
|
1079 startTag.Set(startTag.Right(startTag.Length() - attrValueLen)); |
|
1080 tokenLexer.Inc(attrValueLen); |
|
1081 } |
|
1082 else |
|
1083 { |
|
1084 iState = EStateError; |
|
1085 return ERcDocumentError; |
|
1086 } |
|
1087 } |
|
1088 else |
|
1089 { |
|
1090 iState = EStateError; |
|
1091 return ERcDocumentError; |
|
1092 } |
|
1093 } |
|
1094 |
|
1095 // check if tag is empty element |
|
1096 iLexer.Inc(offset - KCloseBracket().Length()); // iLexer into the end of the tag - 1 position |
|
1097 iLexer.Mark(iMarkPosition); |
|
1098 |
|
1099 if (iLexer.Get() == '/') // next char is '>' for sure |
|
1100 { |
|
1101 iLexer.Inc(KCloseBracket().Length()); |
|
1102 iIsEmptyElement = ETrue; |
|
1103 iLexer.Mark(iMarkPosition); |
|
1104 } |
|
1105 else if (iLexer.Get() == '>') |
|
1106 { |
|
1107 iIsEmptyElement = EFalse; |
|
1108 iLexer.Mark(iMarkPosition); |
|
1109 } |
|
1110 else |
|
1111 { |
|
1112 iState = EStateError; |
|
1113 return ERcDocumentError; |
|
1114 } |
|
1115 } |
|
1116 else |
|
1117 { |
|
1118 iState = EStateError; |
|
1119 return ERcDocumentError; |
|
1120 } |
|
1121 } |
|
1122 return KErrNone; |
|
1123 } |
|
1124 |
|
1125 //////////////////////////////////////////////////////////////////////////////////////// |
|
1126 // |
|
1127 //////////////////////////////////////////////////////////////////////////////////////// |
|
1128 TInt CXmlPullParser::GetElementText() |
|
1129 { |
|
1130 TPtrC8 elementText; |
|
1131 TInt offset; |
|
1132 TInt cdataStartOffset; |
|
1133 TInt cdataEndOffset; |
|
1134 |
|
1135 iLexer.Mark(iMarkPosition); // Remember where we are |
|
1136 |
|
1137 if (iLexer.Eos()) |
|
1138 { |
|
1139 iState = EStateError; // we can not be in the end of the doc when |
|
1140 // we should have Start Tag |
|
1141 return ERcDocumentError; |
|
1142 } |
|
1143 else |
|
1144 { |
|
1145 elementText.Set(iLexer.Remainder()); |
|
1146 |
|
1147 if (iCdataStartFound) |
|
1148 { |
|
1149 if ((cdataEndOffset = elementText.Find(KEndCData)) != KErrNotFound) |
|
1150 { |
|
1151 iCdataStartFound = EFalse; |
|
1152 iCdataSectionText = ETrue; // text inside CDATA section |
|
1153 iText.Set(elementText.Left(cdataEndOffset)); |
|
1154 if (iText.Find(KStartCData) != KErrNotFound) |
|
1155 { |
|
1156 // Nested CDATA sections are not allowed |
|
1157 iState = EStateError; |
|
1158 return ERcDocumentError; |
|
1159 } |
|
1160 iLexer.Inc(cdataEndOffset + KEndCData().Length()); |
|
1161 } |
|
1162 else |
|
1163 { |
|
1164 // CDATA end not found -> error |
|
1165 iState = EStateError; |
|
1166 return ERcDocumentError; |
|
1167 } |
|
1168 } |
|
1169 else |
|
1170 { |
|
1171 // Start of CDATA section '<![CDATA[' |
|
1172 if ((cdataStartOffset = elementText.Find(KStartCData)) == 0) |
|
1173 { |
|
1174 if ((cdataEndOffset = elementText.Find(KEndCData)) != KErrNotFound) |
|
1175 { |
|
1176 iCdataStartFound = EFalse; |
|
1177 iCdataSectionText = ETrue; // text inside CDATA section |
|
1178 iText.Set(elementText.Mid(KStartCData().Length(), cdataEndOffset - KStartCData().Length())); |
|
1179 if (iText.Find(KStartCData) != KErrNotFound) |
|
1180 { |
|
1181 // Nested CDATA sections are not allowed |
|
1182 iState = EStateError; |
|
1183 return ERcDocumentError; |
|
1184 } |
|
1185 iLexer.Inc(cdataEndOffset + KEndCData().Length()); |
|
1186 } |
|
1187 else |
|
1188 { |
|
1189 // CDATA end not found -> error |
|
1190 iState = EStateError; |
|
1191 return ERcDocumentError; |
|
1192 } |
|
1193 } |
|
1194 else |
|
1195 { |
|
1196 offset = elementText.Find(KOpenBracket); // any '<' |
|
1197 |
|
1198 if ((cdataStartOffset != KErrNotFound) && !(offset < cdataStartOffset)) |
|
1199 { |
|
1200 iCdataStartFound = ETrue; |
|
1201 iCdataSectionText = EFalse; // text before CDATA section |
|
1202 iText.Set(elementText.Left(cdataStartOffset)); |
|
1203 iLexer.Inc(cdataStartOffset + KStartCData().Length()); |
|
1204 } |
|
1205 else |
|
1206 { |
|
1207 // No CDATA section found |
|
1208 // iCdataStartFound = EFalse; // this is EFalse any way |
|
1209 iCdataSectionText = EFalse; |
|
1210 if (offset != KErrNotFound) |
|
1211 { |
|
1212 iText.Set(elementText.Left(offset)); |
|
1213 iLexer.Inc(offset); |
|
1214 } |
|
1215 else |
|
1216 { |
|
1217 iState = EStateError; |
|
1218 return ERcDocumentError; |
|
1219 } |
|
1220 } |
|
1221 } |
|
1222 } |
|
1223 iState = EStateText; |
|
1224 return KErrNone; |
|
1225 } |
|
1226 } |
|
1227 |
|
1228 //////////////////////////////////////////////////////////////////////////////////////// |
|
1229 // |
|
1230 //////////////////////////////////////////////////////////////////////////////////////// |
|
1231 TBool CXmlPullParser::CheckIfNextEndTag() |
|
1232 { |
|
1233 iLexer.Mark(iMarkPosition); |
|
1234 |
|
1235 if (iLexer.Eos()) |
|
1236 { |
|
1237 iState = EStateError; // we can not be in the end of the doc when |
|
1238 // we should have Start/End Tag |
|
1239 return ETrue; // the caller must check the iState!! |
|
1240 } |
|
1241 else |
|
1242 { |
|
1243 if (iLexer.Get() == '<' && iLexer.Get() == '/') |
|
1244 { |
|
1245 iLexer.UnGetToMark(iMarkPosition); |
|
1246 return ETrue; |
|
1247 } |
|
1248 else |
|
1249 { |
|
1250 iLexer.UnGetToMark(iMarkPosition); |
|
1251 return EFalse; |
|
1252 } |
|
1253 } |
|
1254 } |
|
1255 |
|
1256 //////////////////////////////////////////////////////////////////////////////////////// |
|
1257 // |
|
1258 //////////////////////////////////////////////////////////////////////////////////////// |
|
1259 TBool CXmlPullParser::CheckIfNextStartTag() |
|
1260 { |
|
1261 iLexer.Mark(iMarkPosition); |
|
1262 |
|
1263 if (iLexer.Eos()) |
|
1264 { |
|
1265 iState = EStateError; // we can not be in the end of the doc when |
|
1266 // we should have Start/End Tag |
|
1267 return ETrue; // the caller must check the iState!! |
|
1268 } |
|
1269 else |
|
1270 { |
|
1271 if (iLexer.Get() == '<' && iLexer.Get().IsAlpha()) |
|
1272 { |
|
1273 iLexer.UnGetToMark(iMarkPosition); |
|
1274 return ETrue; |
|
1275 } |
|
1276 else |
|
1277 { |
|
1278 iLexer.UnGetToMark(iMarkPosition); |
|
1279 return EFalse; |
|
1280 } |
|
1281 } |
|
1282 } |
|
1283 |
|
1284 |
|
1285 //////////////////////////////////////////////////////////////////////////////////////// |
|
1286 // |
|
1287 //////////////////////////////////////////////////////////////////////////////////////// |
|
1288 TInt CXmlPullParser::GetElementEndTag() |
|
1289 { |
|
1290 TPtrC8 elementText; |
|
1291 TInt offset; |
|
1292 |
|
1293 iLexer.Mark(iMarkPosition); // Remember where we are |
|
1294 |
|
1295 if (iLexer.Eos()) |
|
1296 { |
|
1297 iState = EStateError; // we can not be in the end of the doc when |
|
1298 // we should have End Tag |
|
1299 return ERcDocumentError; |
|
1300 } |
|
1301 else |
|
1302 { |
|
1303 if (iLexer.Get() == '<' && iLexer.Get() == '/') |
|
1304 { |
|
1305 elementText.Set(iLexer.Remainder()); |
|
1306 if ((offset = elementText.Find(KCloseBracket)) != KErrNotFound) |
|
1307 { |
|
1308 // End tag format: '</' Name S? '>' |
|
1309 iElement.Set(elementText.Left(offset)); |
|
1310 if (iElement[iElement.Length() - 1] == ' ') |
|
1311 { |
|
1312 iElement.Set(iElement.Left(iElement.Length() - 1)); |
|
1313 } |
|
1314 |
|
1315 // delete /end tag from the iPathBuf |
|
1316 // this is done by subtracting the length of the buffer |
|
1317 iPathBufPtr.SetLength(iPathBufPtr.LocateReverse('/')); |
|
1318 |
|
1319 // decrement iDepth |
|
1320 iDepth--; |
|
1321 |
|
1322 iLexer.Inc(offset + KCloseBracket().Length()); |
|
1323 iState = EStateEndTag; |
|
1324 return KErrNone; |
|
1325 } |
|
1326 else |
|
1327 { |
|
1328 iState = EStateError; |
|
1329 return ERcDocumentError; |
|
1330 } |
|
1331 } |
|
1332 else |
|
1333 { |
|
1334 iState = EStateError; |
|
1335 return ERcDocumentError; |
|
1336 } |
|
1337 } |
|
1338 } |
|
1339 |
|
1340 //////////////////////////////////////////////////////////////////////////////////////// |
|
1341 // |
|
1342 //////////////////////////////////////////////////////////////////////////////////////// |
|
1343 TBool CXmlPullParser::CheckIfEndOfFile() |
|
1344 { |
|
1345 iLexer.Mark(iMarkPosition); |
|
1346 |
|
1347 if ( (iDepth == 0) && (iPathBufPtr.Length() == 0) ) |
|
1348 { |
|
1349 iState = EStateEndDocument; |
|
1350 return ETrue; |
|
1351 } |
|
1352 else |
|
1353 { |
|
1354 return EFalse; |
|
1355 } |
|
1356 } |
|
1357 |
|
1358 //////////////////////////////////////////////////////////////////////////////////////// |
|
1359 // |
|
1360 //////////////////////////////////////////////////////////////////////////////////////// |
|
1361 TInt CXmlPullParser::EscapeCharRefAndPreDefEntities() |
|
1362 { |
|
1363 TInt retVal; |
|
1364 |
|
1365 if (iStringValuePtr.Find(KAmpersandHash) != KErrNotFound) |
|
1366 { |
|
1367 retVal = CharacterReferencesEscaped(); // handle ª and &#aa; |
|
1368 if ( retVal != KErrNone ) |
|
1369 { |
|
1370 return retVal; |
|
1371 } |
|
1372 } |
|
1373 |
|
1374 if (iStringValuePtr.Find(KAmpersand) != KErrNotFound) |
|
1375 { |
|
1376 retVal = PredefinedEntitiesEscaped(); // handle < > & ' and " |
|
1377 if ( retVal != KErrNone ) |
|
1378 { |
|
1379 return retVal; |
|
1380 } |
|
1381 } |
|
1382 |
|
1383 return KErrNone; |
|
1384 } |
|
1385 |
|
1386 //////////////////////////////////////////////////////////////////////////////////////// |
|
1387 // |
|
1388 //////////////////////////////////////////////////////////////////////////////////////// |
|
1389 TInt CXmlPullParser::CharacterReferencesEscaped() |
|
1390 { |
|
1391 TInt startPos, length; |
|
1392 TInt retVal; |
|
1393 TInt i = 0; |
|
1394 TRadix radix = EDecimal; |
|
1395 |
|
1396 TLex8 tempLexer; |
|
1397 TLexMark8 mark; |
|
1398 TUint number; |
|
1399 |
|
1400 TPtrC8 tempPtr; |
|
1401 |
|
1402 while ( (startPos = iStringValuePtr.Find(KAmpersandHash)) != KErrNotFound) |
|
1403 { |
|
1404 tempPtr.Set(iStringValuePtr.Right(iStringValuePtr.Length() - startPos)); |
|
1405 length = tempPtr.Find(KSemicolon) - KAmpersandHash().Length(); |
|
1406 tempPtr.Set(iStringValuePtr.Mid(startPos + KAmpersandHash().Length(), length)); |
|
1407 tempLexer.Assign(tempPtr); |
|
1408 if ( tempLexer.Peek() == 'x' ) |
|
1409 { |
|
1410 tempLexer.Inc(); //increment to next character position |
|
1411 tempLexer.Mark(mark); |
|
1412 for ( i = 0; i < (length - 1); i++ ) // check that whole input is hexadecimal |
|
1413 { |
|
1414 if ( !(tempLexer.Get()).IsHexDigit() ) |
|
1415 { |
|
1416 return ERcDocumentError; // after &#x there must be hexadecimal digits (0-9, a-f, A-F). |
|
1417 } |
|
1418 } |
|
1419 tempLexer.UnGetToMark(mark); |
|
1420 radix = EHex; |
|
1421 } |
|
1422 else |
|
1423 { |
|
1424 tempLexer.Mark(mark); |
|
1425 for ( i = 0; i < length; i++ ) |
|
1426 { |
|
1427 if ( !(tempLexer.Get()).IsDigit() ) |
|
1428 { |
|
1429 return ERcDocumentError; // after &# there must be standard decimal digits (0-9). |
|
1430 } |
|
1431 } |
|
1432 tempLexer.UnGetToMark(mark); |
|
1433 radix = EDecimal; |
|
1434 } |
|
1435 |
|
1436 if ( (retVal = tempLexer.Val(number, radix)) == KErrNone) |
|
1437 { |
|
1438 TChar ch(number); |
|
1439 TBuf8<12> buf; |
|
1440 buf.Append(ch); |
|
1441 iStringValuePtr.Replace(startPos, length + KAmpersandHash().Length() + |
|
1442 KSemicolon().Length(), buf); |
|
1443 } |
|
1444 else |
|
1445 { |
|
1446 return retVal; |
|
1447 } |
|
1448 } |
|
1449 return KErrNone; |
|
1450 } |
|
1451 |
|
1452 //////////////////////////////////////////////////////////////////////////////////////// |
|
1453 // |
|
1454 //////////////////////////////////////////////////////////////////////////////////////// |
|
1455 TInt CXmlPullParser::PredefinedEntitiesEscaped() |
|
1456 { |
|
1457 TInt pos; |
|
1458 |
|
1459 while (iStringValuePtr.Find(KAmpersand) != KErrNotFound) |
|
1460 { |
|
1461 if ((pos = iStringValuePtr.Find(KEntityLowerThan)) != KErrNotFound) |
|
1462 { |
|
1463 iStringValuePtr.Replace(pos, KEntityLowerThan().Length(), KOpenBracket); |
|
1464 } |
|
1465 else if ((pos = iStringValuePtr.Find(KEntityGreaterThan)) != KErrNotFound) |
|
1466 { |
|
1467 iStringValuePtr.Replace(pos, KEntityGreaterThan().Length(), KCloseBracket); |
|
1468 } |
|
1469 else if ((pos = iStringValuePtr.Find(KEntityAmpersand)) != KErrNotFound) |
|
1470 { |
|
1471 iStringValuePtr.Replace(pos, KEntityAmpersand().Length(), KAmpersand); |
|
1472 } |
|
1473 else if ((pos = iStringValuePtr.Find(KEntityApostrophe)) != KErrNotFound) |
|
1474 { |
|
1475 iStringValuePtr.Replace(pos, KEntityApostrophe().Length(), KSingleQuote); |
|
1476 } |
|
1477 else if ((pos = iStringValuePtr.Find(KEntityQuotation)) != KErrNotFound) |
|
1478 { |
|
1479 iStringValuePtr.Replace(pos, KEntityQuotation().Length(), KDoubleQuote); |
|
1480 } |
|
1481 else |
|
1482 { |
|
1483 return KErrNone; |
|
1484 } |
|
1485 } |
|
1486 return KErrNone; |
|
1487 } |