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

/*
 *  LibAxl:  Another XML library
 *  Copyright (C) 2006 Advanced Software Production Line, S.L.
 *
 *  This program is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public License
 *  as published by the Free Software Foundation; either version 2.1 of
 *  the License, or (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of 
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the  
 *  GNU Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this program; if not, write to the Free
 *  Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
 *  02111-1307 USA
 *  
 *  You may find a copy of the license under this software is released
 *  at COPYING file. This is LGPL software: you are welcome to
 *  develop proprietary applications using this library without any
 *  royalty or fee but returning back any change, improvement or
 *  addition in the form of source code, project image, documentation
 *  patches, etc. 
 *
 *  For commercial support on build XML enabled solutions contact us:
 *          
 *      Postal address:
 *         Advanced Software Production Line, S.L.
 *         Edificio Alius A, Oficina 102,
 *         C/ Antonio Suarez Nº 10,
 *         Alcalá de Henares 28802 Madrid
 *         Spain
 *
 *      Email address:
 *         info@aspl.es - http://www.aspl.es/xml
 */
#include <axl_ns.h>

#define LOG_DOMAIN "axl-ns-node"

/**
 * \defgroup axl_ns_node_module Axl Node Namespace: Xml 1.0 namespace support for XML nodes
 */

/** 
 * \addtogroup axl_ns_node_module
 * @{
 */

/** 
 * @brief Allows to perform a node name (tag) checking using XML 1.0
 * Namespace rules.
 *
 * This function must be used instead of \ref NODE_CMP_NAME if your application must support
 * XML 1.0 namespaces.
 *
 * The idea is that you declares the namespace that you will recognize
 * using a macro definition at some place in your headers, as follows:
 * \code
 * #define YOUR_NS "http://yourdomain.com/somepath/yourapplication"
 * \endcode
 *
 * Previous namespace must be unique. This is crucial to avoid tag
 * clashing. Now, you use this namespace identifier and the local name
 * of your tag to check a particular node to have a particular name as
 * follows:
 * 
 * \code
 * if (axl_ns_node_cmp (node, YOUR_NS, "table")) {
 *     // found table node inside your namespace
 * }
 * \endcode
 *
 * It is required to call first to \ref axl_ns_doc_validate in order
 * to make this function to properly work. 
 * 
 * @param node The node that will be checked.
 *
 * @param ns The namespace to use to match the node name.
 *
 * @param name The node name to be checked (without namespace
 * prefixes).
 * 
 * @return \ref axl_true if the node name is the one expected, binded by
 * the namespace declaration, otherwise \ref axl_false is returned. The
 * function returns \ref axl_false in the of some paremeter is provided
 * null.
 */
axl_bool axl_ns_node_cmp (axlNode    * node, 
		      const char * ns, 
		      const char * name)
{
	int    position;
	char * _name;

	axl_return_val_if_fail (node, axl_false);
	axl_return_val_if_fail (ns, axl_false);
	axl_return_val_if_fail (name, axl_false);

	/* check the name is namespace prefixed */
	if (axl_ns_node_is_prefixed (node, &position)) {

		/* namespace bound */
		_name           = (char*) axl_node_get_name (node);
		_name[position] = 0;

		/* call to check */
		if (! axl_ns_doc_node_check (node, _name, ns)) {
			/* restore the value */
			_name[position] = ':';
			return axl_false;
		}

		/* restore the value */
		_name[position] = ':';

		/* now check the node name (now we know the namespace is checked) */
		return axl_cmp (name, _name + position + 1);
	} /* end if */

	/* look for the default namespace */
	if (! axl_ns_doc_check_default (node, ns)) {
		/* default namespace for the current node doesn't match */
		return axl_false;
	}
	
	/* default namespace match, check the node name */
	return axl_cmp (name, axl_node_get_name (node));
}

/** 
 * @brief Allows to find the first child called as provided inside the
 * childs (including its descendants) hold by the parent provided,
 * with namespace support.
 *
 * This function must be used instead of \ref
 * axl_node_find_called if your application must support
 * XML 1.0 namespaces.
 *
 * This function is similar to \ref axl_ns_node_get_child_called but
 * it will look for a child node called as provided not only in direct
 * childs hold by the parent but also on its all descendants, giving
 * support to configure the namespace where the lookup will be run.
 *
 * If you are looking for a function to search for a particular child
 * node inside direct childs stored for the provided parent, then you
 * must use \ref axl_ns_node_get_child_called.
 *
 * There is also a convenience function that allows to perform a
 * lookup using as a reference a document (using the root node from
 * it): \ref axl_ns_doc_find_called.
 *
 * @param parent The parent where the lookup will be produced.
 *
 * @param ns The namespace where the node will be searched
 *
 * @param name The name of the child to be looked up.
 * 
 * @return A reference to the node found (first instaned matching the
 * name) or NULL if it fails to find a child. 
 */
