XMLParser 详解

XMLParser内部通过 OSFileSource    fFile来读取文件内容;
成员变量XMLTag*         fRootTag,获取内容后调用 
fRootTag = NEW XMLTag();
    Bool16 result = fRootTag->ParseTag(&theParser, fVerifier, errorBuffer, errorBufferSize);

来将xml信息填充到fRootTag中,其内部有嵌套Tag。而每一个Tag内部又能获取到属性。因此能够获取到整个xml内容。



char* theXMLFilePath = "c:\\Program Files\\Darwin Streaming Server\\streamingserver.xml";
int main(int argc, char * argv[]) 
{

	XMLParser  parser2(theXMLFilePath);
	char erro[500] = {0};
	if ( !parser2.ParseFile(erro,500))
	{
		return -1;
	}

	XMLTag *pTag = parser2.GetRootTag();
	cout << pTag->GetTagName() << endl;
	int nLen = pTag->GetNumEmbeddedTags();
	for (int i =0;i  < nLen; i ++)
	{
		XMLTag *pTempTag = pTag->GetEmbeddedTag(i);
		cout << pTempTag->GetTagName() << endl;
	}}




/*
 *
 * @APPLE_LICENSE_HEADER_START@
 * 
 * Copyright (c) 1999-2003 Apple Computer, Inc.  All Rights Reserved.
 * 
 * This file contains Original Code and/or Modifications of Original Code
 * as defined in and that are subject to the Apple Public Source License
 * Version 2.0 (the 'License'). You may not use this file except in
 * compliance with the License. Please obtain a copy of the License at
 * http://www.opensource.apple.com/apsl/ and read it before using this
 * file.
 * 
 * The Original Code and all software distributed under the License are
 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
 * Please see the License for the specific language governing rights and
 * limitations under the License.
 * 
 * @APPLE_LICENSE_HEADER_END@
 *
 */

#ifndef __XMLParser_h__
#define __XMLParser_h__

#include "StringParser.h"
#include "OSQueue.h"
#include "OSFileSource.h"
#include "ResizeableStringFormatter.h"

class DTDVerifier
{
public:
    virtual bool IsValidSubtag(char* tagName, char* subTagName) = 0;
    virtual bool IsValidAttributeName(char* tagName, char* attrName) = 0;
    virtual bool IsValidAttributeValue(char* tagName, char* attrName, char* attrValue) = 0;
    virtual char* GetRequiredAttribute(char* tagName, int index) = 0;
    virtual bool CanHaveValue(char* tagName) = 0;
};

class XMLTag
{
public:
    XMLTag();
    XMLTag(char* tagName);
    ~XMLTag();
    
    bool ParseTag(StringParser* parser, DTDVerifier* verifier, char* errorBuffer = NULL, int errorBufferSize = 0);
    
    char* GetAttributeValue(const char* attrName);
    char* GetValue() { return fValue; }
    char* GetTagName() { return fTag; }
    
    UInt32 GetNumEmbeddedTags() { return fEmbeddedTags.GetLength(); }
    
    XMLTag* GetEmbeddedTag(const UInt32 index = 0);
    XMLTag* GetEmbeddedTagByName(const char* tagName, const UInt32 index = 0);
    XMLTag* GetEmbeddedTagByAttr(const char* attrName, const char* attrValue, const UInt32 index = 0);
    XMLTag* GetEmbeddedTagByNameAndAttr(const char* tagName, const char* attrName, const char* attrValue, const UInt32 index = 0);
    
    void AddAttribute(char* attrName, char* attrValue);
    void RemoveAttribute(char* attrName);
    void AddEmbeddedTag(XMLTag* tag);
    void RemoveEmbeddedTag(XMLTag* tag);
    
    void SetTagName( char* name);
    void SetValue( char* value);
    
    void FormatData(ResizeableStringFormatter* formatter, UInt32 indent);

private:
    void ConsumeIfComment(StringParser* parser);

    char* fTag;
    char* fValue;
    OSQueue fAttributes;
    OSQueue fEmbeddedTags;
    
    OSQueueElem fElem;

    static UInt8 sNonNameMask[];        // stop when you hit a word
};

