⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ilibparsers.c

📁 解析xml格式的文件的好源码。解析xml格式的文件的好源码。解析xml格式的文件的好源码。解析xml格式的文件的好源码。解析xml格式的文件的好源码。
💻 C
📖 第 1 页 / 共 5 页
字号:
/*! \fn ILibGetXMLAttributes(struct ILibXMLNode *node)
	\breif Reads the attributes from an XML node
	\param node The node to read the attributes from
	\returns A linked list of attributes
*/
struct ILibXMLAttribute *ILibGetXMLAttributes(struct ILibXMLNode *node)
{
	struct ILibXMLAttribute *RetVal = NULL;
	struct ILibXMLAttribute *current = NULL;
	char *c;
	int EndReserved = (node->EmptyTag==0)?1:2;
	int i;
	int CheckName = node->Name[node->NameLength]==0?1:0;
	
	struct parser_result *xml;
	struct parser_result_field *field,*field2;
	struct parser_result *temp2;
	struct parser_result *temp3;
	

	//
	// The reserved field is used to show where the data segments start and stop. We
	// can also use them to figure out where the attributes start and stop
	//
	c = (char*)node->Reserved - 1;
	while(*c!='<')
	{
		//
		// The Reserved field of the StartElement points to the first character after
		// the '>' of the StartElement. Just work our way backwards to find the start of
		// the StartElement
		//
		c = c -1;
	}
	c = c +1;
	
	//
	// Now that we isolated the string in between the '<' and the '>' we can parse the
	// string as delimited by ' ', because thats what delineates attributes. We need
	// to use ILibParseStringAdv because these attributes can be within quotation marks
	//
	//
	// But before we start, replace linefeeds and carriage-return-linefeeds to spaces
	//

	for(i=0;i<(int)((char*)node->Reserved - c -EndReserved);++i)
	{
		if(c[i]==10 || c[i]==13 || c[i]==9 || c[i]==0)
		{
			c[i]=' ';
		}
	}
	
	xml = ILibParseStringAdv(c,0,(int)((char*)node->Reserved - c -EndReserved)," ",1);
	field = xml->FirstResult;
	//
	// We skip the first token, because the first token, is the Element name
	//
	if(field!=NULL) {field = field->NextResult;}

	//
	// Iterate through all the other tokens, as these are all attributes
	//
	while(field!=NULL)
	{
		if(field->datalength>0)
		{
			if(RetVal==NULL)
			{
				//
				// If we haven't already created an Attribute node, create it now
				//
				RetVal = (struct ILibXMLAttribute*)malloc(sizeof(struct ILibXMLAttribute));
				RetVal->Next = NULL;
			}
			else
			{
				//
				// We already created an Attribute node, so simply create a new one, and
				// attach it on the beginning of the old one.
				//
				current = (struct ILibXMLAttribute*)malloc(sizeof(struct ILibXMLAttribute));
				current->Next = RetVal;
				RetVal = current;
			}

			//
			// Parse each token by the ':'
			// If this results in more than one token, we can figure that the first token
			// is the namespace prefix
			//
			temp2 = ILibParseStringAdv(field->data,0,field->datalength,":",1);
			if(temp2->NumResults==1)
			{
				//
				// This attribute has no prefix, so just parse on the '='
				// The first token is the attribute name, the other is the value
				//
				RetVal->Prefix = NULL;
				RetVal->PrefixLength = 0;
				temp3 = ILibParseStringAdv(field->data,0,field->datalength,"=",1);
				if(temp3->NumResults==1)
				{
					//
					// There were whitespaces around the '='
					//
					field2 = field->NextResult;
					while(field2!=NULL)
					{
						if(!(field2->datalength==1 && memcmp(field2->data,"=",1)==0) && field2->datalength>0)
						{
							ILibDestructParserResults(temp3);
							temp3 = ILibParseStringAdv(field->data,0,(int)((field2->data-field->data)+field2->datalength),"=",1);
							field = field2;
							break;
						}
						field2 = field2->NextResult;
					}
				}
			}
			else
			{
				//
				// Since there is a namespace prefix, seperate that out, and parse the remainder
				// on the '=' to figure out what the attribute name and value are
				//
				RetVal->Prefix = temp2->FirstResult->data;
				RetVal->PrefixLength = temp2->FirstResult->datalength;
				temp3 = ILibParseStringAdv(field->data,RetVal->PrefixLength+1,field->datalength-RetVal->PrefixLength-1,"=",1);
				if(temp3->NumResults==1)
				{
					//
					// There were whitespaces around the '='
					//
					field2 = field->NextResult;
					while(field2!=NULL)
					{
						if(!(field2->datalength==1 && memcmp(field2->data,"=",1)==0) && field2->datalength>0)
						{
							ILibDestructParserResults(temp3);
							temp3 = ILibParseStringAdv(field->data,RetVal->PrefixLength+1,(int)((field2->data-field->data)+field2->datalength-RetVal->PrefixLength-1),"=",1);
							field = field2;
							break;
						}
						field2 = field2->NextResult;
					}
				}			
			}
			//
			// After attaching the pointers, we can free the results, as all the data
			// is a pointer into the original string. We can think of the nodes we created
			// as templates. Once done, we don't need them anymore.
			//
			ILibDestructParserResults(temp2);
			RetVal->Parent = node;
			RetVal->Name = temp3->FirstResult->data;
			RetVal->Value = temp3->LastResult->data;
			RetVal->NameLength = ILibTrimString(&(RetVal->Name),temp3->FirstResult->datalength);
			RetVal->ValueLength = ILibTrimString(&(RetVal->Value),temp3->LastResult->datalength);
			// 
			// Remove the Quote or Apostraphe if it exists
			//
			if(RetVal->ValueLength>=2 && (RetVal->Value[0]=='"' || RetVal->Value[0]=='\''))
			{
				RetVal->Value += 1;
				RetVal->ValueLength -= 2;
			}
			ILibDestructParserResults(temp3);
		}
		field = field->NextResult;
	}
	
