📄 ixmlparser.c
字号:
/*==============================================================================*
* Parser_UTF8ToInt
* In UTF-8, characters are encoded using sequences of 1 to 6 octets.
* This functions will return a UTF-8 character value and its octets number.
* Internal to parser only.
* Internal to parser only
*
*===============================================================================*/
static int
Parser_UTF8ToInt( IN char *ss,
OUT int *len )
{
unsigned char *s = ( unsigned char * )ss;
int c = *s;
if( c <= 127 ) { // if c<=127, c is just the character.
*len = 1;
return c;
} else if( ( c & 0xE0 ) == 0xC0 && ( s[1] & 0xc0 ) == 0x80 ) { // a sequence of 110xxxxx and 10xxxxxx?
*len = 2;
return ( ( ( c & 0x1f ) << 6 ) | ( s[1] & 0x3f ) );
} else if( ( c & 0xF0 ) == 0xE0 && ( s[1] & 0xc0 ) == 0x80 && ( s[2] & 0xc0 ) == 0x80 ) { // a sequence of 1110xxxx,10xxxxxx and 10xxxxxx ?
*len = 3;
return ( ( ( c & 0xf ) << 12 ) | ( ( s[1] & 0x3f ) << 6 ) |
( s[2] & 0x3f ) );
} else if( ( c & 0xf8 ) == 0xf0 && ( s[1] & 0xc0 ) == 0x80 && ( s[2] & 0xc0 ) == 0x80 && ( s[3] & 0xc0 ) == 0x80 ) { // a sequence of 11110xxx,10xxxxxx,10xxxxxx and 10xxxxxx ?
*len = 4;
return ( ( ( c & 0x7 ) << 18 ) | ( ( s[1] & 0x3f ) << 12 ) |
( ( s[2] & 0x3f ) << 6 ) | ( s[3] & 0x3f ) );
} else if( ( c & 0xfc ) == 0xf8 && ( s[1] & 0xc0 ) == 0x80 && ( s[2] & 0xc0 ) == 0x80 && ( s[3] & 0xc0 ) == 0x80 && ( s[4] & 0xc0 ) == 0x80 ) { // a sequence of 111110xx,10xxxxxx,10xxxxxx,10xxxxxx,10xxxxxx ?
*len = 5;
return ( ( ( c & 0x3 ) << 24 ) | ( ( s[1] & 0x3f ) << 18 ) |
( ( s[2] & 0x3f ) << 12 ) | ( ( s[3] & 0x3f ) << 6 ) |
( s[4] & 0x3f ) );
} else if( ( c & 0xfe ) == 0xfc && ( s[1] & 0xc0 ) == 0x80 && ( s[2] & 0xc0 ) == 0x80 && ( s[3] & 0xc0 ) == 0x80 && ( s[4] & 0xc0 ) == 0x80 && ( s[5] & 0xc0 ) == 0x80 ) { // a sequence of 1111110x,10xxxxxx,10xxxxxx,10xxxxxx,10xxxxxx and 10xxxxxx ?
*len = 6;
return ( ( ( c & 0x1 ) << 30 ) | ( ( s[1] & 0x3f ) << 24 ) |
( ( s[2] & 0x3f ) << 18 ) | ( ( s[3] & 0x3f ) << 12 ) |
( ( s[4] & 0x3f ) << 6 ) | ( s[5] & 0x3f ) );
} else { // none of above, error
*len = 0;
return -1;
}
}
/*==============================================================================*
* Parser_init
* Initializes a xml parser.
* Internal to parser only
*
*===============================================================================*/
static Parser *
Parser_init( )
{
Parser *newParser = NULL;
newParser = ( Parser * ) malloc( sizeof( Parser ) );
if( newParser == NULL ) {
return NULL;
}
memset( newParser, 0, sizeof( Parser ) );
ixml_membuf_init( &( newParser->tokenBuf ) );
ixml_membuf_init( &( newParser->lastElem ) );
return newParser;
}
/*================================================================
* Parser_isValidEndElement
* check if a new node->nodeName matches top of element stack.
* Internal to parser only.
*
*=================================================================*/
static int
Parser_isValidEndElement( IN Parser * xmlParser,
IN IXML_Node * newNode )
{
return ( strcmp( xmlParser->pCurElement->element, newNode->nodeName )
== 0 );
}
/*===============================================================
* Parser_pushElement
* push a new element onto element stack
* Internal to parser only.
*
*=================================================================*/
static int
Parser_pushElement( IN Parser * xmlParser,
IN IXML_Node * newElement )
{
IXML_ElementStack *pCurElement = NULL;
IXML_ElementStack *pNewStackElement = NULL;
assert( newElement );
if( newElement != NULL ) {
// push new element
pNewStackElement =
( IXML_ElementStack * ) malloc( sizeof( IXML_ElementStack ) );
if( pNewStackElement == NULL ) {
return IXML_INSUFFICIENT_MEMORY;
}
memset( pNewStackElement, 0, sizeof( IXML_ElementStack ) );
// the element member includes both prefix and name
pNewStackElement->element = strdup( newElement->nodeName );
if( pNewStackElement->element == NULL ) {
free( pNewStackElement );
return IXML_INSUFFICIENT_MEMORY;
}
if( newElement->prefix != 0 ) {
pNewStackElement->prefix = strdup( newElement->prefix );
if( pNewStackElement->prefix == NULL ) {
Parser_freeElementStackItem( pNewStackElement );
free( pNewStackElement );
return IXML_INSUFFICIENT_MEMORY;
}
}
if( newElement->namespaceURI != 0 ) {
pNewStackElement->namespaceUri =
strdup( newElement->namespaceURI );
if( pNewStackElement->namespaceUri == NULL ) {
Parser_freeElementStackItem( pNewStackElement );
free( pNewStackElement );
return IXML_INSUFFICIENT_MEMORY;
}
}
pCurElement = xmlParser->pCurElement;
// insert the new element into the top of the stack
pNewStackElement->nextElement = pCurElement;
xmlParser->pCurElement = pNewStackElement;
}
return IXML_SUCCESS;
}
/*================================================================
* Parser_popElement
* Remove element from element stack.
* Internal to parser only.
*
*=================================================================*/
static void
Parser_popElement( IN Parser * xmlParser )
{
IXML_ElementStack *pCur = NULL;
IXML_NamespaceURI *pnsUri = NULL,
*pNextNS = NULL;
pCur = xmlParser->pCurElement;
if( pCur != NULL ) {
xmlParser->pCurElement = pCur->nextElement;
Parser_freeElementStackItem( pCur );
pnsUri = pCur->pNsURI;
while( pnsUri != NULL ) {
pNextNS = pnsUri->nextNsURI;
Parser_freeNsURI( pnsUri );
free( pnsUri );
pnsUri = pNextNS;
}
free( pCur );
}
}
/*================================================================
* Parser_readFileOrBuffer
* read a xml file or buffer contents into xml parser.
* Internal to parser only.
*
*=================================================================*/
static int
Parser_readFileOrBuffer( IN Parser * xmlParser,
IN char *xmlFileName,
IN BOOL file )
{
int fileSize = 0;
int bytesRead = 0;
FILE *xmlFilePtr = NULL;
if( file ) {
xmlFilePtr = fopen( xmlFileName, "rb" );
if( xmlFilePtr == NULL ) {
return IXML_NO_SUCH_FILE;
} else {
fseek( xmlFilePtr, 0, SEEK_END );
fileSize = ftell( xmlFilePtr );
if( fileSize == 0 ) {
fclose( xmlFilePtr );
return IXML_SYNTAX_ERR;
}
xmlParser->dataBuffer = ( char * )malloc( fileSize + 1 );
if( xmlParser->dataBuffer == NULL ) {
fclose( xmlFilePtr );
return IXML_INSUFFICIENT_MEMORY;
}
fseek( xmlFilePtr, 0, SEEK_SET );
bytesRead =
fread( xmlParser->dataBuffer, 1, fileSize, xmlFilePtr );
xmlParser->dataBuffer[bytesRead] = '\0'; // append null
fclose( xmlFilePtr );
}
} else {
xmlParser->dataBuffer = strdup( xmlFileName );
if( xmlParser->dataBuffer == NULL ) {
return IXML_INSUFFICIENT_MEMORY;
}
}
return IXML_SUCCESS;
}
/*================================================================
* Parser_LoadDocument
* parses a xml file and return the DOM tree.
* Internal to parser only
*
*=================================================================*/
int
Parser_LoadDocument( OUT IXML_Document ** retDoc,
IN char *xmlFileName,
IN BOOL file )
{
int rc = IXML_SUCCESS;
Parser *xmlParser = NULL;
xmlParser = Parser_init( );
if( xmlParser == NULL ) {
return IXML_INSUFFICIENT_MEMORY;
}
rc = Parser_readFileOrBuffer( xmlParser, xmlFileName, file );
if( rc != IXML_SUCCESS ) {
Parser_free( xmlParser );
return rc;
}
xmlParser->curPtr = xmlParser->dataBuffer;
rc = Parser_parseDocument( retDoc, xmlParser );
return rc;
}
/*================================================================
* isTopLevelElement
* decides whether we have top level element already.
* Internal to parser only.
*
*=================================================================*/
static int
isTopLevelElement( IN Parser * xmlParser )
{
assert( xmlParser );
return ( xmlParser->pCurElement == NULL );
}
/*================================================================
* isDuplicateAttribute
* Decide whether the new attribute is the same as an
* existing one.
* Internal to parser only.
*
*=================================================================*/
static int
isDuplicateAttribute( IN Parser * xmlParser,
IN IXML_Node * newAttrNode )
{
IXML_Node *elementNode = NULL;
IXML_Node *attrNode = NULL;
elementNode = xmlParser->currentNodePtr;
attrNode = elementNode->firstAttr;
while( attrNode != NULL ) {
if( strcmp( attrNode->nodeName, newAttrNode->nodeName ) == 0 ) {
return TRUE;
}
attrNode = attrNode->nextSibling;
}
return FALSE;
}
/*================================================================
* Parser_processAttributeName
* processes the attribute name.
* Internal to parser only.
*
*=================================================================*/
static int
Parser_processAttributeName( IN IXML_Document * rootDoc,
IN Parser * xmlParser,
IN IXML_Node * newNode )
{
IXML_Attr *attr = NULL;
int rc = IXML_SUCCESS;
if( isDuplicateAttribute( xmlParser, newNode ) == TRUE ) {
return IXML_SYNTAX_ERR;
}
rc = ixmlDocument_createAttributeEx( rootDoc, newNode->nodeName,
&attr );
if( rc != IXML_SUCCESS ) {
return rc;
}
rc = ixmlNode_setNodeProperties( ( IXML_Node * ) attr, newNode );
if( rc != IXML_SUCCESS ) {
return rc;
}
rc = ixmlElement_setAttributeNode( ( IXML_Element * ) xmlParser->
currentNodePtr, attr, NULL );
return rc;
}
/*================================================================
* Parser_processElementName
* Processes element name
* Internal to parser only.
*
*=================================================================*/
static int
Parser_processElementName( IN IXML_Document * rootDoc,
IN Parser * xmlParser,
IN IXML_Node * newNode )
{
IXML_Element *newElement = NULL;
char *nsURI = NULL;
int rc = IXML_SUCCESS;
if( xmlParser->bHasTopLevel == TRUE ) {
if( isTopLevelElement( xmlParser ) == TRUE ) {
return IXML_SYNTAX_ERR;
}
} else {
xmlParser->bHasTopLevel = TRUE;
}
xmlParser->savePtr = xmlParser->curPtr;
rc = ixmlDocument_createElementEx( rootDoc, newNode->nodeName,
&newElement );
if( rc != IXML_SUCCESS ) {
return rc;
}
rc = ixmlNode_setNodeProperties( ( IXML_Node * ) newElement, newNode );
if( rc != IXML_SUCCESS ) {
ixmlElement_free( newElement );
return rc;
}
if( newNode->prefix != NULL ) { // element has namespace prefix
if( Parser_ElementPrefixDefined( xmlParser, newNode, &nsURI ) !=
TRUE ) {
// read next node to see whether it includes namespace definition
xmlParser->pNeedPrefixNode = ( IXML_Node * ) newElement;
} else { // fill in the namespace
Parser_setElementNamespace( newElement, nsURI );
}
} else // does element has default namespace
{
// the node may have default namespace definition
if( Parser_hasDefaultNamespace( xmlParser, newNode, &nsURI ) ==
TRUE ) {
Parser_setElementNamespace( newElement, nsURI );
} else if( xmlParser->state == eATTRIBUTE ) {
// the default namespace maybe defined later
xmlParser->pNeedPrefixNode = ( IXML_Node * ) newElement;
}
}
rc = ixmlNode_appendChild( xmlParser->currentNodePtr,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -