Boolean XmlParser::_next( XmlEntry& entry, Boolean includeComment) { if (!_putBackStack.isEmpty()) { entry = _putBackStack.top(); _putBackStack.pop(); return true; } // If a character was overwritten with a null-terminator the last // time this routine was called, then put back that character. Before // exiting of course, restore the null-terminator. char* nullTerminator = 0; if (_restoreChar && !*_current) { nullTerminator = _current; *_current = _restoreChar; _restoreChar = '\0'; } entry.attributes.clear(); if (_supportedNamespaces) { // Remove namespaces of a deeper scope level from the stack. while (!_nameSpaces.isEmpty() && _nameSpaces.top().scopeLevel > _stack.size()) { _nameSpaces.pop(); } } // Loop until we are done with comments if includeComment is false. do { // Skip over any whitespace: _skipWhitespace(_line, _current); if (!*_current) { if (nullTerminator) *nullTerminator = '\0'; if (!_stack.isEmpty()) throw XmlException(XmlException::UNCLOSED_TAGS, _line); return false; } // Either a "<...>" or content begins next: if (*_current == '<') { _current++; _getElement(_current, entry); if (nullTerminator) *nullTerminator = '\0'; if (entry.type == XmlEntry::START_TAG) { if (_stack.isEmpty() && _foundRoot) throw XmlException(XmlException::MULTIPLE_ROOTS, _line); _foundRoot = true; _stack.push((char*)entry.text); } else if (entry.type == XmlEntry::END_TAG) { if (_stack.isEmpty()) throw XmlException(XmlException::START_END_MISMATCH, _line); if (strcmp(_stack.top(), entry.text) != 0) throw XmlException(XmlException::START_END_MISMATCH, _line); _stack.pop(); } } else { // Normalize the content: char* start = _current; Uint32 textLen; _normalizeElementValue(_line, _current, textLen); // Get the content: entry.type = XmlEntry::CONTENT; entry.text = start; entry.textLen = textLen; // Overwrite '<' with a null character (temporarily). _restoreChar = *_current; *_current = '\0'; if (nullTerminator) *nullTerminator = '\0'; } } while (!includeComment && entry.type == XmlEntry::COMMENT); if (_supportedNamespaces && (entry.type == XmlEntry::START_TAG || entry.type == XmlEntry::EMPTY_TAG || entry.type == XmlEntry::END_TAG)) { // Determine the namespace type for this entry if (entry.type == XmlEntry::START_TAG || entry.type == XmlEntry::EMPTY_TAG) { // Process namespace declarations and determine the namespace type // for the attributes. Uint32 scopeLevel = _stack.size(); if (entry.type == XmlEntry::EMPTY_TAG) { // Empty tags are deeper scope, but not pushed onto the stack scopeLevel++; } for (Uint32 i = 0, n = entry.attributes.size(); i < n; i++) { XmlAttribute& attr = entry.attributes[i]; if ((strncmp(attr.name, "xmlns:", 6) == 0) || (strcmp(attr.name, "xmlns") == 0)) { // Process a namespace declaration XmlNamespace ns; if (attr.name[5] == ':') { ns.localName = attr.localName; } else { // Default name space has no local name ns.localName = 0; } ns.extendedName = attr.value; ns.scopeLevel = scopeLevel; ns.type = _getSupportedNamespaceType(ns.extendedName); // If the namespace is not supported, assign it a unique // negative identifier. if (ns.type == -1) { ns.type = _currentUnsupportedNSType--; } _nameSpaces.push(ns); } else { // Get the namespace type for this attribute. attr.nsType = _getNamespaceType(attr.name); } } } entry.nsType = _getNamespaceType(entry.text); } else { entry.nsType = -1; } return true; }
xmlChar* as_xmlname(Request& r, MethodParams& params, int index, const char* msg) { xmlChar* localName=r.transcode(params.as_string(index, msg ? msg : XML_LOCAL_NAME_MUST_BE_STRING)); if(xmlValidateName(localName, 0)) throw XmlException(0, XML_INVALID_LOCAL_NAME, localName); return localName; }
void XmlParser::_getElement(char*& p, XmlEntry& entry) { //-------------------------------------------------------------------------- // Get the element name (expect one of these: '?', '!', [A-Za-z_]) //-------------------------------------------------------------------------- if (*p == '?') { entry.type = XmlEntry::XML_DECLARATION; entry.text = ++p; if (_getElementName(p, entry.localName)) return; } else if (*p == '!') { p++; // Expect a comment or CDATA: if (p[0] == '-' && p[1] == '-') { p += 2; entry.type = XmlEntry::COMMENT; entry.text = p; _getComment(p); return; } else if (memcmp(p, "[CDATA[", 7) == 0) { p += 7; entry.type = XmlEntry::CDATA; entry.text = p; _getCData(p); entry.textLen = strlen(entry.text); return; } else if (memcmp(p, "DOCTYPE", 7) == 0) { entry.type = XmlEntry::DOCTYPE; entry.text = ""; _getDocType(p); return; } throw(XmlException(XmlException::EXPECTED_COMMENT_OR_CDATA, _line)); } else if (*p == '/') { entry.type = XmlEntry::END_TAG; entry.text = ++p; if (!_getElementName(p, entry.localName)) throw(XmlException(XmlException::BAD_END_TAG, _line)); return; } else if (CharSet::isAlphaUnder(Uint8(*p))) { entry.type = XmlEntry::START_TAG; entry.text = p; Boolean openCloseElement = false; if (_getOpenElementName(p, entry.localName, openCloseElement)) { if (openCloseElement) entry.type = XmlEntry::EMPTY_TAG; return; } } else throw XmlException(XmlException::BAD_START_TAG, _line); //-------------------------------------------------------------------------- // Grab all the attributes: //-------------------------------------------------------------------------- for (;;) { if (entry.type == XmlEntry::XML_DECLARATION) { if (p[0] == '?' && p[1] == '>') { p += 2; return; } } else if (entry.type == XmlEntry::START_TAG && p[0] == '/' && p[1] =='>') { entry.type = XmlEntry::EMPTY_TAG; p += 2; return; } else if (*p == '>') { p++; return; } XmlAttribute attr; attr.nsType = -1; attr.name = p; _getAttributeNameAndEqual(p, attr.localName); // Get the attribute value (e.g., "some value") { if ((*p != '"') && (*p != '\'')) { throw XmlException(XmlException::BAD_ATTRIBUTE_VALUE, _line); } char quote = *p++; char* start; _normalizeAttributeValue(_line, p, quote, start); attr.value = start; if (*p != quote) { throw XmlException(XmlException::BAD_ATTRIBUTE_VALUE, _line); } // Overwrite the closing quote with a null-terminator: *p++ = '\0'; } if (entry.type == XmlEntry::XML_DECLARATION) { // The next thing must a space or a "?>": if (!(p[0] == '?' && p[1] == '>') && !_isspace(*p)) { throw XmlException( XmlException::BAD_ATTRIBUTE_VALUE, _line); } } else if (!(*p == '>' || (p[0] == '/' && p[1] == '>') || _isspace(*p))) { // The next thing must be a space or a '>': throw XmlException(XmlException::BAD_ATTRIBUTE_VALUE, _line); } _skipWhitespace(_line, p); entry.attributes.append(attr); } }
xmlChar* as_xmlqname(Request& r, MethodParams& params, int index, const char* msg) { xmlChar* qname=r.transcode(params.as_string(index, msg ? msg : XML_QUALIFIED_NAME_MUST_BE_STRING)); if(xmlValidateQName(qname, 0)) throw XmlException(0, XML_INVALID_QUALIFIED_NAME, qname); return qname; }