	ILibDestructParserResults(xml);
	if(CheckName)
	{
		node->Name[node->NameLength]=0;
	}
	return(RetVal);
}

/*! \fn ILibParseXML(char *buffer, int offset, int length)
	\brief Parses an XML string.
	\para
	The strings are never copied. Everything is referenced via pointers into the original buffer
	\param buffer The string to parse
	\param offset starting index of \a buffer
	\param length Length of \a buffer
	\returns A tree of ILibXMLNodes, representing the XML document
*/
struct ILibXMLNode *ILibParseXML(char *buffer, int offset, int length)
{
	struct parser_result *xml;
	struct parser_result_field *field;
	struct parser_result *temp;
	struct parser_result *temp2;
	struct parser_result *temp3;
	char* TagName;
	int TagNameLength;
	int StartTag;
	int EmptyTag;
	int i;
	
	struct ILibXMLNode *RetVal = NULL;
	struct ILibXMLNode *current = NULL;
	struct ILibXMLNode *x = NULL;
	
	char *NSTag;
	int NSTagLength;

	//
	// Even though "technically" the first character of an XML document must be <
	// we're going to be nice, and not enforce that
	//
	while(buffer[offset]!='<' && length>0)
	{
		++offset;
		--length;
	}

	if(length==0)
	{
		// Garbage in Garbage out :)
		//RetVal = (struct ILibXMLNode*)malloc(sizeof(struct ILibXMLNode));
		//memset(RetVal,0,sizeof(struct ILibXMLNode));
		return(RetVal);
	}

	//
	// All XML Elements start with a '<' character. If we delineate the string with 
	// this character, we can go from there.
	//
	xml = ILibParseString(buffer,offset,length,"<",1);
	field = xml->FirstResult;
	while(field!=NULL)
	{
		//
		// Ignore the XML declarator
		//
		if(field->datalength !=0 && memcmp(field->data,"?",1)!=0)
		{
			EmptyTag = 0;
			if(memcmp(field->data,"/",1)==0)
			{
				//
				// The first character after the '<' was a '/', so we know this is the
				// EndElement
				//
				StartTag = 0;
				field->data = field->data+1;
				field->datalength -= 1;
				//
				// If we look for the '>' we can find the end of this element
				//
				temp2 = ILibParseString(field->data,0,field->datalength,">",1);
			}
			else
			{
				//
				// The first character after the '<' was not a '/' so we know this is a 
				// StartElement
				//
				StartTag = -1;
				//
				// If we look for the '>' we can find the end of this element
				//
				temp2 = ILibParseString(field->data,0,field->datalength,">",1);
				if(temp2->FirstResult->datalength>0 && temp2->FirstResult->data[temp2->FirstResult->datalength-1]=='/')
				{
					//
					// If this element ended with a '/' this is an EmptyElement
					//
					EmptyTag = -1;
				}
			}
			//
			// Parsing on the ' ', we can isolate the Element name from the attributes. 
			// The first token, being the element name
			//
			temp = ILibParseString(temp2->FirstResult->data,0,temp2->FirstResult->datalength," ",1);
			//
			// Now that we have the token that contains the element name, we need to parse on the ":"
			// because we need to figure out what the namespace qualifiers are
			//
			temp3 = ILibParseString(temp->FirstResult->data,0,temp->FirstResult->datalength,":",1);
			if(temp3->NumResults==1)
			{
				//
				// If there is only one token, there was no namespace prefix. 
				// The whole token is the attribute name
				//
				NSTag = NULL;
				NSTagLength = 0;
				TagName = temp3->FirstResult->data;
				TagNameLength = temp3->FirstResult->datalength;
			}
			else
			{
				//
				// The first token is the namespace prefix, the second is the attribute name
				//
				NSTag = temp3->FirstResult->data;
				NSTagLength = temp3->FirstResult->datalength;
				TagName = temp3->FirstResult->NextResult->data;
				TagNameLength = temp3->FirstResult->NextResult->datalength;
			}
			ILibDestructParserResults(temp3);
			
			//
			// Iterate through the tag name, to figure out what the exact length is, as
			// well as check to see if its an empty element
			//
			for(i=0;i<TagNameLength;++i)
			{
				if( (TagName[i]==' ')||(TagName[i]=='/')||(TagName[i]=='>')||(TagName[i]=='\t')||(TagName[i]=='\r')||(TagName[i]=='\n') )
				{
					if(i!=0)
					{
						if(TagName[i]=='/')
						{
							EmptyTag = -1;
						}
						TagNameLength = i;
						break;
					}
				}
			}
			
			if(TagNameLength!=0)
			{
				//
				// Instantiate a new ILibXMLNode for this element
				//
				x = (struct ILibXMLNode*)malloc(sizeof(struct ILibXMLNode));
				memset(x,0,sizeof(struct ILibXMLNode));
				x->Name = TagName;
				x->NameLength = TagNameLength;
				x->StartTag = StartTag;
				x->NSTag = NSTag;
				x->NSLength = NSTagLength;				
				
				if(StartTag==0)
				{
					//
					// The Reserved field of StartElements point to te first character before
					// the '<'.
					//
					x->Reserved = field->data;
					do
					{
					char *p = (char*)x->Reserved;
						p -= 1;
						x->Reserved = (void*)p;
					}while(*((char*)x->Reserved)=='<');
				}
				else
				{
					//
					// The Reserved field of EndElements point to the end of the element
					//
					x->Reserved = temp2->LastResult->data;
				}
				
				if(RetVal==NULL)
				{
					RetVal = x;
				}
				else
				{
					current->Next = x;
				}
				current = x;
				if(EmptyTag!=0)
				{
					//
					// If this was an empty element, we need to create a bogus EndElement, 
					// just so the tree is consistent. No point in introducing unnecessary complexity
					//
					x = (struct ILibXMLNode*)malloc(sizeof(struct ILibXMLNode));
					memset(x,0,sizeof(struct ILibXMLNode));
					x->Name = TagName;
					x->NameLength = TagNameLength;
					x->NSTag = NSTag;
					x->NSLength = NSTagLength;
										
					x->Reserved = current->Reserved;
					current->EmptyTag = -1;
					current->Next = x;
					current = x;
				}
			}
			
			ILibDestructParserResults(temp2);
			ILibDestructParserResults(temp);
		}
		field = field->NextResult;
	}
	
