1/* 2 * "$Id: mxml-search.c,v 1.7 2004/09/17 18:38:21 rleigh Exp $" 3 * 4 * Search/navigation functions for mini-XML, a small XML-like file 5 * parsing library. 6 * 7 * Copyright 2003 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 * stp_mxmlFindElement() - Find the named element. 22 * stp_mxmlWalkNext() - Walk to the next logical node in the tree. 23 * stp_mxmlWalkPrev() - Walk to the previous logical node in the tree. 24 */ 25 26/* 27 * Include necessary headers... 28 */ 29 30#include <gutenprint/mxml.h> 31#include "config.h" 32 33 34/* 35 * 'stp_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 * STP_MXML_DESCEND_FIRST for the initial search and STP_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 47stp_mxml_node_t * /* O - Element node or NULL */ 48stp_mxmlFindElement(stp_mxml_node_t *node, /* I - Current node */ 49 stp_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 - STP_MXML_DESCEND, STP_MXML_NO_DESCEND, or STP_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 = stp_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 == STP_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 = stp_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 == STP_MXML_DESCEND) 112 node = stp_mxmlWalkNext(node, top, STP_MXML_DESCEND); 113 else 114 node = node->next; 115 } 116 117 return (NULL); 118} 119 120 121/* 122 * 'stp_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 129stp_mxml_node_t * /* O - Next node or NULL */ 130stp_mxmlWalkNext(stp_mxml_node_t *node, /* I - Current node */ 131 stp_mxml_node_t *top, /* I - Top node */ 132 int descend) /* I - Descend into tree - STP_MXML_DESCEND, STP_MXML_NO_DESCEND, or STP_MXML_DESCEND_FIRST */ 133{ 134 if (!node) 135 return (NULL); 136 else if (node->child && descend) 137 return (node->child); 138 else if (node->next) 139 return (node->next); 140 else if (node->parent && node->parent != top) 141 { 142 node = node->parent; 143 144 while (!node->next) 145 if (node->parent == top || !node->parent) 146 return (NULL); 147 else 148 node = node->parent; 149 150 return (node->next); 151 } 152 else 153 return (NULL); 154} 155 156 157/* 158 * 'stp_mxmlWalkPrev()' - Walk to the previous logical node in the tree. 159 * 160 * The descend argument controls whether the previous node's last child 161 * is considered to be the previous node. The top node argument constrains 162 * the walk to the node's children. 163 */ 164 165stp_mxml_node_t * /* O - Previous node or NULL */ 166stp_mxmlWalkPrev(stp_mxml_node_t *node, /* I - Current node */ 167 stp_mxml_node_t *top, /* I - Top node */ 168 int descend) /* I - Descend into tree - STP_MXML_DESCEND, STP_MXML_NO_DESCEND, or STP_MXML_DESCEND_FIRST */ 169{ 170 if (!node) 171 return (NULL); 172 else if (node->prev) 173 { 174 if (node->prev->last_child && descend) 175 { 176 /* 177 * Find the last child under the previous node... 178 */ 179 180 node = node->prev->last_child; 181 182 while (node->last_child) 183 node = node->last_child; 184 185 return (node); 186 } 187 else 188 return (node->prev); 189 } 190 else if (node->parent != top) 191 return (node->parent); 192 else 193 return (NULL); 194} 195 196 197/* 198 * End of "$Id: mxml-search.c,v 1.7 2004/09/17 18:38:21 rleigh Exp $". 199 */ 200