⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sflxml.c

📁 短小精悍的C语言标准函数库。提供450个以上的可移植的算法和工具代码。
💻 C
📖 第 1 页 / 共 2 页
字号:
/*  ----------------------------------------------------------------<Prolog>-
    Name:       sflxml.c
    Title:      XML (Extensible Markup Language) access functions
    Package:    Standard Function Library (SFL)

    Written:    1998/02/25  iMatix SFL project team <sfl@imatix.com>
    Revised:    2000/01/20

    Copyright:  Copyright (c) 1991-99 iMatix Corporation
    License:    This is free software; you can redistribute it and/or modify
                it under the terms of the SFL License Agreement as provided
                in the file LICENSE.TXT.  This software is distributed in
                the hope that it will be useful, but without any warranty.
 ------------------------------------------------------------------</Prolog>-*/

#include "prelude.h"                    /*  Universal header file            */
#include "sflstr.h"                     /*  String functions                 */
#include "sfllist.h"                    /*  List access functions            */
#include "sflmem.h"                     /*  Memory access functions          */
#include "sflfile.h"                    /*  File access functions            */
#include "sfldate.h"                    /*  Date and time functions          */
#include "sflxml.h"                     /*  Prototypes for functions         */
#include "sflxmll.h"                    /*  Loading & saving functions       */


/*  Implementation-dependent type definitions                                */

struct _XML_ITEM {                      /*  Item node definition             */
    struct _XML_ITEM
        *next,                          /*  Next item in list                */
        *prev,                          /*  Previous item in list            */
        *parent;                        /*  Parent if this is a child        */
    char
        *name,                          /*  Item name, allocated string      */
        *value;                         /*  Value node, allocated string     */
    LIST
        attrs,                          /*  List of attributes, 0 or more    */
        children;                       /*  List of children, 0 or more      */
};

struct _XML_ATTR {                      /*  Attribute node definition        */
    struct _XML_ATTR
        *next,                          /*  Next attr in list                */
        *prev;                          /*  Previous attr in list            */
    struct _XML_ITEM
        *parent;                        /*  Parent item if this attribute    */
    char
        *name,                          /*  Attribute name                   */
        *value;                         /*  Attribute value, may be null     */
};


/*  ---------------------------------------------------------------------[<]-
    Function: xml_create

    Synopsis: Creates and initialises a new XML_ITEM item.  Returns
    the address of the created XML_ITEM item or NULL if there was not
    enough memory.  Sets the new item's name and value as specified; only
    one of these should contain a value, although sflxml will not complain
    if both do.  If the name is non-NULL this is a child node; if the
    value is non-NULL then this is a value node.
    ---------------------------------------------------------------------[>]-*/

XML_ITEM *
xml_create (
    const char *name,
    const char *value)
{
    XML_ITEM
        *item;

    list_create (item, sizeof (XML_ITEM));
    if (item)
      {
        list_reset (&item-> attrs);
        list_reset (&item-> children);
        item-> parent = NULL;
        item-> name   = mem_strdup (name);
        item-> value  = mem_strdup (value);

        return (item);
      }
    else
        return (NULL);
}


/*  ---------------------------------------------------------------------[<]-
    Function: xml_new

    Synopsis: Creates and initialises a new XML_ITEM item with a specified
    parent item.  Returns the address of the created XML_ITEM item or NULL
    if there was not enough memory.  Sets the new item's name and value as
    specified; only one of these should contain a value, although sflxml
    will not complain if both do.  If the name is non-NULL this is a child
    node; if the value is non-NULL then this is a value node.  If the
    parent argument is non-NULL, attaches the new item to the end of the
    parent item list.
    ---------------------------------------------------------------------[>]-*/

XML_ITEM *
xml_new (
    XML_ITEM   *parent,
    const char *name,
    const char *value)
{
    XML_ITEM
        *item;

    item = xml_create (name, value);
    if (item && parent)
        xml_attach_child (parent, item);

    return item;
}


/*  ---------------------------------------------------------------------[<]-
    Function: xml_modify_value

    Synopsis: Modifies an existing XML item's value.
    ---------------------------------------------------------------------[>]-*/

void
xml_modify_value  (XML_ITEM *item, const char *value)
{
    ASSERT (item);

    if (!item-> value)
        item-> value = mem_strdup (value);
    else
        if (! value || (strneq (value, item-> value)))
          {
            mem_free (item-> value);
            item-> value = mem_strdup (value);
          }
}


/*  ---------------------------------------------------------------------[<]-
    Function: xml_rename

    Synopsis: Modifies an existing XML item's name.
    ---------------------------------------------------------------------[>]-*/


