mxml-search.c

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

Generated by  doxygen 1.6.2