	ILibDestructParserResults(xml);
	return(RetVal);
}

/*! \fn ILibQueue_Create()
	\brief Create an empty Queue
	\returns An empty queue
*/
void *ILibQueue_Create()
{
	return(ILibLinkedList_Create());
}

/*! \fn ILibQueue_Lock(void *q)
	\brief Locks a queue
	\param q The queue to lock
*/
void ILibQueue_Lock(void *q)
{
	ILibLinkedList_Lock(q);
}

/*! \fn ILibQueue_UnLock(void *q)
	\brief Unlocks a queue
	\param q The queue to unlock
*/
void ILibQueue_UnLock(void *q)
{
	ILibLinkedList_UnLock(q);
}

/*! \fn ILibQueue_Destroy(void *q)
	\brief Frees the resources associated with a queue
	\param q The queue to free
*/
void ILibQueue_Destroy(void *q)
{
	ILibLinkedList_Destroy(q);
}

/*! \fn ILibQueue_IsEmpty(void *q)
	\brief Checks to see if a queue is empty
	\param q The queue to check
	\returns zero value if not empty, non-zero if empty
*/
int ILibQueue_IsEmpty(void *q)
{
	return(ILibLinkedList_GetNode_Head(q)==NULL?1:0);
}

/*! \fn ILibQueue_EnQueue(void *q, void *data)
	\brief Add an item to the queue
	\param q The queue to add to
	\param data The data to add to the queue
*/
void ILibQueue_EnQueue(void *q, void *data)
{
	ILibLinkedList_AddTail(q,data);
}
/*! \fn ILibQueue_DeQueue(void *q)
	\brief Removes an item from the queue
	\param q The queue to pop the item from
	\returns The item popped off the queue. NULL if empty
*/
void *ILibQueue_DeQueue(void *q)
{
	void *RetVal = NULL;
	void *node;

	node = ILibLinkedList_GetNode_Head(q);
	if(node!=NULL)
	{
		RetVal = ILibLinkedList_GetDataFromNode(node);
		ILibLinkedList_Remove(node);
	}
	return(RetVal);
}

/*! \fn ILibQueue_PeekQueue(void *q)
	\brief Peeks at an item from the queue
	\param q The queue to peek an item from
	\returns The item from the queue. NULL if empty
*/
void *ILibQueue_PeekQueue(void *q)
{
	void *RetVal = NULL;
	void *node;

	node = ILibLinkedList_GetNode_Head(q);
	if(node!=NULL)
	{
		RetVal = ILibLinkedList_GetDataFromNode(node);
	}
	return(RetVal);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -