📄 sflxml.c
字号:
/* ----------------------------------------------------------------<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 + -