axlNode * axl_ns_node_find_called  (axlNode    * parent,
				    const char * ns,
				    const char * name)
{
	axlNode * node;
	axlNode * child;

	/* for the first child found */
	node = axl_ns_node_get_child_called (parent, ns, name);
	if (node != NULL)
		return node;

	/* now, for all childs, try to look for the node */
	node = axl_node_get_first_child (parent);
	while (node != NULL) {
		/* make the search */
		child = axl_ns_node_find_called (node, ns, name);
		
		/* child found, return the reference */
		if (child != NULL)
			return child;
		
		/* get next */
		node = axl_node_get_next (node);
	} /* end while */

	/* child note found */
	return NULL;
}

/** 
 * @brief Allows to get a particular child node for the given node
 * (\ref axlNode), inside the provided namespace.
 *
 * This function must be used instead of \ref
 * axl_node_get_child_called if your application must support
 * XML 1.0 namespaces.
 * 
 * @param parent The parent node where the child will be looked up.
 *
 * @param ns The namespace where the lookup will be run.
 *
 * @param name The name for the child to search.
 * 
 * @return A refernce to a \ref axlNode or NULL if no child exists
 * called by the name provided, inside the node provided.
 */
axlNode * axl_ns_node_get_child_called   (axlNode    * parent, 
					  const char * ns,
					  const char * name)
{
	axlNode * node;

	/* for the first child found */
	node = axl_node_get_first_child (parent);
	while (node != NULL) {
		/* check and return the node found */
		if (axl_ns_node_cmp (node, ns, name))
			return node;
		
		/* get next */
		node = axl_node_get_next (node);
	} /* end while */

	return NULL;
}

/** 
 * @brief Allows to get the next node, following to the node provided,
 * matching the given name, inside the namespace configuration
 * provided.
 *
 * This function must be used instead of \ref
 * axl_node_get_next_called if your application must support
 * XML 1.0 namespaces.
 * 
 * @param node The node that is requested to return its next sibling
 * node.
 * 
 * @param ns The namespace value to use to perform the search.
 *
 * @param name The name to match for the next node.
 * 
 * @return A reference to the next node or NULL if it fails. The
 * returned reference mustn't be deallocated.
 */
axlNode * axl_ns_node_get_next_called    (axlNode    * node,
					  const char * ns,
					  const char * name)
{
	axlNode * next;

	axl_return_val_if_fail (node, NULL);
	axl_return_val_if_fail (ns, NULL);
	axl_return_val_if_fail (name, NULL);

	/* while there is a next node */
	next = axl_node_get_next (node);
	while (next != NULL) {
		/* check the node */
		if (axl_ns_node_cmp (next, ns, name))
			return next;

		/* update to the next */
		next = axl_node_get_next (next);
	} /* end while */

	/* no node was found */
	return NULL;
}

/** 
 * @brief Allows to get the previous node, preceding to the node
 * provided, matching the given name, inside the given namespace
 * value.
 * 
 * @param node The node that is requested to return its previous
 * sibling node.
 *
 * @param ns The namespace to be used to perform the lookup.
 *
 * @param name The name to match for the previous node.
 * 
 * @return A reference to the previous node or NULL if it fails. The
 * returned reference mustn't be deallocated.
 */
axlNode * axl_ns_node_get_previous_called (axlNode    * node,
					   const char * ns,
					   const char * name)
{
	axlNode * previous;

	axl_return_val_if_fail (node, NULL);
	axl_return_val_if_fail (ns, NULL);
	axl_return_val_if_fail (name, NULL);

	/* while there is a previous node */
	previous = axl_node_get_previous (node);
	while (previous != NULL) {
		/* check the node */
		if (axl_ns_node_cmp (previous, ns, name))
			return previous;

		/* update to the next */
		previous = axl_node_get_previous (previous);
	} /* end while */

	/* no node was found */
	return NULL;
}

/** 
 * @brief Allows to check if the provided node, has a name (tag) which is namespace prefixed. 
 *
 * The following name is considered namespace prefixed
 * <b>edi:price</b> while using <b>edi</b> is not.
 *
 * @param node The node to be checked to have a name prefixed.
 *
 * @param position Optional variable where the position of the ":"
 * inside the xml node name is returned. On \ref axl_false, the value is
 * configured to -1.
 * 
 * @return \ref axl_true if the node is prefixed, otherwise \ref axl_false is
 * returned. The function also returns \ref axl_false if the node
 * reference received is NULL.
 */
axl_bool axl_ns_node_is_prefixed  (axlNode * node, int * position)
{
	int          iterator = 0;
	const char * name;

	axl_return_val_if_fail (node, axl_false);

	/* configure default position */
	if (position)
		*position = -1;

	/* get the node name and check each character */
	name = axl_node_get_name (node);
	while (name[iterator] != 0) {

		/* if found, notify this */
		if (name[iterator] == ':') {
			/* configure default position */
			if (position)
				*position = iterator;

			return axl_true;
		} /* end if */

		/* go to the next character */
		iterator++;
	} /* end while */
	
	/* reached this point, axl_false must be returned */
	return axl_false;
}

/**
 * @}
 */

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