Annotation of gpl/axl/ns/axl_ns_node.c, revision 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>