class XMLAttribute
{
public:
    XMLAttribute();
    ~XMLAttribute();
    
    char* fAttrName;
    char* fAttrValue;
    
    OSQueueElem fElem;
};

class XMLParser
{
public:
    XMLParser( char* inPath, DTDVerifier* verifier = NULL);
    ~XMLParser();
    
    // Check for existence, man.
    Bool16  DoesFileExist();
    Bool16  DoesFileExistAsDirectory();
    Bool16  CanWriteFile();
    
    Bool16  ParseFile(char* errorBuffer = NULL, int errorBufferSize = 0);
        
    XMLTag* GetRootTag() { return fRootTag; }
    void SetRootTag(XMLTag* tag);
    
    void WriteToFile(char** fileHeader);
    
private:
    XMLTag*         fRootTag;
        
    OSFileSource    fFile;
    char*           fFilePath;
    DTDVerifier*    fVerifier;
};

#endif

/*
 *
 * @APPLE_LICENSE_HEADER_START@
 * 
 * Copyright (c) 1999-2003 Apple Computer, Inc.  All Rights Reserved.
 * 
 * This file contains Original Code and/or Modifications of Original Code
 * as defined in and that are subject to the Apple Public Source License
 * Version 2.0 (the 'License'). You may not use this file except in
 * compliance with the License. Please obtain a copy of the License at
 * http://www.opensource.apple.com/apsl/ and read it before using this
 * file.
 * 
 * The Original Code and all software distributed under the License are
 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
 * Please see the License for the specific language governing rights and
 * limitations under the License.
 * 
 * @APPLE_LICENSE_HEADER_END@
 *
 */

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

#ifndef __Win32__
#include <unistd.h>
#endif

#include "XMLParser.h"
#include "OSMemory.h"

XMLParser::XMLParser( char* inPath, DTDVerifier* verifier)
    : fRootTag(NULL), fFilePath(NULL)
{
    StrPtrLen thePath(inPath);
    fFilePath = thePath.GetAsCString();
    fFile.Set(inPath);
    fVerifier = verifier;
}

XMLParser::~XMLParser()
{
    if (fRootTag)
        delete fRootTag;

    delete [] fFilePath;
}

Bool16 XMLParser::ParseFile(char* errorBuffer, int errorBufferSize)
{
    if (fRootTag != NULL)
    {
        delete fRootTag;    // flush old data
        fRootTag = NULL;
    }
    
    fFile.Set(fFilePath);

    if (errorBufferSize < 500) errorBuffer = NULL;  // Just a hack to avoid checking everywhere
    if ((fFile.GetLength() == 0) || fFile.IsDir())
    {
        if (errorBuffer != NULL)
            qtss_sprintf(errorBuffer, "Couldn't read xml file");
        return false;   // we don't have a valid file;
    }
    
    char* fileData = NEW char[ (SInt32) (fFile.GetLength() + 1)];
    UInt32 theLengthRead = 0;
    fFile.Read(0, fileData, (UInt32) fFile.GetLength(), &theLengthRead); 

    StrPtrLen theDataPtr(fileData, theLengthRead);
    StringParser theParser(&theDataPtr);
    
    fRootTag = NEW XMLTag();
    Bool16 result = fRootTag->ParseTag(&theParser, fVerifier, errorBuffer, errorBufferSize);
    if (!result)
    {
        // got error parsing file
        delete fRootTag;
        fRootTag = NULL;
    }
    
    delete fileData;
    
    fFile.Close();

    return result;
}

Bool16  XMLParser::DoesFileExist()
{
    Bool16 itExists = false;
    fFile.Set(fFilePath);
    if ((fFile.GetLength() > 0) && (!fFile.IsDir()))
        itExists = true;
    fFile.Close();
    
    return itExists;
}

Bool16  XMLParser::DoesFileExistAsDirectory()
{
    Bool16 itExists = false;
    fFile.Set(fFilePath);
    if (fFile.IsDir())
        itExists = true;
    fFile.Close();
    
    return itExists;
}

