mirror of
https://github.com/michaelrsweet/mxml.git
synced 2024-11-13 07:15:30 +00:00
97ca6dc424
to the LGPL2 (STR #108)
200 lines
4.9 KiB
C
200 lines
4.9 KiB
C
/*
|
|
* "$Id$"
|
|
*
|
|
* Search/navigation functions for Mini-XML, a small XML-like file
|
|
* parsing library.
|
|
*
|
|
* Copyright 2003-2010 by Michael R Sweet.
|
|
*
|
|
* These coded instructions, statements, and computer programs are the
|
|
* property of Michael R Sweet and are protected by Federal copyright
|
|
* law. Distribution and use rights are outlined in the file "COPYING"
|
|
* which should have been included with this file. If this file is
|
|
* missing or damaged, see the license at:
|
|
*
|
|
* http://www.minixml.org/
|
|
*
|
|
* Contents:
|
|
*
|
|
* mxmlFindElement() - Find the named element.
|
|
* mxmlWalkNext() - Walk to the next logical node in the tree.
|
|
* mxmlWalkPrev() - Walk to the previous logical node in the tree.
|
|
*/
|
|
|
|
/*
|
|
* Include necessary headers...
|
|
*/
|
|
|
|
#include "config.h"
|
|
#include "mxml.h"
|
|
|
|
|
|
/*
|
|
* 'mxmlFindElement()' - Find the named element.
|
|
*
|
|
* The search is constrained by the name, attribute name, and value; any
|
|
* NULL names or values are treated as wildcards, so different kinds of
|
|
* searches can be implemented by looking for all elements of a given name
|
|
* or all elements with a specific attribute. The descend argument determines
|
|
* whether the search descends into child nodes; normally you will use
|
|
* MXML_DESCEND_FIRST for the initial search and MXML_NO_DESCEND to find
|
|
* additional direct descendents of the node. The top node argument
|
|
* constrains the search to a particular node's children.
|
|
*/
|
|
|
|
mxml_node_t * /* O - Element node or NULL */
|
|
mxmlFindElement(mxml_node_t *node, /* I - Current node */
|
|
mxml_node_t *top, /* I - Top node */
|
|
const char *name, /* I - Element name or NULL for any */
|
|
const char *attr, /* I - Attribute name, or NULL for none */
|
|
const char *value, /* I - Attribute value, or NULL for any */
|
|
int descend) /* I - Descend into tree - MXML_DESCEND, MXML_NO_DESCEND, or MXML_DESCEND_FIRST */
|
|
{
|
|
const char *temp; /* Current attribute value */
|
|
|
|
|
|
/*
|
|
* Range check input...
|
|
*/
|
|
|
|
if (!node || !top || (!attr && value))
|
|
return (NULL);
|
|
|
|
/*
|
|
* Start with the next node...
|
|
*/
|
|
|
|
node = mxmlWalkNext(node, top, descend);
|
|
|
|
/*
|
|
* Loop until we find a matching element...
|
|
*/
|
|
|
|
while (node != NULL)
|
|
{
|
|
/*
|
|
* See if this node matches...
|
|
*/
|
|
|
|
if (node->type == MXML_ELEMENT &&
|
|
node->value.element.name &&
|
|
(!name || !strcmp(node->value.element.name, name)))
|
|
{
|
|
/*
|
|
* See if we need to check for an attribute...
|
|
*/
|
|
|
|
if (!attr)
|
|
return (node); /* No attribute search, return it... */
|
|
|
|
/*
|
|
* Check for the attribute...
|
|
*/
|
|
|
|
if ((temp = mxmlElementGetAttr(node, attr)) != NULL)
|
|
{
|
|
/*
|
|
* OK, we have the attribute, does it match?
|
|
*/
|
|
|
|
if (!value || !strcmp(value, temp))
|
|
return (node); /* Yes, return it... */
|
|
}
|
|
}
|
|
|
|
/*
|
|
* No match, move on to the next node...
|
|
*/
|
|
|
|
if (descend == MXML_DESCEND)
|
|
node = mxmlWalkNext(node, top, MXML_DESCEND);
|
|
else
|
|
node = node->next;
|
|
}
|
|
|
|
return (NULL);
|
|
}
|
|
|
|
|
|
/*
|
|
* 'mxmlWalkNext()' - Walk to the next logical node in the tree.
|
|
*
|
|
* The descend argument controls whether the first child is considered
|
|
* to be the next node. The top node argument constrains the walk to
|
|
* the node's children.
|
|
*/
|
|
|
|
mxml_node_t * /* O - Next node or NULL */
|
|
mxmlWalkNext(mxml_node_t *node, /* I - Current node */
|
|
mxml_node_t *top, /* I - Top node */
|
|
int descend) /* I - Descend into tree - MXML_DESCEND, MXML_NO_DESCEND, or MXML_DESCEND_FIRST */
|
|
{
|
|
if (!node)
|
|
return (NULL);
|
|
else if (node->child && descend)
|
|
return (node->child);
|
|
else if (node == top)
|
|
return (NULL);
|
|
else if (node->next)
|
|
return (node->next);
|
|
else if (node->parent && node->parent != top)
|
|
{
|
|
node = node->parent;
|
|
|
|
while (!node->next)
|
|
if (node->parent == top || !node->parent)
|
|
return (NULL);
|
|
else
|
|
node = node->parent;
|
|
|
|
return (node->next);
|
|
}
|
|
else
|
|
return (NULL);
|
|
}
|
|
|
|
|
|
/*
|
|
* 'mxmlWalkPrev()' - Walk to the previous logical node in the tree.
|
|
*
|
|
* The descend argument controls whether the previous node's last child
|
|
* is considered to be the previous node. The top node argument constrains
|
|
* the walk to the node's children.
|
|
*/
|
|
|
|
mxml_node_t * /* O - Previous node or NULL */
|
|
mxmlWalkPrev(mxml_node_t *node, /* I - Current node */
|
|
mxml_node_t *top, /* I - Top node */
|
|
int descend) /* I - Descend into tree - MXML_DESCEND, MXML_NO_DESCEND, or MXML_DESCEND_FIRST */
|
|
{
|
|
if (!node || node == top)
|
|
return (NULL);
|
|
else if (node->prev)
|
|
{
|
|
if (node->prev->last_child && descend)
|
|
{
|
|
/*
|
|
* Find the last child under the previous node...
|
|
*/
|
|
|
|
node = node->prev->last_child;
|
|
|
|
while (node->last_child)
|
|
node = node->last_child;
|
|
|
|
return (node);
|
|
}
|
|
else
|
|
return (node->prev);
|
|
}
|
|
else if (node->parent != top)
|
|
return (node->parent);
|
|
else
|
|
return (NULL);
|
|
}
|
|
|
|
|
|
/*
|
|
* End of "$Id$".
|
|
*/
|