Home | History | Annotate | Download | only in xml
      1 /*
      2  * Copyright (C) 2007 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #include <xml/xml_tinyParser.h>
     18 
     19 int32_t xml_errno;
     20 
     21 #ifdef XML_DOM_PARSER
     22 
     23 #define XML_IS_WHITESPACE(x) ((x) == '\t' || (x) == '\n' || (x) == ' ' || (x) == '\r')
     24 #define XML_IS_NAMECHAR(ch) (isalpha(ch) || isdigit(ch) || ch ==':' || \
     25                              ch == '_' || ch == '-' || ch =='.')
     26 
     27 static uint8_t *xml_ignore_blank(uint8_t *buffer)
     28 {
     29     if (NULL == buffer)
     30         return NULL;
     31 
     32     while (XML_IS_WHITESPACE(*buffer))
     33         buffer++;
     34 
     35     return buffer;
     36 }
     37 
     38 static uint8_t *xml_goto_tagend(uint8_t *buffer)
     39 {
     40     int32_t nameLen, valueLen;
     41     uint8_t *name, *value;
     42 
     43     if (NULL == buffer)
     44         return NULL;
     45 
     46     /* Ignore the start-tag */
     47     if (*buffer == '<') {
     48         buffer++;
     49         while (buffer != NULL && XML_IS_NAMECHAR(*buffer))
     50             buffer++;
     51         if (NULL == buffer)
     52             return NULL;
     53     }
     54 
     55     do {
     56         if (NULL == (buffer = xml_ignore_blank(buffer)))
     57             return NULL;
     58 
     59         if (*buffer == '>' || (*buffer == '/' && *(buffer + 1) == '>'))
     60             return buffer;
     61 
     62         if (NULL ==
     63             XML_DOM_getAttr(buffer, &name, &nameLen, &value, &valueLen))
     64             return NULL;
     65 
     66         buffer = value + valueLen + 1;
     67     } while (*buffer != '\0');
     68 
     69     return NULL;
     70 }
     71 
     72 static uint8_t *xml_match_tag(uint8_t *buffer)
     73 {
     74     int32_t tagLen, tagType, bal;
     75 
     76     if (NULL == buffer)
     77         return NULL;
     78 
     79     bal = 0;
     80     do {
     81         if (NULL == (buffer = XML_DOM_getTag(buffer, &tagLen, &tagType)))
     82             return NULL;
     83 
     84         switch (tagType) {
     85         case XML_TAG_SELF:
     86         case XML_TAG_START:
     87             if (NULL == (buffer = xml_goto_tagend(buffer + tagLen + 1)))
     88                 return NULL;
     89             if (strncmp((char *)buffer, "/>", 2) == 0) {
     90                 buffer += 2;
     91             } else {
     92                 bal++;
     93             }
     94             break;
     95 
     96         case XML_TAG_END:
     97             if (bal <= 0)
     98                 return NULL;
     99             buffer = buffer + tagLen + 2;
    100             bal--;
    101             break;
    102         }
    103     } while (bal != 0);
    104 
    105     return buffer;
    106 }
    107 
    108 uint8_t *XML_DOM_getAttr(uint8_t *buffer, uint8_t **pName, int32_t *nameLen,
    109                       uint8_t **pValue, int32_t *valueLen)
    110 {
    111     uint8_t charQuoted;
    112 
    113     if (NULL == buffer) {
    114         XML_ERROR(XML_ERROR_BUFFER_NULL);
    115         return NULL;
    116     }
    117 
    118     /* Ignore the tag */
    119     if (*buffer == '<') {
    120         buffer++;
    121         /* Ignore the STag */
    122         while (buffer != NULL && XML_IS_NAMECHAR(*buffer))
    123             buffer++;
    124         if (NULL == buffer)
    125             return NULL;
    126     }
    127 
    128     if (NULL == (buffer = xml_ignore_blank(buffer))) {
    129         XML_ERROR(XML_ERROR_BUFFER_NULL);
    130         return NULL;
    131     }
    132 
    133     /* Name */
    134     *pName = buffer;
    135     while (buffer != NULL && XML_IS_NAMECHAR(*buffer))
    136         buffer++;
    137     if (NULL == buffer) {
    138         XML_ERROR(XML_ERROR_ATTR_NAME);
    139         return NULL;
    140     }
    141     *nameLen = buffer - *pName;
    142     if (*nameLen <= 0) {
    143         XML_ERROR(XML_ERROR_ATTR_NAME);
    144         return NULL;
    145     }
    146 
    147     /* '=' */
    148     buffer = xml_ignore_blank(buffer);
    149     if (NULL == buffer || *buffer != '=') {
    150         XML_ERROR(XML_ERROR_ATTR_MISSED_EQUAL);
    151         return NULL;
    152     }
    153 
    154     /* Value */
    155     buffer++;
    156     buffer = xml_ignore_blank(buffer);
    157     if (NULL == buffer || (*buffer != '"' && *buffer != '\'')) {
    158         XML_ERROR(XML_ERROR_ATTR_VALUE);
    159         return NULL;
    160     }
    161     charQuoted = *buffer++;
    162     *pValue = buffer;
    163     while (*buffer != '\0' && *buffer != charQuoted)
    164         buffer++;
    165     if (*buffer != charQuoted) {
    166         XML_ERROR(XML_ERROR_ATTR_VALUE);
    167         return NULL;
    168     }
    169     *valueLen = buffer - *pValue;
    170 
    171     XML_ERROR(XML_ERROR_OK);
    172 
    173     return buffer + 1;
    174 }
    175 
    176 uint8_t *XML_DOM_getValue(uint8_t *buffer, uint8_t **pValue, int32_t *valueLen)
    177 {
    178     uint8_t *pEnd;
    179 
    180     if (NULL == buffer) {
    181         XML_ERROR(XML_ERROR_BUFFER_NULL);
    182         return NULL;
    183     }
    184 
    185     /* Ignore the STag */
    186     if (*buffer == '<') {
    187         buffer++;
    188         /* If it's an end_tag, no value should be returned */
    189         if (*buffer == '/') {
    190             *valueLen = 0;
    191             XML_ERROR(XML_ERROR_NOVALUE);
    192             return NULL;
    193         }
    194 
    195         while (buffer != NULL && XML_IS_NAMECHAR(*buffer))
    196             buffer++;
    197         if (NULL == buffer) {
    198             XML_ERROR(XML_ERROR_BUFFER_NULL);
    199             return NULL;
    200         }
    201 
    202         if (NULL == (buffer = xml_goto_tagend(buffer))) {
    203             XML_ERROR(XML_ERROR_PROPERTY_END);
    204             return NULL;
    205         }
    206     }
    207 
    208     /* <test/> node found */
    209     if (*buffer == '/') {
    210         if (*(buffer + 1) != '>') {
    211             XML_ERROR(XML_ERROR_PROPERTY_END);
    212             return NULL;
    213         }
    214         XML_ERROR(XML_ERROR_OK);
    215         *valueLen = 0;
    216         return buffer;
    217     }
    218 
    219     if (*buffer == '>')
    220         buffer++;
    221 
    222     if (NULL == (buffer = xml_ignore_blank(buffer))) {
    223         XML_ERROR(XML_ERROR_BUFFER_NULL);
    224         return NULL;
    225     }
    226 
    227     /* the following is a tag instead of the value */
    228     if (*buffer == '<') { /* nono value, such as <test></test> */
    229         buffer++;
    230         if (*buffer != '/') {
    231             XML_ERROR(XML_ERROR_ENDTAG);
    232             return NULL;
    233         }
    234         *valueLen = 0;
    235         XML_ERROR(XML_ERROR_OK);
    236         return NULL;
    237     }
    238 
    239     *pValue = buffer;
    240     pEnd = NULL;
    241     while (*buffer != '\0' && *buffer != '<') {
    242         if (!XML_IS_WHITESPACE(*buffer))
    243             pEnd = buffer;
    244         buffer++;
    245     }
    246     if (*buffer != '<' || pEnd == NULL) {
    247         XML_ERROR(XML_ERROR_VALUE);
    248         return NULL;
    249     }
    250 
    251     *valueLen = pEnd - *pValue + 1;
    252 
    253     buffer++;
    254     if (*buffer != '/') {
    255         XML_ERROR(XML_ERROR_ENDTAG);
    256         return NULL;
    257     }
    258 
    259     XML_ERROR(XML_ERROR_OK);
    260 
    261     return buffer - 1;
    262 }
    263 
    264 uint8_t *XML_DOM_getTag(uint8_t *buffer, int32_t *tagLen, int32_t *tagType)
    265 {
    266     uint8_t *pStart;
    267 
    268     /* WARNING: <!-- --> comment is not supported in this verison */
    269     if (NULL == buffer) {
    270         XML_ERROR(XML_ERROR_BUFFER_NULL);
    271         return NULL;
    272     }
    273 
    274     do {
    275         while (*buffer != '<') {
    276             if (*buffer == '\0') {
    277                 XML_ERROR(XML_ERROR_BUFFER_NULL);
    278                 return NULL;
    279             }
    280 
    281             if (*buffer == '\"' || *buffer == '\'') {
    282                 uint8_t charQuoted = *buffer;
    283                 buffer++;
    284                 while (*buffer != '\0' && *buffer != charQuoted)
    285                     buffer++;
    286                 if (*buffer == '\0') {
    287                     XML_ERROR(XML_ERROR_BUFFER_NULL);
    288                     return NULL;
    289                 }
    290             }
    291             buffer++;
    292         }
    293         buffer++;
    294     } while (*buffer == '!' || *buffer == '?');
    295 
    296     pStart = buffer - 1;
    297 
    298     if (*buffer == '/') {
    299         buffer++;
    300         *tagType = XML_TAG_END;
    301     } else {
    302         /* check here if it is self-end-tag */
    303         uint8_t *pCheck = xml_goto_tagend(pStart);
    304         if (pCheck == NULL) {
    305             XML_ERROR(XML_ERROR_PROPERTY_END);
    306             return NULL;
    307         }
    308 
    309         if (*pCheck == '>')
    310             *tagType = XML_TAG_START;
    311         else if (strncmp((char *)pCheck, "/>", 2) == 0)
    312             *tagType = XML_TAG_SELF;
    313         else {
    314             XML_ERROR(XML_ERROR_PROPERTY_END);
    315             return NULL;
    316         }
    317     }
    318 
    319     while (buffer != NULL && XML_IS_NAMECHAR(*buffer))
    320         buffer++;
    321     if (NULL == buffer) {
    322         XML_ERROR(XML_ERROR_BUFFER_NULL);
    323         return NULL;
    324     }
    325 
    326     if (*tagType == XML_TAG_END)
    327         *tagLen = buffer - pStart - 2;
    328     else
    329         *tagLen = buffer - pStart - 1;
    330 
    331     XML_ERROR(XML_ERROR_OK);
    332 
    333     return pStart;
    334 }
    335 
    336 uint8_t *XML_DOM_getNode(uint8_t *buffer, const uint8_t *const node)
    337 {
    338     uint8_t *pStart;
    339     uint8_t buf[XML_MAX_PROPERTY_LEN + 2];
    340     uint8_t *nodeStr = buf;
    341     uint8_t *retPtr = NULL;
    342     int32_t tagLen, tagType;
    343     uint8_t *lastNode = (uint8_t *)"";
    344 
    345     if (NULL == buffer) {
    346         XML_ERROR(XML_ERROR_BUFFER_NULL);
    347         return NULL;
    348     }
    349 
    350     strncpy((char *)nodeStr, (char *)node, XML_MAX_PROPERTY_LEN);
    351     strcat((char *)nodeStr, "\\");
    352     pStart = (uint8_t *)strchr((char *)nodeStr, '\\');
    353 
    354     while (pStart != NULL) {
    355         *pStart = '\0';
    356 
    357         /* get the first start_tag from buffer */
    358         if (NULL == (buffer = XML_DOM_getTag(buffer, &tagLen, &tagType))) {
    359             XML_ERROR(XML_ERROR_NO_SUCH_NODE);
    360             return NULL;
    361         }
    362 
    363         if (tagType == XML_TAG_END) {
    364             if (0 ==
    365                 strncmp((char *)lastNode, (char *)(buffer + 2), strlen((char *)lastNode)))
    366                 XML_ERROR(XML_ERROR_NO_SUCH_NODE);
    367             else
    368                 XML_ERROR(XML_ERROR_NO_START_TAG);
    369             return NULL;
    370         }
    371 
    372         /* wrong node, contiue to fetch the next node */
    373         if ((int32_t) strlen((char *)nodeStr) != tagLen
    374             || strncmp((char *)nodeStr, (char *)(buffer + 1), tagLen) != 0) {
    375             /* we should ignore all the middle code */
    376             buffer = xml_match_tag(buffer);
    377             continue;
    378         }
    379 
    380         retPtr = buffer;        /* retPtr starts with '<xxx>' */
    381         buffer += (tagLen + 1);
    382 
    383         if (tagType == XML_TAG_SELF) {
    384             nodeStr = pStart + 1;
    385             break;
    386         }
    387 
    388         lastNode = nodeStr;
    389         nodeStr = pStart + 1;
    390         pStart = (uint8_t *)strchr((char *)nodeStr, '\\');
    391     }
    392 
    393     /* Check 5: nodeStr should be empty here */
    394     if (*nodeStr != '\0') {
    395         XML_ERROR(XML_ERROR_NO_SUCH_NODE);
    396         return NULL;
    397     }
    398 
    399     XML_ERROR(XML_ERROR_OK);
    400 
    401     return retPtr;
    402 }
    403 
    404 uint8_t *XML_DOM_getNodeValue(uint8_t *buffer, uint8_t *node,
    405                            uint8_t **value, int32_t *valueLen)
    406 {
    407     uint8_t *pStart;
    408     uint8_t *lastTag;
    409 
    410     if (NULL == node || NULL == buffer) {
    411         XML_ERROR(XML_ERROR_BUFFER_NULL);
    412         return NULL;
    413     }
    414 
    415     lastTag = node + strlen((char *)node) - 1;
    416     while (lastTag >= node && *lastTag != '\\')
    417         lastTag--;
    418     lastTag++;
    419 
    420     if (NULL == (pStart = XML_DOM_getNode(buffer, node)))
    421         return NULL;
    422 
    423     pStart += (strlen((char *)lastTag) + 1);
    424 
    425     if (NULL == (pStart = xml_goto_tagend(pStart))) {
    426         XML_ERROR(XML_ERROR_PROPERTY_END);
    427         return NULL;
    428     }
    429 
    430     if (NULL == (pStart = XML_DOM_getValue(pStart, value, valueLen)))
    431         return NULL;
    432 
    433     /* Check the end tag */
    434 #ifdef XML_DOM_CHECK_ENDTAG
    435     if (strncmp((char *)pStart, "/>", 2) == 0) {
    436 
    437     } else if (strncmp((char *)lastTag, (char *)(pStart + 2), strlen((char *)lastTag)) !=
    438                0) {
    439         XML_ERROR(XML_ERROR_ENDTAG);
    440         return NULL;
    441     }
    442 #endif
    443 
    444     XML_ERROR(XML_ERROR_OK);
    445 
    446     return *value;
    447 }
    448 
    449 uint8_t *XML_DOM_getNextNode(uint8_t *buffer, uint8_t **pNodeName, int32_t *nodenameLen)
    450 {
    451     int32_t tagType;
    452 
    453     if (NULL == buffer)
    454         return NULL;
    455 
    456     do {
    457         if (NULL ==
    458             (buffer = XML_DOM_getTag(buffer + 1, nodenameLen, &tagType))) {
    459             XML_ERROR(XML_ERROR_NO_SUCH_NODE);
    460             return NULL;
    461         }
    462     } while (tagType == XML_TAG_END);
    463 
    464     *pNodeName = buffer + 1;
    465 
    466     XML_ERROR(XML_ERROR_OK);
    467 
    468     return buffer;
    469 }
    470 
    471 #endif /* XML_DOM_PARSER */
    472 
    473 #ifdef WBXML_DOM_PARSER
    474 
    475 #ifdef WBXML_OLD_VERSION
    476 uint8_t *WBXML_DOM_getNode(uint8_t *buffer, int32_t bufferLen,
    477                                  uint8_t *node)
    478 {
    479     int32_t i = 0, j = 0;
    480 
    481     if (NULL == buffer || node == NULL) {
    482         XML_ERROR(XML_ERROR_BUFFER_NULL);
    483         return NULL;
    484     }
    485 
    486     while (i < bufferLen) {
    487         if (WBXML_GET_TAG(buffer[i]) == WBXML_GET_TAG(node[j])) {
    488             j++;
    489             if (node[j] == '\0')
    490                 break;
    491 
    492             /* Check if there is the content(it should have content) */
    493             if (!WBXML_HAS_CONTENT(buffer[i])) {
    494                 /*XML_ERROR(WBXML_ERROR_MISSED_CONTENT); */
    495                 XML_ERROR(XML_ERROR_NO_SUCH_NODE);
    496                 return NULL;
    497             }
    498 
    499             /* Ignore the attrib filed */
    500             if (WBXML_HAS_ATTR(buffer[i])) {
    501                 while (i < bufferLen && buffer[i] != WBXML_ATTR_END)
    502                     i++;
    503                 if (i >= bufferLen)
    504                     break;
    505             }
    506         }
    507         i++;
    508 
    509         /* Ignore the content filed */
    510         if (buffer[i] == WBXML_STR_I) {
    511             while (i < bufferLen && buffer[i] != WBXML_END)
    512                 i++;
    513             if (i >= bufferLen)
    514                 break;
    515             i++;
    516         }
    517     }
    518 
    519     if (i >= bufferLen) {
    520         XML_ERROR(XML_ERROR_NO_SUCH_NODE);
    521         return NULL;
    522     }
    523 
    524     XML_ERROR(XML_ERROR_OK);
    525 
    526     return buffer + i + 1;
    527 }
    528 
    529 uint8_t *WBXML_DOM_getNodeValue(uint8_t *buffer, int32_t bufferLen,
    530                                       uint8_t *node,
    531                                       uint8_t **value, int32_t *valueLen)
    532 {
    533     int32_t i;
    534     uint8_t *pEnd;
    535 
    536     *value = NULL;
    537     *valueLen = 0;
    538 
    539     pEnd = buffer + bufferLen;
    540     buffer = WBXML_DOM_getNode(buffer, bufferLen, node);
    541     if (NULL == buffer) {
    542         XML_ERROR(XML_ERROR_NO_SUCH_NODE);
    543         return NULL;
    544     }
    545 
    546     if (*buffer == WBXML_OPAUE) {
    547         buffer++;
    548         *valueLen = WBXML_GetUintVar(buffer, &i);
    549         if (*valueLen < 0) {
    550             XML_ERROR(WBXML_ERROR_MBUINT32);
    551             return NULL;
    552         }
    553         buffer += i;
    554         *value = buffer;
    555         return *value;
    556     }
    557 
    558     if (*buffer != WBXML_STR_I) {
    559         XML_ERROR(WBXML_ERROR_MISSED_STARTTAG);
    560         return NULL;
    561     }
    562 
    563     buffer++;
    564 
    565     i = 0;
    566     while ((buffer + i) < pEnd && buffer[i] != WBXML_END)
    567         i++;
    568 
    569     if (buffer[i] != WBXML_END) {
    570         XML_ERROR(WBXML_ERROR_MISSED_ENDTAG);
    571         return NULL;
    572     }
    573 
    574     *value = buffer;
    575     *valueLen = i;
    576     XML_ERROR(XML_ERROR_OK);
    577 
    578     return *value;
    579 }
    580 #endif /* WBXML_OLD_VERSION */
    581 
    582 #define MAX_UINT_VAR_BYTE                                    4
    583 #define UINTVAR_INVALID                                      -1
    584 int32_t WBXML_GetUintVar(const uint8_t *const buffer, int32_t *len)
    585 {
    586     int32_t i, byteLen;
    587     int32_t sum;
    588 
    589     byteLen = 0;
    590     while ((buffer[byteLen] & 0x80) > 0 && byteLen < MAX_UINT_VAR_BYTE)
    591         byteLen++;
    592 
    593     if (byteLen > MAX_UINT_VAR_BYTE)
    594         return UINTVAR_INVALID;
    595 
    596     *len = byteLen + 1;
    597     sum = buffer[byteLen];
    598     for (i = byteLen - 1; i >= 0; i--)
    599         sum += ((buffer[i] & 0x7F) << 7 * (byteLen - i));
    600 
    601     return sum;
    602 }
    603 
    604 XML_BOOL WBXML_DOM_Init(WBXML * pWbxml, uint8_t *buffer,
    605                         int32_t bufferLen)
    606 {
    607     int32_t num, len;
    608 
    609     pWbxml->End = buffer + bufferLen;
    610     pWbxml->version = *buffer++;
    611     if (UINTVAR_INVALID == (num = WBXML_GetUintVar(buffer, &len)))
    612         return XML_FALSE;
    613     buffer += len;
    614     pWbxml->publicid = num;
    615     if (UINTVAR_INVALID == (num = WBXML_GetUintVar(buffer, &len)))
    616         return XML_FALSE;
    617     buffer += len;
    618     pWbxml->charset = num;
    619     if (UINTVAR_INVALID == (num = WBXML_GetUintVar(buffer, &len)))
    620         return XML_FALSE;
    621     buffer += len;
    622     pWbxml->strTable = buffer;
    623     pWbxml->strTableLen = num;
    624     buffer += num;
    625     pWbxml->curPtr = pWbxml->Content = buffer;
    626     pWbxml->depth = 0;
    627 
    628     return XML_TRUE;
    629 }
    630 
    631 void WBXML_DOM_Rewind(WBXML * pWbxml)
    632 {
    633     pWbxml->curPtr = pWbxml->Content;
    634 }
    635 
    636 XML_BOOL WBXML_DOM_Eof(WBXML * pWbxml)
    637 {
    638     if (pWbxml->curPtr > pWbxml->End)
    639         return XML_TRUE;
    640 
    641     return XML_FALSE;
    642 }
    643 
    644 uint8_t WBXML_DOM_GetTag(WBXML * pWbxml)
    645 {
    646     uint8_t tagChar;
    647 
    648     if (pWbxml->curPtr > pWbxml->End)
    649         return XML_EOF;
    650 
    651     tagChar = *pWbxml->curPtr;
    652     pWbxml->curPtr++;
    653 
    654     if (WBXML_GET_TAG(tagChar) == WBXML_CONTENT_END)
    655         pWbxml->depth--;
    656     else
    657         pWbxml->depth++;
    658 
    659     return tagChar;
    660 }
    661 
    662 uint8_t WBXML_DOM_GetChar(WBXML * pWbxml)
    663 {
    664     return *pWbxml->curPtr++;
    665 }
    666 
    667 void WBXML_DOM_Seek(WBXML * pWbxml, int32_t offset)
    668 {
    669     pWbxml->curPtr += offset;
    670 }
    671 
    672 uint8_t WBXML_DOM_GetUIntVar(WBXML * pWbxml)
    673 {
    674     int32_t num, len;
    675 
    676     num = WBXML_GetUintVar(pWbxml->curPtr, &len);
    677     pWbxml->curPtr += len;
    678 
    679     return (uint8_t)num;
    680 }
    681 
    682 #ifdef XML_TREE_STRUCTURE
    683 
    684 #ifdef DEBUG_MODE
    685 static int32_t malloc_times = 0;
    686 static int32_t free_times = 0;
    687 void XML_PrintMallocInfo()
    688 {
    689     printf("====XML_PrintMallocInfo====\n");
    690     printf(" Total malloc times:%d\n", malloc_times);
    691     printf(" Total free   times:%d\n", free_times);
    692     printf("===========================\n");
    693 }
    694 #endif
    695 
    696 void *xml_malloc(int32_t size)
    697 {
    698 #ifdef DEBUG_MODE
    699     malloc_times++;
    700 #endif
    701     return malloc(size);
    702 }
    703 
    704 void xml_free(void *buffer)
    705 {
    706 #ifdef DEBUG_MODE
    707     free_times++;
    708 #endif
    709     free(buffer);
    710 }
    711 
    712 XML_TREE *xml_tree_fillnode(uint8_t **buf, int32_t tagLen)
    713 {
    714     XML_TREE *Tree;
    715     uint8_t *pAttr, *pName, *pValue;
    716     int32_t nameLen, valueLen;
    717     uint8_t *buffer = *buf;
    718 
    719     if (NULL == (Tree = (XML_TREE *) xml_malloc(sizeof(XML_TREE))))
    720         return NULL;
    721     memset(Tree, 0, sizeof(XML_TREE));
    722 
    723     strncpy((char *)Tree->tag, (char *)++buffer, tagLen);
    724     buffer += tagLen;
    725     pAttr = buffer;
    726 
    727     /* attribute */
    728     while (NULL !=
    729            (pAttr =
    730             XML_DOM_getAttr(pAttr, &pName, &nameLen, &pValue,
    731                             &valueLen))) {
    732         XML_TREE_ATTR *attr;
    733         if (NULL ==
    734             (attr = (XML_TREE_ATTR *) xml_malloc(sizeof(XML_TREE_ATTR))))
    735             return NULL;
    736         memset(attr, 0, sizeof(XML_TREE_ATTR));
    737         strncpy((char *)attr->name, (char *)pName, nameLen);
    738         strncpy((char *)attr->value, (char *)pValue, valueLen);
    739         buffer = pValue + valueLen + 1;
    740 
    741         if (NULL != Tree->attr) // no attribute now
    742             Tree->last_attr->next = attr;
    743         else
    744             Tree->attr = attr;
    745         Tree->last_attr = attr;
    746     }
    747 
    748     /* value */
    749     pAttr = XML_DOM_getValue(buffer, &pValue, &valueLen);
    750     if (pAttr != NULL && valueLen > 0) {
    751         strncpy((char *)Tree->value, (char *)pValue, valueLen);
    752         buffer = pValue + valueLen;
    753     }
    754 
    755     *buf = buffer;
    756     return Tree;
    757 }
    758 
    759 XML_TREE *XML_makeTree(uint8_t **buf)
    760 {
    761     uint8_t *pBuf;
    762     int32_t valueLen, tagType;
    763     uint8_t *buffer = *buf;
    764     XML_TREE *TreeHead = NULL;
    765 
    766     if (NULL == (buffer = XML_DOM_getTag(buffer, &valueLen, &tagType)))
    767         return NULL;
    768     if (XML_TAG_END == tagType)
    769         return NULL;
    770     if (NULL == (TreeHead = xml_tree_fillnode(&buffer, valueLen)))
    771         return NULL;
    772     if (XML_TAG_SELF == tagType) {
    773         *buf = buffer;
    774         return TreeHead;
    775     }
    776 
    777     do {
    778         if (NULL == (pBuf = XML_DOM_getTag(buffer, &valueLen, &tagType)))
    779             return NULL;
    780 
    781         switch (tagType) {
    782         case XML_TAG_SELF:
    783         case XML_TAG_START:
    784             if (NULL == TreeHead->child)
    785                 TreeHead->child = XML_makeTree(&buffer);
    786             else if (NULL == TreeHead->child->last_brother) {
    787                 TreeHead->child->brother = XML_makeTree(&buffer);
    788                 TreeHead->child->last_brother = TreeHead->child->brother;
    789             } else {
    790                 TreeHead->child->last_brother->brother =
    791                     XML_makeTree(&buffer);
    792                 TreeHead->child->last_brother =
    793                     TreeHead->child->last_brother->brother;
    794             }
    795             break;
    796         case XML_TAG_END:
    797             *buf = pBuf;
    798             return TreeHead;
    799         }
    800         buffer++;
    801     } while (1);
    802 }
    803 
    804 void XML_freeTree(XML_TREE * pTree)
    805 {
    806     XML_TREE *p, *pNext;
    807     XML_TREE_ATTR *pa, *lastpa;
    808 
    809     if (NULL == pTree)
    810         return;
    811 
    812     p = pTree->brother;
    813     while (NULL != p) {
    814         pNext = p->brother;
    815         p->brother = NULL;
    816         XML_freeTree(p);
    817         p = pNext;
    818     }
    819 
    820     if (NULL != pTree->child)
    821         XML_freeTree(pTree->child);
    822 
    823     pa = pTree->attr;
    824     while (NULL != pa) {
    825         lastpa = pa;
    826         pa = pa->next;
    827         xml_free(lastpa);
    828     }
    829     xml_free(pTree);
    830 }
    831 
    832 #endif /* XML_TREE_STRUCTURE */
    833 
    834 #endif /* WBXML_DOM_PARSER */
    835