Bool16  XMLParser::CanWriteFile()
{
    //
    // First check if it exists for reading
    FILE* theFile = ::fopen(fFilePath, "r");
    if (theFile == NULL)
        return true;
    
    ::fclose(theFile);
    
    //
    // File exists for reading, check if we can write it
    theFile = ::fopen(fFilePath, "a");
    if (theFile == NULL)
        return false;
        
    //
    // We can read and write
    ::fclose(theFile);
    return true;
}

void XMLParser::SetRootTag(XMLTag* tag)
{
    if (fRootTag != NULL)
        delete fRootTag;
    fRootTag = tag;
}
    
void XMLParser::WriteToFile(char** fileHeader)
{
    char theBuffer[8192];
    ResizeableStringFormatter formatter(theBuffer, 8192);
    
    //
    // Write the file header
    for (UInt32 a = 0; fileHeader[a] != NULL; a++)
    {
        formatter.Put(fileHeader[a]);
        formatter.Put(kEOLString);
    }
    
        if (fRootTag)
                fRootTag->FormatData(&formatter, 0);

    //
    // New libC code. This seems to work better on Win32
    formatter.PutTerminator();
    FILE* theFile = ::fopen(fFilePath, "w");
    if (theFile == NULL)
        return;
        
    qtss_fprintf(theFile, "%s", formatter.GetBufPtr());
    ::fclose(theFile);
    
#if __MacOSX__
    (void) ::chown(fFilePath,76,80);//owner qtss, group admin
#endif

#ifndef __Win32__
    ::chmod(fFilePath, S_IRUSR | S_IWUSR | S_IRGRP );
#endif
}

UInt8 XMLTag::sNonNameMask[] =
{
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, //0-9 
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, //10-19 
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, //20-29
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, //30-39 
    1, 1, 1, 1, 1, 0, 0, 1, 0, 0, //40-49 '.' and '-' are name chars
    0, 0, 0, 0, 0, 0, 0, 0, 0, 1, //50-59 ':' is a name char
    1, 1, 1, 1, 1, 0, 0, 0, 0, 0, //60-69 //stop on every character except a letter or number
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //70-79
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //80-89
    0, 1, 1, 1, 1, 0, 1, 0, 0, 0, //90-99 '_' is a name char
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //100-109
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //110-119
    0, 0, 0, 1, 1, 1, 1, 1, 1, 1, //120-129
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, //130-139
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, //140-149
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, //150-159
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, //160-169
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, //170-179
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, //180-189
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, //190-199
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, //200-209
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, //210-219
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, //220-229
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, //230-239
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, //240-249
    1, 1, 1, 1, 1, 1             //250-255
};

XMLTag::XMLTag() :
    fTag(NULL),
    fValue(NULL),
    fElem(NULL)
{ fElem = this;
}

XMLTag::XMLTag(char* tagName) :
    fTag(NULL),
    fValue(NULL),
    fElem(NULL)
{   fElem = this;
    StrPtrLen temp(tagName);
    fTag = temp.GetAsCString();
}

XMLTag::~XMLTag()
{
    if (fTag)
        delete fTag;
    if (fValue)
        delete fValue;      
        
    OSQueueElem* elem;
    while ((elem = fAttributes.DeQueue()) != NULL)
    {
        XMLAttribute* attr = (XMLAttribute*)elem->GetEnclosingObject();
        delete attr;
    }       

    while ((elem = fEmbeddedTags.DeQueue()) != NULL)
    {
        XMLTag* tag = (XMLTag*)elem->GetEnclosingObject();
        delete tag;
    }
    
    if (fElem.IsMemberOfAnyQueue())
        fElem.InQueue()->Remove(&fElem);    // remove from parent tag
}

void XMLTag::ConsumeIfComment(StringParser* parser)
{
    if ((parser->GetDataRemaining() > 2) && ((*parser)[1] == '-') && ((*parser)[2] == '-'))
    {
        // this is a comment, so skip to end of comment
        parser->ConsumeLength(NULL, 2); // skip '--'
        
        // look for -->
        while((parser->GetDataRemaining() > 2) && ((parser->PeekFast() != '-') ||
                ((*parser)[1] != '-') || ((*parser)[2] != '>')))
        {
            if (parser->PeekFast() == '-') parser->ConsumeLength(NULL, 1);
            parser->ConsumeUntil(NULL, '-');
        }
        
        if (parser->GetDataRemaining() > 2) parser->ConsumeLength(NULL, 3); // consume -->
    }
}

