XmlElement* XmlDocument::readNextElement (const bool alsoParseSubElements) { XmlElement* node = nullptr; skipNextWhiteSpace(); if (outOfData) return nullptr; if (*input == '<') { ++input; String::CharPointerType endOfToken (XmlIdentifierChars::findEndOfToken (input)); if (endOfToken == input) { // no tag name - but allow for a gap after the '<' before giving an error skipNextWhiteSpace(); endOfToken = XmlIdentifierChars::findEndOfToken (input); if (endOfToken == input) { setLastError ("tag name missing", false); return node; } } node = new XmlElement (input, endOfToken); input = endOfToken; LinkedListPointer<XmlElement::XmlAttributeNode>::Appender attributeAppender (node->attributes); // look for attributes for (;;) { skipNextWhiteSpace(); const juce_wchar c = *input; // empty tag.. if (c == '/' && input[1] == '>') { input += 2; break; } // parse the guts of the element.. if (c == '>') { ++input; if (alsoParseSubElements) readChildElements (*node); break; } // get an attribute.. if (XmlIdentifierChars::isIdentifierChar (c)) { String::CharPointerType attNameEnd (XmlIdentifierChars::findEndOfToken (input)); if (attNameEnd != input) { const String::CharPointerType attNameStart (input); input = attNameEnd; skipNextWhiteSpace(); if (readNextChar() == '=') { skipNextWhiteSpace(); const juce_wchar nextChar = *input; if (nextChar == '"' || nextChar == '\'') { XmlElement::XmlAttributeNode* const newAtt = new XmlElement::XmlAttributeNode (attNameStart, attNameEnd); readQuotedString (newAtt->value); attributeAppender.append (newAtt); continue; } } else { setLastError ("expected '=' after attribute '" + String (attNameStart, attNameEnd) + "'", false); return node; } } } else { if (! outOfData) setLastError ("illegal character found in " + node->getTagName() + ": '" + c + "'", false); } break; } } return node; }
XmlElement* XmlDocument::readNextElement (const bool alsoParseSubElements) { XmlElement* node = nullptr; skipNextWhiteSpace(); if (outOfData) return nullptr; const int openBracket = input.indexOf ((juce_wchar) '<'); if (openBracket >= 0) { input += openBracket + 1; int tagLen = findNextTokenLength(); if (tagLen == 0) { // no tag name - but allow for a gap after the '<' before giving an error skipNextWhiteSpace(); tagLen = findNextTokenLength(); if (tagLen == 0) { setLastError ("tag name missing", false); return node; } } node = new XmlElement (String (input, (size_t) tagLen)); input += tagLen; LinkedListPointer<XmlElement::XmlAttributeNode>::Appender attributeAppender (node->attributes); // look for attributes for (;;) { skipNextWhiteSpace(); const juce_wchar c = *input; // empty tag.. if (c == '/' && input[1] == '>') { input += 2; break; } // parse the guts of the element.. if (c == '>') { ++input; if (alsoParseSubElements) readChildElements (node); break; } // get an attribute.. if (XmlIdentifierChars::isIdentifierChar (c)) { const int attNameLen = findNextTokenLength(); if (attNameLen > 0) { const String::CharPointerType attNameStart (input); input += attNameLen; skipNextWhiteSpace(); if (readNextChar() == '=') { skipNextWhiteSpace(); const juce_wchar nextChar = *input; if (nextChar == '"' || nextChar == '\'') { XmlElement::XmlAttributeNode* const newAtt = new XmlElement::XmlAttributeNode (String (attNameStart, (size_t) attNameLen), String::empty); readQuotedString (newAtt->value); attributeAppender.append (newAtt); continue; } } } } else { if (! outOfData) setLastError ("illegal character found in " + node->getTagName() + ": '" + c + "'", false); } break; } } return node; }