| 682 | } |
| 683 | |
| 684 | char* XMLNode::ParseDeep(char* p, StrPair* parentEnd) { |
| 685 | // This is a recursive method, but thinking about it "at the current level" |
| 686 | // it is a pretty simple flat list: |
| 687 | // <foo/> |
| 688 | // <!-- comment --> |
| 689 | // |
| 690 | // With a special case: |
| 691 | // <foo> |
| 692 | // </foo> |
| 693 | // <!-- comment --> |
| 694 | // |
| 695 | // Where the closing element (/foo) *must* be the next thing after the opening |
| 696 | // element, and the names must match. BUT the tricky bit is that the closing |
| 697 | // element will be read by the child. |
| 698 | // |
| 699 | // 'endTag' is the end tag for this node, it is returned by a call to a child. |
| 700 | // 'parentEnd' is the end tag for the parent, which is filled in and returned. |
| 701 | |
| 702 | while (p && *p) { |
| 703 | XMLNode* node = 0; |
| 704 | |
| 705 | p = _document->Identify(p, &node); |
| 706 | if (p == 0 || node == 0) { |
| 707 | break; |
| 708 | } |
| 709 | |
| 710 | StrPair endTag; |
| 711 | char* tmp = p; |
| 712 | p = node->ParseDeep(p, &endTag); |
| 713 | if (!p) { |
| 714 | DELETE_NODE(node); |
| 715 | node = 0; |
| 716 | if (!_document->HasError()) { |
| 717 | _document->SetError(tmp, XML_ERROR_PARSING, 0, 0); |
| 718 | } |
| 719 | break; |
| 720 | } |
| 721 | |
| 722 | // We read the end tag. Return it to the parent. |
| 723 | if (node->ToElement() && node->ToElement()->ClosingType() == XMLElement::CLOSING) { |
| 724 | if (parentEnd) { |
| 725 | *parentEnd = static_cast<XMLElement*>(node)->_value; |
| 726 | } |
| 727 | node->_memPool->SetTracked(); // created and then immediately deleted. |
| 728 | DELETE_NODE(node); |
| 729 | return p; |
| 730 | } |
| 731 | |
| 732 | // Handle an end tag returned to this level. |
| 733 | // And handle a bunch of annoying errors. |
| 734 | XMLElement* ele = node->ToElement(); |
| 735 | if (ele) { |
| 736 | if (endTag.Empty() && ele->ClosingType() == XMLElement::OPEN) { |
| 737 | _document->SetError(p, XML_ERROR_MISMATCHED_ELEMENT, node->Value(), 0); |
| 738 | p = 0; |
| 739 | } else if (!endTag.Empty() && ele->ClosingType() != XMLElement::OPEN) { |
| 740 | _document->SetError(p, XML_ERROR_MISMATCHED_ELEMENT, node->Value(), 0); |
| 741 | p = 0; |
no test coverage detected