bool XMLTag::ParseTag(StringParser* parser, DTDVerifier* verifier, char* errorBuffer, int errorBufferSize)
{
    while (true)
    {
        if (!parser->GetThru(NULL, '<'))
        {
            if (errorBuffer != NULL)
                qtss_sprintf(errorBuffer, "Couldn't find a valid tag");
            return false;   // couldn't find beginning of tag
        }
            
        char c = parser->PeekFast();
        if (c == '/')
        {
            if (errorBuffer != NULL)
                qtss_sprintf(errorBuffer, "End tag with no begin tag on line %d", parser->GetCurrentLineNumber());
            return false;   // we shouldn't be seeing a close tag here
        }
            
        if ((c != '!') && (c != '?'))
            break;  // this should be the beginning of a regular tag
            
        ConsumeIfComment(parser);
        // otherwise this is a processing instruction or a c-data, so look for the next tag
    }
    
    int tagStartLine = parser->GetCurrentLineNumber();
    
    StrPtrLen temp;
    parser->ConsumeUntil(&temp, sNonNameMask);
    if (temp.Len == 0)
    {
        if (errorBuffer != NULL)
        {
            if (parser->GetDataRemaining() == 0)
                qtss_sprintf(errorBuffer, "Unexpected end of file on line %d", parser->GetCurrentLineNumber());
            else
                qtss_sprintf(errorBuffer, "Unexpected character (%c) on line %d", parser->PeekFast(), parser->GetCurrentLineNumber());
        }
        return false;   // bad file
    }
        
    fTag = temp.GetAsCString();
    
    parser->ConsumeWhitespace();
    while ((parser->PeekFast() != '>') && (parser->PeekFast() != '/'))
    {
        // we must have an attribute value for this tag
        XMLAttribute* attr = new XMLAttribute;
        fAttributes.EnQueue(&attr->fElem);
        parser->ConsumeUntil(&temp, sNonNameMask);
        if (temp.Len == 0)
        {
            if (errorBuffer != NULL)
            {
                if (parser->GetDataRemaining() == 0)
                    qtss_sprintf(errorBuffer, "Unexpected end of file on line %d", parser->GetCurrentLineNumber());
                else
                    qtss_sprintf(errorBuffer, "Unexpected character (%c) on line %d", parser->PeekFast(), parser->GetCurrentLineNumber());
            }
            return false;   // bad file
        }

        attr->fAttrName = temp.GetAsCString();

        if (!parser->Expect('='))
        {
            if (errorBuffer != NULL)
                qtss_sprintf(errorBuffer, "Missing '=' after attribute %s on line %d", attr->fAttrName, parser->GetCurrentLineNumber());
            return false;   // bad attribute specification
        }
        if (!parser->Expect('"'))
        {
            if (errorBuffer != NULL)
                qtss_sprintf(errorBuffer, "Attribute %s value not in quotes on line %d", attr->fAttrName, parser->GetCurrentLineNumber());
            return false;   // bad attribute specification
        }
            
        parser->ConsumeUntil(&temp, '"');
        attr->fAttrValue = temp.GetAsCString();
        if (!parser->Expect('"'))
        {
            if (errorBuffer != NULL)
                qtss_sprintf(errorBuffer, "Attribute %s value not in quotes on line %d", attr->fAttrName, parser->GetCurrentLineNumber());
            return false;   // bad attribute specification
        }
        
        if (verifier && !verifier->IsValidAttributeName(fTag, attr->fAttrName))
        {
            if (errorBuffer != NULL)
                qtss_sprintf(errorBuffer, "Attribute %s not allowed in tag %s on line %d", attr->fAttrName, fTag, parser->GetCurrentLineNumber());
            return false;   // bad attribute specification
        }

        if (verifier && !verifier->IsValidAttributeValue(fTag, attr->fAttrName, attr->fAttrValue))
        {
            if (errorBuffer != NULL)
                qtss_sprintf(errorBuffer, "Bad value for attribute %s on line %d", attr->fAttrName, parser->GetCurrentLineNumber());
            return false;   // bad attribute specification
        }

        parser->ConsumeWhitespace();
    }
    
    if (parser->PeekFast() == '/')
    {
        // this is an empty element tag, i.e. no contents or end tag (e.g <TAG attr="value" />
        parser->Expect('/');
        if (!parser->Expect('>'))
        {
            if (errorBuffer != NULL)
                qtss_sprintf(errorBuffer, "'>' must follow '/' on line %d", parser->GetCurrentLineNumber());
            return false;   // bad attribute specification
        }
        
        return true;    // we're done with this tag
    }
    
    if (!parser->Expect('>'))
    {
        if (errorBuffer != NULL)
            qtss_sprintf(errorBuffer, "Bad format for tag <%s> on line %d", fTag, parser->GetCurrentLineNumber());
        return false;   // bad attribute specification
    }
    
    while(true)
    {
        parser->ConsumeUntil(&temp, '<');   // this is either value or whitespace
        if (parser->GetDataRemaining() < 4)
        {
            if (errorBuffer != NULL)
                qtss_sprintf(errorBuffer, "Reached end of file without end for tag <%s> declared on line %d", fTag, tagStartLine);
            return false;
        }
        if ((*parser)[1] == '/')
        {
            // we'll only assign a value if there were no embedded tags
            if (fEmbeddedTags.GetLength() == 0 && (!verifier || verifier->CanHaveValue(fTag)))
                fValue = temp.GetAsCString();
            else
            {
                // otherwise this needs to have been just whitespace
                StringParser tempParser(&temp);
                tempParser.ConsumeWhitespace();
                if (tempParser.GetDataRemaining() > 0)
                {
                    if (errorBuffer)
                    {
                        if (fEmbeddedTags.GetLength() > 0)
                            qtss_sprintf(errorBuffer, "Unexpected text outside of tag on line %d", tagStartLine);
                        else
                            qtss_sprintf(errorBuffer, "Tag <%s> on line %d not allowed to have data", fTag, tagStartLine);
                    }
                }
            }
            break;  // we're all done with this tag
        }
        
        if (((*parser)[1] != '!') && ((*parser)[1] != '?'))
        {
            // this must be the beginning of an embedded tag
            XMLTag* tag = NEW XMLTag();
            fEmbeddedTags.EnQueue(&tag->fElem);
            if (!tag->ParseTag(parser, verifier, errorBuffer, errorBufferSize))
                return false;
                
            if (verifier && !verifier->IsValidSubtag(fTag, tag->GetTagName()))
            {
                if (errorBuffer != NULL)
                    qtss_sprintf(errorBuffer, "Tag %s not allowed in tag %s on line %d", tag->GetTagName(), fTag, parser->GetCurrentLineNumber());
                return false;   // bad attribute specification
            }
        }
        else
        {
            parser->ConsumeLength(NULL, 1); // skip '<'
            ConsumeIfComment(parser);
        }
    }

    parser->ConsumeLength(NULL, 2); // skip '</'
    parser->ConsumeUntil(&temp, sNonNameMask);
    if (!temp.Equal(fTag))
    {
        char* newTag = temp.GetAsCString();
        if (errorBuffer != NULL)
            qtss_sprintf(errorBuffer, "End tag </%s> on line %d doesn't match tag <%s> declared on line %d", newTag, parser->GetCurrentLineNumber(),fTag, tagStartLine);
        delete newTag;
        return false;   // bad attribute specification
    }
    
    if (!parser->GetThru(NULL, '>'))
    {
        if (errorBuffer != NULL)
            qtss_sprintf(errorBuffer, "Couldn't find end of tag <%s> declared on line %d", fTag, tagStartLine);
        return false;   // bad attribute specification
    }
    
    return true;
}

char* XMLTag::GetAttributeValue(const char* attrName)
{
    for (OSQueueIter iter(&fAttributes); !iter.IsDone(); iter.Next())
    {
        XMLAttribute* attr = (XMLAttribute*)iter.GetCurrent()->GetEnclosingObject();
        if (!strcmp(attr->fAttrName, attrName))
            return attr->fAttrValue;
    }
    
    return NULL;
}

XMLTag* XMLTag::GetEmbeddedTag(const UInt32 index)
{
    if (fEmbeddedTags.GetLength() <= index)
        return NULL;
    
    OSQueueIter iter(&fEmbeddedTags);
    for (UInt32 i = 0; i < index; i++)
    {
        iter.Next();
    }
    OSQueueElem* result = iter.GetCurrent();
    
    return (XMLTag*)result->GetEnclosingObject();
}

XMLTag* XMLTag::GetEmbeddedTagByName(const char* tagName, const UInt32 index)
{
    if (fEmbeddedTags.GetLength() <= index)
        return NULL;
    
    XMLTag* result = NULL;
    UInt32 curIndex = 0;
    for (OSQueueIter iter(&fEmbeddedTags); !iter.IsDone(); iter.Next())
    {
        XMLTag* temp = (XMLTag*)iter.GetCurrent()->GetEnclosingObject();
        if (!strcmp(temp->GetTagName(), tagName))
        {
            if (curIndex == index)
            {
                result = temp;
                break;
            }
                
            curIndex++;
        }
    }
    
    return result;
}

XMLTag* XMLTag::GetEmbeddedTagByAttr(const char* attrName, const char* attrValue, const UInt32 index)
{
    if (fEmbeddedTags.GetLength() <= index)
        return NULL;
    
    XMLTag* result = NULL;
    UInt32 curIndex = 0;
    for (OSQueueIter iter(&fEmbeddedTags); !iter.IsDone(); iter.Next())
    {
        XMLTag* temp = (XMLTag*)iter.GetCurrent()->GetEnclosingObject();
        if ((temp->GetAttributeValue(attrName) != NULL) && (!strcmp(temp->GetAttributeValue(attrName), attrValue)))
        {
            if (curIndex == index)
            {
                result = temp;
                break;
            }
                
            curIndex++;
        }
    }
    
    return result;
}

XMLTag* XMLTag::GetEmbeddedTagByNameAndAttr(const char* tagName, const char* attrName, const char* attrValue, const UInt32 index)
{
    if (fEmbeddedTags.GetLength() <= index)
        return NULL;
    
    XMLTag* result = NULL;
    UInt32 curIndex = 0;
    for (OSQueueIter iter(&fEmbeddedTags); !iter.IsDone(); iter.Next())
    {
        XMLTag* temp = (XMLTag*)iter.GetCurrent()->GetEnclosingObject();
        if (!strcmp(temp->GetTagName(), tagName) && (temp->GetAttributeValue(attrName) != NULL) && 
            (!strcmp(temp->GetAttributeValue(attrName), attrValue)))
        {
            if (curIndex == index)
            {
                result = temp;
                break;
            }
                
            curIndex++;
        }
    }
    
    return result;
}

void XMLTag::AddAttribute( char* attrName, char* attrValue)
{
    XMLAttribute* attr = NEW XMLAttribute;
    StrPtrLen temp(attrName);
    attr->fAttrName = temp.GetAsCString();
    temp.Set(attrValue);
    attr->fAttrValue = temp.GetAsCString();
    
    fAttributes.EnQueue(&attr->fElem);
}

void XMLTag::RemoveAttribute(char* attrName)
{
    for (OSQueueIter iter(&fAttributes); !iter.IsDone(); iter.Next())
    {
        XMLAttribute* attr = (XMLAttribute*)iter.GetCurrent()->GetEnclosingObject();
        if (!strcmp(attr->fAttrName, attrName))
        {
            fAttributes.Remove(&attr->fElem);
            delete attr;
            return;
        }
    }
}

void XMLTag::AddEmbeddedTag(XMLTag* tag)
{
    fEmbeddedTags.EnQueue(&tag->fElem);
}

void XMLTag::RemoveEmbeddedTag(XMLTag* tag)
{
    fEmbeddedTags.Remove(&tag->fElem);
}

void XMLTag::SetTagName( char* name)
{
    Assert (name != NULL);  // can't have a tag without a name!
    
    if (fTag != NULL)
        delete fTag;
        
    StrPtrLen temp(name);
    fTag = temp.GetAsCString();
}
    
void XMLTag::SetValue( char* value)
{
    if (fEmbeddedTags.GetLength() > 0)
        return;     // can't have a value with embedded tags
        
    if (fValue != NULL)
        delete fValue;
        
    if (value == NULL)
        fValue = NULL;
    else
    {
        StrPtrLen temp(value);
        fValue = temp.GetAsCString();
    }
}
    
void XMLTag::FormatData(ResizeableStringFormatter* formatter, UInt32 indent)
{
    for (UInt32 i=0; i<indent; i++) formatter->PutChar('\t');

    formatter->PutChar('<');
    formatter->Put(fTag);
    if (fAttributes.GetLength() > 0)
    {
        formatter->PutChar(' ');
        for (OSQueueIter iter(&fAttributes); !iter.IsDone(); iter.Next())
        {
            XMLAttribute* attr = (XMLAttribute*)iter.GetCurrent()->GetEnclosingObject();
            formatter->Put(attr->fAttrName);
            formatter->Put("=\"");
            formatter->Put(attr->fAttrValue);
            formatter->Put("\" ");
        }
    }
    formatter->PutChar('>');
    
    if (fEmbeddedTags.GetLength() == 0)
    {
        if (fValue > 0)
            formatter->Put(fValue);
    }
    else
    {
        formatter->Put(kEOLString);
        for (OSQueueIter iter(&fEmbeddedTags); !iter.IsDone(); iter.Next())
        {
            XMLTag* current = (XMLTag*)iter.GetCurrent()->GetEnclosingObject();
            current->FormatData(formatter, indent + 1);
        }

        for (UInt32 i=0; i<indent; i++) formatter->PutChar('\t');
    }
    
    formatter->Put("</");
    formatter->Put(fTag);
    formatter->PutChar('>');
    formatter->Put(kEOLString);
}

XMLAttribute::XMLAttribute()
    : fAttrName(NULL),
    fAttrValue(NULL)
{   fElem = this;
}

XMLAttribute::~XMLAttribute()
{
    if (fAttrName)
        delete fAttrName;
    if (fAttrValue)
        delete fAttrValue;      
}





  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
