#include #include #include SWORD_NAMESPACE_START void XMLTag::parse() const { int i; int start; char *name = 0; char *value = 0; if (!buf) return; for (i = 0; ((buf[i]) && (!isalpha(buf[i]))); i++); for (; buf[i]; i++) { if (buf[i] == ' ') { for (; ((buf[i]) && (!isalpha(buf[i]))); i++); if (buf[i]) { // we have an attribute name start = i; for (; ((buf[i]) && (!strchr(" =", buf[i]))); i++); if (i-start) { if (name) delete [] name; name = new char [ (i-start) + 1 ]; strncpy(name, buf+start, i-start); name[i-start] = 0; } for (; ((buf[i]) && (strchr(" =\"", buf[i]))); i++); if (buf[i]) { // we have attribute value start = i; for (; ((buf[i]) && (buf[i] != '\"')); i++); if (i-start) { if (value) delete [] value; value = new char [ (i-start) + 1 ]; strncpy(value, buf+start, i-start); value[i-start] = 0; attributes[name] = value; } } } } if (!buf[i]) break; } for (;i;i--) { if (buf[i] == '/') empty = true; if (!strchr(" \n>\t", buf[i])) break; } parsed = true; if (name) delete [] name; if (value) delete [] value; } XMLTag::XMLTag(const char *tagString) { name = 0; buf = 0; setText(tagString); } void XMLTag::setText(const char *tagString) { parsed = false; empty = false; endTag = false; if (buf) { delete [] buf; buf = 0; } if (!tagString) // assert tagString before proceeding return; stdstr(&buf, tagString); int start = 0; int i; // skip beginning silliness for (i = 0; ((tagString[i]) && (!isalpha(tagString[i]))); i++) { if (tagString[i] == '/') endTag = true; } start = i; for (; ((tagString[i]) && (!strchr(" />", tagString[i]))); i++); if (i-start) { if (name) delete [] name; name = new char [ (i-start) + 1 ]; strncpy(name, tagString+start, i-start); name[i-start] = 0; if (tagString[i] == '/') empty = true; } } XMLTag::~XMLTag() { if (buf) delete [] buf; if (name) delete [] name; } const StringList XMLTag::getAttributeNames() const { StringList retVal; if (!parsed) parse(); for (StringPairMap::iterator it = attributes.begin(); it != attributes.end(); it++) retVal.push_back(it->first.c_str()); return retVal; } const char *XMLTag::getPart(const char *buf, int partNum, char partSplit) const { for (; (buf && partNum); partNum--) { buf = strchr(buf, partSplit); if (buf) buf++; } if (buf) { const char *end = strchr(buf, partSplit); junkBuf = buf; if (end) junkBuf.setSize(end - buf); return junkBuf.c_str(); } return 0; } int XMLTag::getAttributePartCount(const char *attribName, char partSplit) const { int count; const char *buf = getAttribute(attribName); for (count = 0; buf; count++) { buf = strchr(buf, partSplit); if (buf) buf++; } return count; } const char *XMLTag::getAttribute(const char *attribName, int partNum, char partSplit) const { if (!parsed) parse(); StringPairMap::iterator it = attributes.find(attribName); const char *retVal = (it == attributes.end()) ? 0 : it->second.c_str(); if ((retVal) && (partNum > -1)) retVal = getPart(retVal, partNum, partSplit); return retVal; } const char *XMLTag::setAttribute(const char *attribName, const char *attribValue) { if (!parsed) parse(); if (attribValue) attributes[attribName] = attribValue; else attributes.erase(attribName); return attribValue; } const char *XMLTag::toString() const { SWBuf tag = "<"; if (!parsed) parse(); if (isEndTag()) tag += "/"; tag += getName(); for (StringPairMap::iterator it = attributes.begin(); it != attributes.end(); it++) { tag.appendFormatted(" %s=\"%s\"", it->first.c_str(), it->second.c_str()); } if (isEmpty()) tag += "/"; tag += ">"; if (buf) delete [] buf; buf = new char [ tag.length() + 1 ]; strcpy(buf, tag.c_str()); return buf; } SWORD_NAMESPACE_END