00001 /* SVN FILE INFO 00002 * $Revision: 174 $ : Last Committed Revision 00003 * $Date: 2008-06-24 10:50:29 -0700 (Tue, 24 Jun 2008) $ : 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 #include "config.h" 00034 #include "mxml.h" 00035 00036 00037 /* 00038 * 'mxmlFindElement()' - Find the named element. 00039 * 00040 * The search is constrained by the name, attribute name, and value; any 00041 * NULL names or values are treated as wildcards, so different kinds of 00042 * searches can be implemented by looking for all elements of a given name 00043 * or all elements with a specific attribute. The descend argument determines 00044 * whether the search descends into child nodes; normally you will use 00045 * MXML_DESCEND_FIRST for the initial search and MXML_NO_DESCEND to find 00046 * additional direct descendents of the node. The top node argument 00047 * constrains the search to a particular node's children. 00048 */ 00049 00050 mxml_node_t * /* O - Element node or NULL */ 00051 mxmlFindElement(mxml_node_t *node, /* I - Current node */ 00052 mxml_node_t *top, /* I - Top node */ 00053 const char *name, /* I - Element name or NULL for any */ 00054 const char *attr, /* I - Attribute name, or NULL for none */ 00055 const char *value, /* I - Attribute value, or NULL for any */ 00056 int descend) /* I - Descend into tree - MXML_DESCEND, MXML_NO_DESCEND, or MXML_DESCEND_FIRST */ 00057 { 00058 const char *temp; /* Current attribute value */ 00059 00060 00061 /* 00062 * Range check input... 00063 */ 00064 00065 if (!node || !top || (!attr && value)) 00066 return (NULL); 00067 00068 /* 00069 * Start with the next node... 00070 */ 00071 00072 node = mxmlWalkNext(node, top, descend); 00073 00074 /* 00075 * Loop until we find a matching element... 00076 */ 00077 00078 while (node != NULL) 00079 { 00080 /* 00081 * See if this node matches... 00082 */ 00083 00084 if (node->type == MXML_ELEMENT && 00085 node->value.element.name && 00086 (!name || !strcmp(node->value.element.name, name))) 00087 { 00088 /* 00089 * See if we need to check for an attribute... 00090 */ 00091 00092 if (!attr) 00093 return (node); /* No attribute search, return it... */ 00094 00095 /* 00096 * Check for the attribute... 00097 */ 00098 00099 if ((temp = mxmlElementGetAttr(node, attr)) != NULL) 00100 { 00101 /* 00102 * OK, we have the attribute, does it match? 00103 */ 00104 00105 if (!value || !strcmp(value, temp)) 00106 return (node); /* Yes, return it... */ 00107 } 00108 } 00109 00110 /* 00111 * No match, move on to the next node... 00112 */ 00113 00114 if (descend == MXML_DESCEND) 00115 node = mxmlWalkNext(node, top, MXML_DESCEND); 00116 else 00117 node = node->next; 00118 } 00119 00120 return (NULL); 00121 } 00122 00123 00124 /* 00125 * 'mxmlWalkNext()' - Walk to the next logical node in the tree. 00126 * 00127 * The descend argument controls whether the first child is considered 00128 * to be the next node. The top node argument constrains the walk to 00129 * the node's children. 00130 */ 00131 00132 mxml_node_t * /* O - Next node or NULL */ 00133 mxmlWalkNext(mxml_node_t *node, /* I - Current node */ 00134 mxml_node_t *top, /* I - Top node */ 00135 int descend) /* I - Descend into tree - MXML_DESCEND, MXML_NO_DESCEND, or MXML_DESCEND_FIRST */ 00136 { 00137 if (!node) 00138 return (NULL); 00139 else if (node->child && descend) 00140 return (node->child); 00141 else if (node->next) 00142 return (node->next); 00143 else if (node->parent && node->parent != top) 00144 { 00145 node = node->parent; 00146 00147 while (!node->next) 00148 if (node->parent == top || !node->parent) 00149 return (NULL); 00150 else 00151 node = node->parent; 00152 00153 return (node->next); 00154 } 00155 else 00156 return (NULL); 00157 } 00158 00159 00160 /* 00161 * 'mxmlWalkPrev()' - Walk to the previous logical node in the tree. 00162 * 00163 * The descend argument controls whether the previous node's last child 00164 * is considered to be the previous node. The top node argument constrains 00165 * the walk to the node's children. 00166 */ 00167 00168 mxml_node_t * /* O - Previous node or NULL */ 00169 mxmlWalkPrev(mxml_node_t *node, /* I - Current node */ 00170 mxml_node_t *top, /* I - Top node */ 00171 int descend) /* I - Descend into tree - MXML_DESCEND, MXML_NO_DESCEND, or MXML_DESCEND_FIRST */ 00172 { 00173 if (!node) 00174 return (NULL); 00175 else if (node->prev) 00176 { 00177 if (node->prev->last_child && descend) 00178 { 00179 /* 00180 * Find the last child under the previous node... 00181 */ 00182 00183 node = node->prev->last_child; 00184 00185 while (node->last_child) 00186 node = node->last_child; 00187 00188 return (node); 00189 } 00190 else 00191 return (node->prev); 00192 } 00193 else if (node->parent != top) 00194 return (node->parent); 00195 else 00196 return (NULL); 00197 } 00198 00199 00200 /* 00201 * End of "$Id: mxml-search.c,v 1.1 2007/05/23 20:43:27 david_ko Exp $". 00202 */