python模块详解 各个模块的详解 核心模块 1.1. 介绍 1.2. _ _builtin_ _ 模块 1.3. exceptions 模块 1.4. os 模块 1.5. os.path 模块 1.6. stat 模块 1.7. string 模块 1.8. re 模块 1.9. math 模块 1.10. cmath 模块 1.11. operator 模块 1.12. copy 模块 1.13. sys 模块 1.14. atexit 模块 1.15. time 模块 1.16. types 模块 1.17. gc 模块 更多标准模块 2.1. 概览 2.2. fileinput 模块 2.3. shutil 模块 2.4. tempfile 模块 2.5. StringIO 模块 2.6. cStringIO 模块 2.7. mmap 模块 2.8. UserDict 模块 2.9. UserList 模块 2.10. UserString 模块 2.11. traceback 模块 2.12. errno 模块 2.13. getopt 模块 2.14. getpass 模块 2.15. glob 模块 2.16. fnmatch 模块 2.17. random 模块 2.18. whrandom 模块 2.19. md5 模块 2.20. sha 模块 2.21. crypt 模块 2.22. rotor 模块 2.23. zlib 模块 2.24. code 模块 线程和进程 3.1. 概览 3.2. threading 模块 3.3. Queue 模块 3.4. thread 模块 3.5. commands 模块 3.6. pipes 模块 3.7. popen2 模块 3.8. signal 模块 数据表示 4.1. 概览 4.2. array 模块 4.3. struct 模块 4.4. xdrlib 模块 4.5. marshal 模块 4.6. pickle 模块 4.7. cPickle 模块 4.8. copy_reg 模块 4.9. pprint 模块 4.10. repr 模块 4.11. base64 模块 4.12. binhex 模块 4.13. quopri 模块 4.14. uu 模块 4.15. binascii 模块 文件格式 5.1. 概览 5.2. xmllib 模块 5.3. xml.parsers.expat 模块 5.4. sgmllib 模块 5.5. htmllib 模块 5.6. htmlentitydefs 模块 5.7. formatter 模块 5.8. ConfigParser 模块 5.9. netrc 模块 5.10. shlex 模块 5.11. zipfile 模块 5.12. gzip 模块 邮件和新闻消息处理 6.1. 概览 6.2. rfc822 模块 6.3. mimetools 模块 6.4. MimeWriter 模块 6.5. mailbox 模块 6.6. mailcap 模块 6.7. mimetypes 模块 6.8. packmail 模块 6.9. mimify 模块 6.10. multifile 模块 网络协议 7.1. 概览 7.2. socket 模块 7.3. select 模块 7.4. asyncore 模块 7.5. asynchat 模块 7.6. urllib 模块 7.7. urlparse 模块 7.8. cookie 模块 7.9. robotparser 模块 7.10. ftplib 模块 7.11. gopherlib 模块 7.12. httplib 模块 7.13. poplib 模块 7.14. imaplib 模块 7.15. smtplib 模块 7.16. telnetlib 模块 7.17. nntplib 模块 7.18. SocketServer 模块 7.19. BaseHTTPServer 模块 7.20. SimpleHTTPServer 模块 7.21. CGIHTTPServer 模块 7.22. cgi 模块 7.23. webbrowser 模块 国际化 8.1. locale 模块 8.2. unicodedata 模块 8.3. ucnhash 模块 多媒体相关模块 9.1. 概览 9.2. imghdr 模块 9.3. sndhdr 模块 9.4. whatsound 模块 9.5. aifc 模块 9.6. sunau 模块 9.7. sunaudio 模块 9.8. wave 模块 9.9. audiodev 模块 9.10. winsound 模块 数据储存 10.1. 概览 10.2. anydbm 模块 10.3. whichdb 模块 10.4. shelve 模块 10.5. dbhash 模块 10.6. dbm 模块 10.7. dumbdbm 模块 10.8. gdbm 模块 工具和实用程序 11.1. dis 模块 11.2. pdb 模块 11.3. bdb 模块 11.4. profile 模块 11.5. pstats 模块 11.6. tabnanny 模块 其他模块 12.1. 概览 12.2. fcntl 模块 12.3. pwd 模块 12.4. grp 模块 12.5. nis 模块 12.6. curses 模块 12.7. termios 模块 12.8. tty 模块 12.9. resource 模块 12.10. syslog 模块 12.11. msvcrt 模块 12.12. nt 模块 12.13. _winreg 模块 12.14. posix 模块 执行支持模块 13.1. dospath 模块 13.2. macpath 模块 13.3. ntpath 模块 13.4. posixpath 模块 13.5. strop 模块 13.6. imp 模块 13.7. new 模块 13.8. pre 模块 13.9. sre 模块 13.10. py_compile 模块 13.11. compileall 模块 13.12. ihooks 模块 13.13. linecache 模块 13.14. macurl2path 模块 13.15. nturl2path 模块 13.16. tokenize 模块 13.17. keyword 模块 13.18. parser 模块 13.19. symbol 模块 13.20. token 模块 其他模块 14.1. 概览 14.2. pyclbr 模块 14.3. filecmp 模块 14.4. cmd 模块 14.5. rexec 模块 14.6. Bastion 模块 14.7. readline 模块 14.8. rlcompleter 模块 14.9. statvfs 模块 14.10. calendar 模块 14.11. sched 模块 14.12. statcache 模块 14.13. grep 模块 14.14. dircache 模块 14.15. dircmp 模块 14.16. cmp 模块 14.17. cmpcache 模块 14.18. util 模块 14.19. soundex 模块 14.20. timing 模块 14.21. posixfile 模块 14.22. bisect 模块 14.23. knee 模块 14.24. tzparse 模块 14.25. regex 模块 14.26. regsub 模块 14.27. reconvert 模块 14.28. regex_syntax 模块 14.29. find 模块

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

sunxiaopengsun

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值