void
xml_rename (XML_ITEM *item, const char *name)
{
    ASSERT (item);

    mem_free (item-> name);
    item-> name = mem_strdup (name);
}


/*  ---------------------------------------------------------------------[<]-
    Function: xml_item_name

    Synopsis: Extracts the name of a specified XML item.  The returned string
    should NOT be modified.  To manipulate it, first make a copy first.
    ---------------------------------------------------------------------[>]-*/

char *
xml_item_name (XML_ITEM *item)
{
    ASSERT (item);

    return item-> name;
}


/*  ---------------------------------------------------------------------[<]-
    Function: xml_item_value

    Synopsis: Extracts the value from a value node.  These are recognised
    by their name being NULL.  The returned string should NOT be modified.
    To manipulate it, first make a copy first.
    ---------------------------------------------------------------------[>]-*/

char *
xml_item_value (XML_ITEM *item)
{
    ASSERT (item);

    return item-> value;
}


/*  ---------------------------------------------------------------------[<]-
    Function: xml_free

    Synopsis: Frees all memory used by an XML_ITEM item and its children.
    ---------------------------------------------------------------------[>]-*/

void
xml_free (
    XML_ITEM *item)
{
    ASSERT (item);

    /*  Free attribute nodes for the item                                    */
    while (!list_empty (&item-> attrs))
        xml_free_attr (item-> attrs.next);

    /*  Free child nodes for the item                                        */
    while (!list_empty (&item-> children))
        xml_free (item-> children.next);

    /*  Now free this item itself                                            */
    list_unlink (item);                 /*  Unlink from its parent list      */
    mem_free (item-> name);             /*  Free strings, if not null        */
    mem_free (item-> value);
    mem_free (item);                    /*  And free the item itself         */
}


/*  ---------------------------------------------------------------------[<]-
    Function: xml_attach_child

    Synopsis: Attaches an XML item as the last child of a given parent.
    If the item is already attached to a parent, it is first removed.
    ---------------------------------------------------------------------[>]-*/

void
xml_attach_child (
    XML_ITEM *parent,
    XML_ITEM *item)
{
    if (item-> parent)
        xml_detach (item);

    item-> parent = parent;
    if (parent)
        list_relink_before (item, &parent-> children);
}


/*  ---------------------------------------------------------------------[<]-
    Function: xml_attach_sibling

    Synopsis: Attaches an XML item as the sibling preceeding a given item.
    If the item is already attached to a parent, it is first removed.
    ---------------------------------------------------------------------[>]-*/

void
xml_attach_sibling (
    XML_ITEM *sibling,
    XML_ITEM *item)
{
    if (item-> parent)
        xml_detach (item);

    item-> parent = xml_parent (sibling);
    list_relink_before (item, sibling);
}


/*  ---------------------------------------------------------------------[<]-
    Function: xml_detach

    Synopsis: Removes an XML item from the tree.
    ---------------------------------------------------------------------[>]-*/

void
xml_detach (
    XML_ITEM *item)
{
    item-> parent = NULL;
    list_unlink (item);
}


/*  ---------------------------------------------------------------------[<]-
    Function: xml_first_child

    Synopsis: Returns the first child node of the specified item, or NULL
    if there are none.
    ---------------------------------------------------------------------[>]-*/

XML_ITEM *
xml_first_child (XML_ITEM *item)
{
    ASSERT (item);

    if (!list_empty (&item-> children))
        return item-> children. next;
    else
        return NULL;
}


/*  ---------------------------------------------------------------------[<]-
    Function: xml_last_child

    Synopsis: Returns the last child node of the specified item, or NULL
    if there are none.
    ---------------------------------------------------------------------[>]-*/

XML_ITEM *
xml_last_child (XML_ITEM *item)
{
    ASSERT (item);

    if (!list_empty (&item-> children))
        return item-> children. prev;
    else
        return NULL;
}


/*  ---------------------------------------------------------------------[<]-
    Function: xml_next_sibling

    Synopsis: Returns the next sibling of the specified item, or NULL if there
    if are none.
    ---------------------------------------------------------------------[>]-*/

XML_ITEM *
xml_next_sibling (XML_ITEM *item)
{
    ASSERT (item);

    if ((LIST *) item-> next != & item-> parent-> children)
        return item-> next;
    else
        return NULL;
}


/*  ---------------------------------------------------------------------[<]-
    Function: xml_prev_sibling

    Synopsis: Returns the previous sibling of the specified item, or NULL if
    there if are none.
    ---------------------------------------------------------------------[>]-*/

XML_ITEM *

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -