Annotation of gpl/axl/ns/axl_ns_node.c, revision 1.1.1.1

1.1       misho       1: /*
                      2:  *  LibAxl:  Another XML library
                      3:  *  Copyright (C) 2006 Advanced Software Production Line, S.L.
                      4:  *
                      5:  *  This program is free software; you can redistribute it and/or
                      6:  *  modify it under the terms of the GNU Lesser General Public License
                      7:  *  as published by the Free Software Foundation; either version 2.1 of
                      8:  *  the License, or (at your option) any later version.
                      9:  *
                     10:  *  This program is distributed in the hope that it will be useful,
                     11:  *  but WITHOUT ANY WARRANTY; without even the implied warranty of 
                     12:  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the  
                     13:  *  GNU Lesser General Public License for more details.
                     14:  *
                     15:  *  You should have received a copy of the GNU Lesser General Public
                     16:  *  License along with this program; if not, write to the Free
                     17:  *  Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
                     18:  *  02111-1307 USA
                     19:  *  
                     20:  *  You may find a copy of the license under this software is released
                     21:  *  at COPYING file. This is LGPL software: you are welcome to
                     22:  *  develop proprietary applications using this library without any
                     23:  *  royalty or fee but returning back any change, improvement or
                     24:  *  addition in the form of source code, project image, documentation
                     25:  *  patches, etc. 
                     26:  *
                     27:  *  For commercial support on build XML enabled solutions contact us:
                     28:  *          
                     29:  *      Postal address:
                     30:  *         Advanced Software Production Line, S.L.
                     31:  *         Edificio Alius A, Oficina 102,
                     32:  *         C/ Antonio Suarez Nº 10,
                     33:  *         Alcalá de Henares 28802 Madrid
                     34:  *         Spain
                     35:  *
                     36:  *      Email address:
                     37:  *         info@aspl.es - http://www.aspl.es/xml
                     38:  */
                     39: #include <axl_ns.h>
                     40: 
                     41: #define LOG_DOMAIN "axl-ns-node"
                     42: 
                     43: /**
                     44:  * \defgroup axl_ns_node_module Axl Node Namespace: Xml 1.0 namespace support for XML nodes
                     45:  */
                     46: 
                     47: /** 
                     48:  * \addtogroup axl_ns_node_module
                     49:  * @{
                     50:  */
                     51: 
                     52: /** 
                     53:  * @brief Allows to perform a node name (tag) checking using XML 1.0
                     54:  * Namespace rules.
                     55:  *
                     56:  * This function must be used instead of \ref NODE_CMP_NAME if your application must support
                     57:  * XML 1.0 namespaces.
                     58:  *
                     59:  * The idea is that you declares the namespace that you will recognize
                     60:  * using a macro definition at some place in your headers, as follows:
                     61:  * \code
                     62:  * #define YOUR_NS "http://yourdomain.com/somepath/yourapplication"
                     63:  * \endcode
                     64:  *
                     65:  * Previous namespace must be unique. This is crucial to avoid tag
                     66:  * clashing. Now, you use this namespace identifier and the local name
                     67:  * of your tag to check a particular node to have a particular name as
                     68:  * follows:
                     69:  * 
                     70:  * \code
                     71:  * if (axl_ns_node_cmp (node, YOUR_NS, "table")) {
                     72:  *     // found table node inside your namespace
                     73:  * }
                     74:  * \endcode
                     75:  *
                     76:  * It is required to call first to \ref axl_ns_doc_validate in order
                     77:  * to make this function to properly work. 
                     78:  * 
                     79:  * @param node The node that will be checked.
                     80:  *
                     81:  * @param ns The namespace to use to match the node name.
                     82:  *
                     83:  * @param name The node name to be checked (without namespace
                     84:  * prefixes).
                     85:  * 
                     86:  * @return \ref axl_true if the node name is the one expected, binded by
                     87:  * the namespace declaration, otherwise \ref axl_false is returned. The
                     88:  * function returns \ref axl_false in the of some paremeter is provided
                     89:  * null.
                     90:  */
                     91: axl_bool axl_ns_node_cmp (axlNode    * node, 
                     92:                      const char * ns, 
                     93:                      const char * name)
                     94: {
                     95:        int    position;
                     96:        char * _name;
                     97: 
                     98:        axl_return_val_if_fail (node, axl_false);
                     99:        axl_return_val_if_fail (ns, axl_false);
                    100:        axl_return_val_if_fail (name, axl_false);
                    101: 
                    102:        /* check the name is namespace prefixed */
                    103:        if (axl_ns_node_is_prefixed (node, &position)) {
                    104: 
                    105:                /* namespace bound */
                    106:                _name           = (char*) axl_node_get_name (node);
                    107:                _name[position] = 0;
                    108: 
                    109:                /* call to check */
                    110:                if (! axl_ns_doc_node_check (node, _name, ns)) {
                    111:                        /* restore the value */
                    112:                        _name[position] = ':';
                    113:                        return axl_false;
                    114:                }
                    115: 
                    116:                /* restore the value */
                    117:                _name[position] = ':';
                    118: 
                    119:                /* now check the node name (now we know the namespace is checked) */
                    120:                return axl_cmp (name, _name + position + 1);
                    121:        } /* end if */
                    122: 
                    123:        /* look for the default namespace */
                    124:        if (! axl_ns_doc_check_default (node, ns)) {
                    125:                /* default namespace for the current node doesn't match */
                    126:                return axl_false;
                    127:        }
                    128:        
                    129:        /* default namespace match, check the node name */
                    130:        return axl_cmp (name, axl_node_get_name (node));
                    131: }
                    132: 
                    133: /** 
                    134:  * @brief Allows to find the first child called as provided inside the
                    135:  * childs (including its descendants) hold by the parent provided,
                    136:  * with namespace support.
                    137:  *
                    138:  * This function must be used instead of \ref
                    139:  * axl_node_find_called if your application must support
                    140:  * XML 1.0 namespaces.
                    141:  *
                    142:  * This function is similar to \ref axl_ns_node_get_child_called but
                    143:  * it will look for a child node called as provided not only in direct
                    144:  * childs hold by the parent but also on its all descendants, giving
                    145:  * support to configure the namespace where the lookup will be run.
                    146:  *
                    147:  * If you are looking for a function to search for a particular child
                    148:  * node inside direct childs stored for the provided parent, then you
                    149:  * must use \ref axl_ns_node_get_child_called.
                    150:  *
                    151:  * There is also a convenience function that allows to perform a
                    152:  * lookup using as a reference a document (using the root node from
                    153:  * it): \ref axl_ns_doc_find_called.
                    154:  *
                    155:  * @param parent The parent where the lookup will be produced.
                    156:  *
                    157:  * @param ns The namespace where the node will be searched
                    158:  *
                    159:  * @param name The name of the child to be looked up.
                    160:  * 
                    161:  * @return A reference to the node found (first instaned matching the
                    162:  * name) or NULL if it fails to find a child. 
                    163:  */
                    164: axlNode * axl_ns_node_find_called  (axlNode    * parent,
                    165:                                    const char * ns,
                    166:                                    const char * name)
                    167: {
                    168:        axlNode * node;
                    169:        axlNode * child;
                    170: 
                    171:        /* for the first child found */
                    172:        node = axl_ns_node_get_child_called (parent, ns, name);
                    173:        if (node != NULL)
                    174:                return node;
                    175: 
                    176:        /* now, for all childs, try to look for the node */
                    177:        node = axl_node_get_first_child (parent);
                    178:        while (node != NULL) {
                    179:                /* make the search */
                    180:                child = axl_ns_node_find_called (node, ns, name);
                    181:                
                    182:                /* child found, return the reference */
                    183:                if (child != NULL)
                    184:                        return child;
                    185:                
                    186:                /* get next */
                    187:                node = axl_node_get_next (node);
                    188:        } /* end while */
                    189: 
                    190:        /* child note found */
                    191:        return NULL;
                    192: }
                    193: 
                    194: /** 
                    195:  * @brief Allows to get a particular child node for the given node
                    196:  * (\ref axlNode), inside the provided namespace.
                    197:  *
                    198:  * This function must be used instead of \ref
                    199:  * axl_node_get_child_called if your application must support
                    200:  * XML 1.0 namespaces.
                    201:  * 
                    202:  * @param parent The parent node where the child will be looked up.
                    203:  *
                    204:  * @param ns The namespace where the lookup will be run.
                    205:  *
                    206:  * @param name The name for the child to search.
                    207:  * 
                    208:  * @return A refernce to a \ref axlNode or NULL if no child exists
                    209:  * called by the name provided, inside the node provided.
                    210:  */
                    211: axlNode * axl_ns_node_get_child_called   (axlNode    * parent, 
                    212:                                          const char * ns,
                    213:                                          const char * name)
                    214: {
                    215:        axlNode * node;
                    216: 
                    217:        /* for the first child found */
                    218:        node = axl_node_get_first_child (parent);
                    219:        while (node != NULL) {
                    220:                /* check and return the node found */
                    221:                if (axl_ns_node_cmp (node, ns, name))
                    222:                        return node;
                    223:                
                    224:                /* get next */
                    225:                node = axl_node_get_next (node);
                    226:        } /* end while */
                    227: 
                    228:        return NULL;
                    229: }
                    230: 
                    231: /** 
                    232:  * @brief Allows to get the next node, following to the node provided,
                    233:  * matching the given name, inside the namespace configuration
                    234:  * provided.
                    235:  *
                    236:  * This function must be used instead of \ref
                    237:  * axl_node_get_next_called if your application must support
                    238:  * XML 1.0 namespaces.
                    239:  * 
                    240:  * @param node The node that is requested to return its next sibling
                    241:  * node.
                    242:  * 
                    243:  * @param ns The namespace value to use to perform the search.
                    244:  *
                    245:  * @param name The name to match for the next node.
                    246:  * 
                    247:  * @return A reference to the next node or NULL if it fails. The
                    248:  * returned reference mustn't be deallocated.
                    249:  */
                    250: axlNode * axl_ns_node_get_next_called    (axlNode    * node,
                    251:                                          const char * ns,
                    252:                                          const char * name)
                    253: {
                    254:        axlNode * next;
                    255: 
                    256:        axl_return_val_if_fail (node, NULL);
                    257:        axl_return_val_if_fail (ns, NULL);
                    258:        axl_return_val_if_fail (name, NULL);
                    259: 
                    260:        /* while there is a next node */
                    261:        next = axl_node_get_next (node);
                    262:        while (next != NULL) {
                    263:                /* check the node */
                    264:                if (axl_ns_node_cmp (next, ns, name))
                    265:                        return next;
                    266: 
                    267:                /* update to the next */
                    268:                next = axl_node_get_next (next);
                    269:        } /* end while */
                    270: 
                    271:        /* no node was found */
                    272:        return NULL;
                    273: }
                    274: 
                    275: /** 
                    276:  * @brief Allows to get the previous node, preceding to the node
                    277:  * provided, matching the given name, inside the given namespace
                    278:  * value.
                    279:  * 
                    280:  * @param node The node that is requested to return its previous
                    281:  * sibling node.
                    282:  *
                    283:  * @param ns The namespace to be used to perform the lookup.
                    284:  *
                    285:  * @param name The name to match for the previous node.
                    286:  * 
                    287:  * @return A reference to the previous node or NULL if it fails. The
                    288:  * returned reference mustn't be deallocated.
                    289:  */
                    290: axlNode * axl_ns_node_get_previous_called (axlNode    * node,
                    291:                                           const char * ns,
                    292:                                           const char * name)
                    293: {
                    294:        axlNode * previous;
                    295: 
                    296:        axl_return_val_if_fail (node, NULL);
                    297:        axl_return_val_if_fail (ns, NULL);
                    298:        axl_return_val_if_fail (name, NULL);
                    299: 
                    300:        /* while there is a previous node */
                    301:        previous = axl_node_get_previous (node);
                    302:        while (previous != NULL) {
                    303:                /* check the node */
                    304:                if (axl_ns_node_cmp (previous, ns, name))
                    305:                        return previous;
                    306: 
                    307:                /* update to the next */
                    308:                previous = axl_node_get_previous (previous);
                    309:        } /* end while */
                    310: 
                    311:        /* no node was found */
                    312:        return NULL;
                    313: }
                    314: 
                    315: /** 
                    316:  * @brief Allows to check if the provided node, has a name (tag) which is namespace prefixed. 
                    317:  *
                    318:  * The following name is considered namespace prefixed
                    319:  * <b>edi:price</b> while using <b>edi</b> is not.
                    320:  *
                    321:  * @param node The node to be checked to have a name prefixed.
                    322:  *
                    323:  * @param position Optional variable where the position of the ":"
                    324:  * inside the xml node name is returned. On \ref axl_false, the value is
                    325:  * configured to -1.
                    326:  * 
                    327:  * @return \ref axl_true if the node is prefixed, otherwise \ref axl_false is
                    328:  * returned. The function also returns \ref axl_false if the node
                    329:  * reference received is NULL.
                    330:  */
                    331: axl_bool axl_ns_node_is_prefixed  (axlNode * node, int * position)
                    332: {
                    333:        int          iterator = 0;
                    334:        const char * name;
                    335: 
                    336:        axl_return_val_if_fail (node, axl_false);
                    337: 
                    338:        /* configure default position */
                    339:        if (position)
                    340:                *position = -1;
                    341: 
                    342:        /* get the node name and check each character */
                    343:        name = axl_node_get_name (node);
                    344:        while (name[iterator] != 0) {
                    345: 
                    346:                /* if found, notify this */
                    347:                if (name[iterator] == ':') {
                    348:                        /* configure default position */
                    349:                        if (position)
                    350:                                *position = iterator;
                    351: 
                    352:                        return axl_true;
                    353:                } /* end if */
                    354: 
                    355:                /* go to the next character */
                    356:                iterator++;
                    357:        } /* end while */
                    358:        
                    359:        /* reached this point, axl_false must be returned */
                    360:        return axl_false;
                    361: }
                    362: 
                    363: /**
                    364:  * @}
                    365:  */

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>