File:  [ELWIX - Embedded LightWeight unIX -] / gpl / axl / ns / axl_ns_node.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Wed Jun 8 07:09:12 2011 UTC (13 years ago) by misho
Branches: axl, MAIN
CVS tags: HEAD, AXL0_6_7, AXL0_6_1
3th party - XML

    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>