## FmXmlFile FmXmlFile — Simple XML parser. |

## Synopsis

    #define             FM_XML_FILE_TAG_NOT_HANDLED
    #define             FM_XML_FILE_TEXT
    #define             FM_XML_FILE_TYPE
                        FmXmlFile;
                        FmXmlFileClass;
    gboolean            (*FmXmlFileHandler)                 (FmXmlFileItem *item,
                                                             GList *children,
                                                             char * const *attribute_names,
                                                             char * const *attribute_values,
                                                             guint n_attributes,
                                                             gint line,
                                                             gint pos,
                                                             GError **error,
                                                             gpointer user_data);
                        FmXmlFileItem;
    typedef             FmXmlFileTag;
    GList *             fm_xml_file_finish_parse            (FmXmlFile *file,
                                                             GError **error);
    gint                fm_xml_file_get_current_line        (FmXmlFile *file,
                                                             gint *pos);
    const char *        fm_xml_file_get_dtd                 (FmXmlFile *file);
    const char *        fm_xml_file_get_tag_name            (FmXmlFile *file,
                                                             FmXmlFileTag tag);
    gboolean            fm_xml_file_insert_before           (FmXmlFileItem *item,
                                                             FmXmlFileItem *new_item);
    gboolean            fm_xml_file_insert_first            (FmXmlFile *file,
                                                             FmXmlFileItem *new_item);
    gboolean            fm_xml_file_item_append_child       (FmXmlFileItem *item,
                                                             FmXmlFileItem *child);
    void                fm_xml_file_item_append_text        (FmXmlFileItem *item,
                                                             const char *text,
                                                             gssize text_size,
                                                             gboolean cdata);
    gboolean            fm_xml_file_item_destroy            (FmXmlFileItem *item);
    FmXmlFileItem *     fm_xml_file_item_find_child         (FmXmlFileItem *item,
                                                             FmXmlFileTag tag);
    GList *             fm_xml_file_item_get_children       (FmXmlFileItem *item);
    const char *        fm_xml_file_item_get_comment        (FmXmlFileItem *item);
    const char *        fm_xml_file_item_get_data           (FmXmlFileItem *item,
                                                             gsize *text_size);
    FmXmlFileItem *     fm_xml_file_item_get_parent         (FmXmlFileItem *item);
    FmXmlFileTag        fm_xml_file_item_get_tag            (FmXmlFileItem *item);
    const char *        fm_xml_file_item_get_tag_name       (FmXmlFileItem *item);
    FmXmlFileItem *     fm_xml_file_item_new                (FmXmlFileTag tag);
    gboolean            fm_xml_file_item_set_attribute      (FmXmlFileItem *item,
                                                             const char *name,
                                                             const char *value);
    void                fm_xml_file_item_set_comment        (FmXmlFileItem *item,
                                                             const char *comment);
    FmXmlFile *         fm_xml_file_new                     (FmXmlFile *sibling);
    gboolean            fm_xml_file_parse_data              (FmXmlFile *file,
                                                             const char *text,
                                                             gsize size,
                                                             GError **error,
                                                             gpointer user_data);
    void                fm_xml_file_set_dtd                 (FmXmlFile *file,
                                                             const char *dtd,
                                                             GError **error);
    FmXmlFileTag        fm_xml_file_set_handler             (FmXmlFile *file,
                                                             const char *tag,
                                                             FmXmlFileHandler handler,
                                                             gboolean in_line,
                                                             GError **error);
    char *              fm_xml_file_to_data                 (FmXmlFile *file,
                                                             gsize *text_size,
                                                             GError **error);

## Object Hierarchy

      GObject
       +----FmXmlFile

## Description

`include`: libfm/fm-extra.h

The FmXmlFile represents content of some XML file in form that can be altered and saved later.

This parser has some simplifications on XML parsing: * Only UTF-8 encoding is supported * No user-defined entities, those should be converted externally * Processing instructions, comments and the doctype declaration are parsed but are not interpreted in any way The markup format does support: * Elements * Attributes * 5 standard entities: &amp; &lt; &gt; &quot; &apos; * Character references * Sections marked as CDATA

