00001 /* SVN FILE INFO 00002 * $Revision: 531 $ : Last Committed Revision 00003 * $Date: 2010-06-17 10:39:34 -0700 (Thu, 17 Jun 2010) $ : Last Committed Date */ 00004 /* 00005 * "$Id: mxml-search.c,v 1.1 2007/05/23 20:43:27 david_ko Exp $" 00006 * 00007 * Search/navigation functions for Mini-XML, a small XML-like file 00008 * parsing library. 00009 * 00010 * Copyright 2003-2005 by Michael Sweet. 00011 * 00012 * This program is free software; you can redistribute it and/or 00013 * modify it under the terms of the GNU Library General Public 00014 * License as published by the Free Software Foundation; either 00015 * version 2, or (at your option) any later version. 00016 * 00017 * This program is distributed in the hope that it will be useful, 00018 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00019 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00020 * GNU General Public License for more details. 00021 * 00022 * Contents: 00023 * 00024 * mxmlFindElement() - Find the named element. 00025 * mxmlWalkNext() - Walk to the next logical node in the tree. 00026 * mxmlWalkPrev() - Walk to the previous logical node in the tree. 00027 */ 00028 00029 /* 00030 * Include necessary headers... 00031 */ 00032 00033 #ifdef _WIN32 00034 #include "winconfig.h" 00035 #else 00036 #include "config.h" 00037 #endif 00038 #include "mxml.h" 00039 00040 00041 /* 00042 * 'mxmlFindElement()' - Find the named element. 00043 * 00044 * The search is constrained by the name, attribute name, and value; any 00045 * NULL names or values are treated as wildcards, so different kinds of 00046 * searches can be implemented by looking for all elements of a given name 00047 * or all elements with a specific attribute. The descend argument determines 00048 * whether the search descends into child nodes; normally you will use 00049 * MXML_DESCEND_FIRST for the initial search and MXML_NO_DESCEND to find 00050 * additional direct descendents of the node. The top node argument 00051 * constrains the search to a particular node's children. 00052 */ 00053 00054 mxml_node_t * /* O - Element node or NULL */ 00055 mxmlFindElement(mxml_node_t *node, /* I - Current node */ 00056 mxml_node_t *top, /* I - Top node */ 00057 const char *name, /* I - Element name or NULL for any */ 00058 const char *attr, /* I - Attribute name, or NULL for none */ 00059 const char *value, /* I - Attribute value, or NULL for any */ 00060 int descend) /* I - Descend into tree - MXML_DESCEND, MXML_NO_DESCEND, or MXML_DESCEND_FIRST */ 00061 { 00062 const char *temp; /* Current attribute value */ 00063 00064 00065 /* 00066 * Range check input... 00067 */ 00068 00069 if (!node || !top || (!attr && value)) 00070 return (NULL); 00071 00072 /* 00073 * Start with the next node... 00074 */ 00075 00076 node = mxmlWalkNext(node, top, descend); 00077 00078 /* 00079 * Loop until we find a matching element... 00080 */ 00081 00082 while (node != NULL) 00083 { 00084 /* 00085 * See if this node matches... 00086 */ 00087 00088 if (node->type == MXML_ELEMENT && 00089 node->value.element.name && 00090 (!name || !strcmp(node->value.element.name, name))) 00091 { 00092 /* 00093 * See if we need to check for an attribute... 00094 */ 00095 00096 if (!attr) 00097 return (node); /* No attribute search, return it... */ 00098 00099 /* 00100 * Check for the attribute... 00101 */ 00102 00103 if ((temp = mxmlElementGetAttr(node, attr)) != NULL) 00104 { 00105 /* 00106 * OK, we have the attribute, does it match? 00107 */ 00108 00109 if (!value || !strcmp(value, temp)) 00110 return (node); /* Yes, return it... */ 00111 } 00112 } 00113 00114 /* 00115 * No match, move on to the next node... 00116 */ 00117 00118 if (descend == MXML_DESCEND) 00119 node = mxmlWalkNext(node, top, MXML_DESCEND); 00120 else 00121 node = node->next; 00122 } 00123 00124 return (NULL); 00125 } 00126 00127 00128 /* 00129 * 'mxmlWalkNext()' - Walk to the next logical node in the tree. 00130 * 00131 * The descend argument controls whether the first child is considered 00132 * to be the next node. The top node argument constrains the walk to 00133 * the node's children. 00134 */ 00135 00136 mxml_node_t * /* O - Next node or NULL */ 00137 mxmlWalkNext(mxml_node_t *node, /* I - Current node */ 00138 mxml_node_t *top, /* I - Top node */ 00139 int descend) /* I - Descend into tree - MXML_DESCEND, MXML_NO_DESCEND, or MXML_DESCEND_FIRST */ 00140 { 00141 if (!node) 00142 return (NULL); 00143 else if (node->child && descend) 00144 return (node->child); 00145 else if (node->next) 00146 return (node->next); 00147 else if (node->parent && node->parent != top) 00148 { 00149 node = node->parent; 00150 00151 while (!node->next) 00152 if (node->parent == top || !node->parent) 00153 return (NULL); 00154 else 00155 node = node->parent; 00156 00157 return (node->next); 00158 } 00159 else 00160 return (NULL); 00161 } 00162 00163 00164 /* 00165 * 'mxmlWalkPrev()' - Walk to the previous logical node in the tree. 00166 * 00167 * The descend argument controls whether the previous node's last child 00168 * is considered to be the previous node. The top node argument constrains 00169 * the walk to the node's children. 00170 */ 00171 00172 mxml_node_t * /* O - Previous node or NULL */ 00173 mxmlWalkPrev(mxml_node_t *node, /* I - Current node */ 00174 mxml_node_t *top, /* I - Top node */ 00175 int descend) /* I - Descend into tree - MXML_DESCEND, MXML_NO_DESCEND, or MXML_DESCEND_FIRST */ 00176 { 00177 if (!node) 00178 return (NULL); 00179 else if (node->prev) 00180 { 00181 if (node->prev->last_child && descend) 00182 { 00183 /* 00184 * Find the last child under the previous node... 00185 */ 00186 00187 node = node->prev->last_child; 00188 00189 while (node->last_child) 00190 node = node->last_child; 00191 00192 return (node); 00193 } 00194 else 00195 return (node->prev); 00196 } 00197 else if (node->parent != top) 00198 return (node->parent); 00199 else 00200 return (NULL); 00201 } 00202 00203 00204 /* 00205 * End of "$Id: mxml-search.c,v 1.1 2007/05/23 20:43:27 david_ko Exp $". 00206 */