Statistics
| Revision:

root / logic / trunk / src / mxml / mxml-search.c @ 49

History | View | Annotate | Download (5.13 KB)

1
/*
2
 * "$Id: mxml-search.c 297 2007-09-09 07:16:52Z mike $"
3
 *
4
 * Search/navigation functions for Mini-XML, a small XML-like file
5
 * parsing library.
6
 *
7
 * Copyright 2003-2007 by Michael Sweet.
8
 *
9
 * This program is free software; you can redistribute it and/or
10
 * modify it under the terms of the GNU Library General Public
11
 * License as published by the Free Software Foundation; either
12
 * version 2, or (at your option) any later version.
13
 *
14
 * This program is distributed in the hope that it will be useful,
15
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
 * GNU General Public License for more details.
18
 *
19
 * Contents:
20
 *
21
 *   mxmlFindElement() - Find the named element.
22
 *   mxmlWalkNext()    - Walk to the next logical node in the tree.
23
 *   mxmlWalkPrev()    - Walk to the previous logical node in the tree.
24
 */
25

    
26
/*
27
 * Include necessary headers...
28
 */
29

    
30
#include "config.h"
31
#include "mxml.h"
32

    
33

    
34
/*
35
 * 'mxmlFindElement()' - Find the named element.
36
 *
37
 * The search is constrained by the name, attribute name, and value; any
38
 * NULL names or values are treated as wildcards, so different kinds of
39
 * searches can be implemented by looking for all elements of a given name
40
 * or all elements with a specific attribute. The descend argument determines
41
 * whether the search descends into child nodes; normally you will use
42
 * MXML_DESCEND_FIRST for the initial search and MXML_NO_DESCEND to find
43
 * additional direct descendents of the node. The top node argument
44
 * constrains the search to a particular node's children.
45
 */
46

    
47
mxml_node_t *                                /* O - Element node or NULL */
48
mxmlFindElement(mxml_node_t *node,        /* I - Current node */
49
                mxml_node_t *top,        /* I - Top node */
50
                const char  *name,        /* I - Element name or NULL for any */
51
                const char  *attr,        /* I - Attribute name, or NULL for none */
52
                const char  *value,        /* I - Attribute value, or NULL for any */
53
                int         descend)        /* I - Descend into tree - MXML_DESCEND, MXML_NO_DESCEND, or MXML_DESCEND_FIRST */
54
{
55
  const char        *temp;                        /* Current attribute value */
56

    
57

    
58
 /*
59
  * Range check input...
60
  */
61

    
62
  if (!node || !top || (!attr && value))
63
    return (NULL);
64

    
65
 /*
66
  * Start with the next node...
67
  */
68

    
69
  node = mxmlWalkNext(node, top, descend);
70

    
71
 /*
72
  * Loop until we find a matching element...
73
  */
74

    
75
  while (node != NULL)
76
  {
77
   /*
78
    * See if this node matches...
79
    */
80

    
81
    if (node->type == MXML_ELEMENT &&
82
        node->value.element.name &&
83
        (!name || !strcmp(node->value.element.name, name)))
84
    {
85
     /*
86
      * See if we need to check for an attribute...
87
      */
88

    
89
      if (!attr)
90
        return (node);                        /* No attribute search, return it... */
91

    
92
     /*
93
      * Check for the attribute...
94
      */
95

    
96
      if ((temp = mxmlElementGetAttr(node, attr)) != NULL)
97
      {
98
       /*
99
        * OK, we have the attribute, does it match?
100
        */
101

    
102
        if (!value || !strcmp(value, temp))
103
          return (node);                /* Yes, return it... */
104
      }
105
    }
106

    
107
   /*
108
    * No match, move on to the next node...
109
    */
110

    
111
    if (descend == MXML_DESCEND)
112
      node = mxmlWalkNext(node, top, MXML_DESCEND);
113
    else
114
      node = node->next;
115
  }
116

    
117
  return (NULL);
118
}
119

    
120

    
121
/*
122
 * 'mxmlWalkNext()' - Walk to the next logical node in the tree.
123
 *
124
 * The descend argument controls whether the first child is considered
125
 * to be the next node. The top node argument constrains the walk to
126
 * the node's children.
127
 */
128

    
129
mxml_node_t *                                /* O - Next node or NULL */
130
mxmlWalkNext(mxml_node_t *node,                /* I - Current node */
131
             mxml_node_t *top,                /* I - Top node */
132
             int         descend)        /* I - Descend into tree - MXML_DESCEND, MXML_NO_DESCEND, or MXML_DESCEND_FIRST */
133
{
134
  if (!node)
135
    return (NULL);
136
  else if (node->child && descend)
137
    return (node->child);
138
  else if (node == top)
139
    return (NULL);
140
  else if (node->next)
141
    return (node->next);
142
  else if (node->parent && node->parent != top)
143
  {
144
    node = node->parent;
145

    
146
    while (!node->next)
147
      if (node->parent == top || !node->parent)
148
        return (NULL);
149
      else
150
        node = node->parent;
151

    
152
    return (node->next);
153
  }
154
  else
155
    return (NULL);
156
}
157

    
158

    
159
/*
160
 * 'mxmlWalkPrev()' - Walk to the previous logical node in the tree.
161
 *
162
 * The descend argument controls whether the previous node's last child
163
 * is considered to be the previous node. The top node argument constrains
164
 * the walk to the node's children.
165
 */
166

    
167
mxml_node_t *                                /* O - Previous node or NULL */
168
mxmlWalkPrev(mxml_node_t *node,                /* I - Current node */
169
             mxml_node_t *top,                /* I - Top node */
170
             int         descend)        /* I - Descend into tree - MXML_DESCEND, MXML_NO_DESCEND, or MXML_DESCEND_FIRST */
171
{
172
  if (!node || node == top)
173
    return (NULL);
174
  else if (node->prev)
175
  {
176
    if (node->prev->last_child && descend)
177
    {
178
     /*
179
      * Find the last child under the previous node...
180
      */
181

    
182
      node = node->prev->last_child;
183

    
184
      while (node->last_child)
185
        node = node->last_child;
186

    
187
      return (node);
188
    }
189
    else
190
      return (node->prev);
191
  }
192
  else if (node->parent != top)
193
    return (node->parent);
194
  else
195
    return (NULL);
196
}
197

    
198

    
199
/*
200
 * End of "$Id: mxml-search.c 297 2007-09-09 07:16:52Z mike $".
201
 */