The application should respect `g_type_init()` if this parser is used without usage of libfm.

## Details

### FM_XML_FILE_TAG_NOT_HANDLED

    #define FM_XML_FILE_TAG_NOT_HANDLED 0

Value of FmXmlFileTag which means this element has no handler installed.

### FM_XML_FILE_TEXT

    #define FM_XML_FILE_TEXT (FmXmlFileTag)-1

Value of FmXmlFileTag which means this element has parsed character data.

### FM_XML_FILE_TYPE

    #define FM_XML_FILE_TYPE           (fm_xml_file_get_type())

### FmXmlFile

    typedef struct _FmXmlFile FmXmlFile;

### FmXmlFileClass

    typedef struct _FmXmlFileClass FmXmlFileClass;

### FmXmlFileHandler ()

    gboolean            (*FmXmlFileHandler)                 (FmXmlFileItem *item,
                                                             GList *children,
                                                             char * const *attribute_names,
                                                             char * const *attribute_values,
                                                             guint n_attributes,
                                                             gint line,
                                                             gint pos,
                                                             GError **error,
                                                             gpointer user_data);

Callback for processing some element in XML file. It will be called at closing tag.

`item` : | XML element being parsed
`children` : | elements found in `item`. [element-type FmXmlFileItem]
`attribute_names` : | attributes names list for `item`
`attribute_values` : | attributes values list for `item`
`n_attributes` : | list length of `attribute_names` and `attribute_values`
`line` : | current line number in the file (starting from 1)
`pos` : | current pos number in the file (starting from 0)
`error` : | location to save error. [allow-none][out]
`user_data` : | data passed to `fm_xml_file_parse_data()`
Returns : | `TRUE` if no errors were found by handler.

Since 1.2.0

### FmXmlFileItem

    typedef struct _FmXmlFileItem FmXmlFileItem;

### FmXmlFileTag

    typedef guint                       FmXmlFileTag;

### fm_xml_file_finish_parse ()

    GList *             fm_xml_file_finish_parse            (FmXmlFile *file,
                                                             GError **error);

Ends parsing of data and retrieves final status. If XML was invalid then returns `NULL` and sets `error` appropriately. This function can be called more than once.

See also: `fm_xml_file_parse_data()`. See also: `fm_xml_file_item_get_children()`.

`file` : | the parser container
`error` : | location to save error. [allow-none][out]
Returns : | contents of XML. [transfer container][element-type FmXmlFileItem]

Since 1.2.0

### fm_xml_file_get_current_line ()

    gint                fm_xml_file_get_current_line        (FmXmlFile *file,
                                                             gint *pos);

Retrieves the line where parser has stopped.

`file` : | the parser container
`pos` : | location to save line position. [allow-none][out]
Returns : | line num (starting from 1).

Since 1.2.0

### fm_xml_file_get_dtd ()

    const char *        fm_xml_file_get_dtd                 (FmXmlFile *file);

Retrieves DTD description for XML data in the container. Returned data are owned by `file` and should not be modified by caller.

`file` : | the parser container
Returns : | DTD description. [transfer none]

Since 1.2.0

### fm_xml_file_get_tag_name ()

    const char *        fm_xml_file_get_tag_name            (FmXmlFile *file,
                                                             FmXmlFileTag tag);

Retrieves tag for its id. Returned data are owned by `file` and should not be modified by caller.

`file` : | the parser container
`tag` : | the tag id to inspect
Returns : | tag string representation. [transfer none]

Since 1.2.0

### fm_xml_file_insert_before ()

    gboolean            fm_xml_file_insert_before           (FmXmlFileItem *item,
                                                             FmXmlFileItem *new_item);

Inserts `new_item` before `item` that is already in XML structure. If `new_item` is already in the XML structure then it will be moved to the new place instead. Behavior after moving between defferent containers is undefined.

`item` : | item to insert before it
`new_item` : | new item to insert
Returns : | `TRUE` in case of success.

Since 1.2.0

### fm_xml_file_insert_first ()

    gboolean            fm_xml_file_insert_first            (FmXmlFile *file,
                                                             FmXmlFileItem *new_item);

Inserts `new_item` as very first element of XML data in container.

`file` : | the parser container
`new_item` : | new item to insert
Returns : | `TRUE` in case of success.

Since 1.2.0

### fm_xml_file_item_append_child ()

    gboolean            fm_xml_file_item_append_child       (FmXmlFileItem *item,
                                                             FmXmlFileItem *child);

Appends `child` after last element contained in `item`. If the `child` already was in the XML structure then it will be moved to the new place instead. Behavior after moving between different containers is undefined.

`item` : | item to append child
`child` : | the child item to append
Returns : | `FALSE` if `child` is busy thus cannot be moved.

Since 1.2.0

### fm_xml_file_item_append_text ()

    void                fm_xml_file_item_append_text        (FmXmlFileItem *item,
                                                             const char *text,
                                                             gssize text_size,
                                                             gboolean cdata);

Appends `text` after last element contained in `item`.

`item` : | item to append text
`text` : | text to append
`text_size` : | length of text in bytes, or -1 if the text is nul-terminated
`cdata` : | `TRUE` if `text` should be saved as CDATA array

Since 1.2.0

### fm_xml_file_item_destroy ()

    gboolean            fm_xml_file_item_destroy            (FmXmlFileItem *item);

Removes element and its children from its parent, and frees all data.

`item` : | element to destroy
Returns : | `FALSE` if `item` is busy thus cannot be destroyed.

Since 1.2.0

### fm_xml_file_item_find_child ()

    FmXmlFileItem *     fm_xml_file_item_find_child         (FmXmlFileItem *item,
                                                             FmXmlFileTag tag);

Searches for first child of `item` which have child with tag id `tag`. Returned data are owned by file and should not be freed by caller.

`item` : | the file element to inspect
`tag` : | tag id to search among children
Returns : | found child or `NULL` if no such child was found. [transfer none]

Since 1.2.0

### fm_xml_file_item_get_children ()

    GList *             fm_xml_file_item_get_children       (FmXmlFileItem *item);

Retrieves list of children for `item` that are known to the parser. Returned list should be freed by `g_list_free()` after usage.

Note: any text between opening tag and closing tag such as

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24

    <Tag>Some text</Tag>

is presented as a child of special type FM_XML_FILE_TEXT and can be retrieved from that child, not from the item representing <Tag>.

See also: `fm_xml_file_item_get_data()`.

`item` : | the file element to inspect
Returns : | children list. [transfer container][element-type FmXmlFileItem]

Since 1.2.0

### fm_xml_file_item_get_comment ()

    const char *        fm_xml_file_item_get_comment        (FmXmlFileItem *item);

If an element `item` has a comment ahead of it then retrieves that comment. The returned data are owned by `item` and should not be freed nor otherwise altered by caller.

`item` : | the file element to inspect
Returns : | comment or `NULL` if no comment is set. [transfer none]

Since 1.2.0

### fm_xml_file_item_get_data ()

    const char *        fm_xml_file_item_get_data           (FmXmlFileItem *item,
                                                             gsize *text_size);

Retrieves text data from `item` of type FM_XML_FILE_TEXT. Returned data are owned by file and should not be freed nor altered.

`item` : | the file element to inspect
`text_size` : | location to save data size. [allow-none][out]
Returns : | text data or `NULL` if `item` isn't text data. [transfer none]

Since 1.2.0

### fm_xml_file_item_get_parent ()

    FmXmlFileItem *     fm_xml_file_item_get_parent         (FmXmlFileItem *item);

Retrieves parent element of `item` if the `item` has one. Returned data are owned by file and should not be freed by caller.

`item` : | the file element to inspect
Returns : | parent element or `NULL` if element has no parent. [transfer none]

Since 1.2.0

### fm_xml_file_item_get_tag ()

    FmXmlFileTag        fm_xml_file_item_get_tag            (FmXmlFileItem *item);

Retrieves tag id of `item`.

`item` : | the file element to inspect
Returns : | tag id.

Since 1.2.0

### fm_xml_file_item_get_tag_name ()

    const char *        fm_xml_file_item_get_tag_name       (FmXmlFileItem *item);

Retrieves tag for its id. Returned data are owned by `item` and should not be modified by caller.

`item` : | the file element to inspect
Returns : | tag string representation or `NULL` if `item` is text. [transfer none]

Since 1.2.0

### fm_xml_file_item_new ()

    FmXmlFileItem *     fm_xml_file_item_new                (FmXmlFileTag tag);

Creates new unattached XML item.

`tag` : | tag id for new item
Returns : | newly allocated FmXmlFileItem. [transfer full]

Since 1.2.0

### fm_xml_file_item_set_attribute ()

    gboolean            fm_xml_file_item_set_attribute      (FmXmlFileItem *item,
                                                             const char *name,
                                                             const char *value);

Changes data for the attribute of some `item` with new `value`. If such attribute wasn't set then adds it for the `item`. If `value` is `NULL` then the attribute will be unset from the `item`.

`item` : | element to update
`name` : | attribute name
`value` : | attribute data. [allow-none]
Returns : | `TRUE` if attribute was set successfully.

Since 1.2.0

### fm_xml_file_item_set_comment ()

    void                fm_xml_file_item_set_comment        (FmXmlFileItem *item,
                                                             const char *comment);

Changes comment that is prepended to `item`.

`item` : | element to set
`comment` : | new comment. [allow-none]

Since 1.2.0

### fm_xml_file_new ()

    FmXmlFile *         fm_xml_file_new                     (FmXmlFile *sibling);

Creates new empty FmXmlFile container. If `sibling` is not `NULL` then new container will have callbacks identical to set in `sibling`. Use `sibling` parameter if you need to work with few XML files that share the same schema or if you need to use the same tag ids for more than one file.

`sibling` : | container to copy handlers data. [allow-none]
Returns : | newly created object. [transfer full]

Since 1.2.0

### fm_xml_file_parse_data ()

    gboolean            fm_xml_file_parse_data              (FmXmlFile *file,
                                                             const char *text,
                                                             gsize size,
                                                             GError **error,
                                                             gpointer user_data);

Parses next chunk of `text` data. Parsing stops at end of data or at any error. In latter case `error` will be set appropriately.

See also: `fm_xml_file_finish_parse()`.

`file` : | the parser container
`text` : | data to parse
`size` : | size of `text`
`error` : | location to save error. [allow-none][out]
`user_data` : | data to pass to handlers
Returns : | `FALSE` if parsing failed.

Since 1.2.0

### fm_xml_file_set_dtd ()

    void                fm_xml_file_set_dtd                 (FmXmlFile *file,
                                                             const char *dtd,
                                                             GError **error);

Changes DTD description for XML data in the container.

`file` : | the parser container
`dtd` : | DTD description for XML data
`error` : | location to save error. [allow-none][out]

Since 1.2.0

### fm_xml_file_set_handler ()

    FmXmlFileTag        fm_xml_file_set_handler             (FmXmlFile *file,
                                                             const char *tag,
                                                             FmXmlFileHandler handler,
                                                             gboolean in_line,
                                                             GError **error);

Sets `handler` for `file` to be called on parse when `tag` is found in XML data. This function will fail if some handler for `tag` was aready set, in this case `error` will be set appropriately.

`file` : | the parser container
`tag` : | tag to use `handler` for
`handler` : | callback for `tag`
`in_line` : | `TRUE` if tag should not receive new line by `fm_xml_file_to_data()`
`error` : | location to save error. [allow-none][out]
Returns : | id for the `tag`.

Since 1.2.0

### fm_xml_file_to_data ()

    char *              fm_xml_file_to_data                 (FmXmlFile *file,
                                                             gsize *text_size,
                                                             GError **error);

Prepares string representation (XML text) for the data that are in the container. Returned data should be freed with `g_free()` after usage.

`file` : | the parser container
`text_size` : | location to save size of returned data. [allow-none][out]
`error` : | location to save error. [allow-none][out]
Returns : | XML text representing data in `file`. [transfer full]

Since 1.2.0