#ifndef __JBXL_TINY_XML_H_
#define __JBXL_TINY_XML_H_
/**
@brief Tiny XML ライブラリヘッダ
@file txml.h
@version 1.0
@author Fumi.Iseki (C)
@date 2009 2/10
@par タイトル
Tiny XML txml.h v1.0 @n
サブセット版 整形式XML 簡易パーサ ライブラリヘッダ
@see tXML
@attention
全てのパターンのパース可能性は保障しない@n
複雑な XMLは(恐らく)パースできない.@n
以外の ..... ?> と は処理しない(読み込みは行う)@n
エンティティは処理しない.@n
*/
#include "tools.h"
#include "ttree.h"
#include "jbxl_state.h"
/** @typedef tXML
typedef tTree tXML; ///<
@b tXML (@b tList, @b tTree, @b _tList と同じもの)
@see tTree
1. ノードデータ tXML:
@code
int ldat.id ノードの種別.XML_ANCHOR_NODE, XML_NAME_NODE, XML_CONTENT_NODE, ..........
int ldat.lv 種別がノード値である子ノードの個数
int ldat.sz 未使用
Buffer ldat.key ノード名またはノード値
Buffer ldat.val の未処理データと のコメント情報を格納
void* ldat.ptr 未使用
tXML* ldat.lst 属性リストへのポインタ.ldat.lst->ldat.keyに属性名,ldat.lst->ldat.valに属性値("'付き)を格納
tXML* next 子ノード(長女)へのポインタ
tXML* prev 親ノードへのポインタ
tXML* altp その他へのポインタ(汎用)
tXML* yngr 子ノード(末っ子)へのポインタ // back から変更
tXML* esis 前の姉妹(姉)ノードへのポインタ
tXML* ysis 次の姉妹(妹)ノードへのポインタ
int depth 深さ
int num 子ノードの数(全ての子ノードの数)
int ctrl 制御用
int state ノードの状態 JBXL_XML_PARSED, JBXL_XML_NODE_OPENED, JBXL_XML_NODE_CLOSES, JBXL_XML_PARSE_ERR, ....
@endcode
2. パースしたXML情報を格納するツリー構造
@code
ABCEFG
NULL (XML_ANCHOR_NODE) -> xml (XML_DOC_NODE)
-> A (XML_NAME_NODE) -> B (XML_NAME_NODE) -> C (XML_NAME_NODE) -> ABC (XML_CONTENT_NODE)
-> D (XML_NAME_NODE)
-> EFG (XML_CONTENT_NODE)
-> E (XML_NAME_NODE)
-> @COMMENT_NODE (XML_COMMENT_NODE) // ただしコメントの処理は暫定的
@endcode
3. ノード(ノード)種別 (ldat.id)
@code
XML_ANCHOR_NODE アンカーノード
XML_NAME_NODE ネームノード
XML_CONTENT_NODE 内容(コンテント)ノード
XML_DOC_NODE xml... ?> ノード
XML_COMMENT_NODE コメントノード
XML_DATA_NODE ノード
XML_PROCESS_NODE XML_DOC_NODE 以外の ... ?>ノード
@endcode
4. 状態 (state)
@code
JBXL_XML_DEFAULT_STATE ノードは,正常にパースされたかどうかの判定はまだ行われていない.
JBXL_XML_PARSED アンカーノードにのみ設定される.このXMLツリーは正常にパースされたことを示す.
JBXL_XML_NODE_STARTED このノードはオープン状態にある.
JBXL_XML_NODE_ENDED このノードは正常にクローズした.
JBXL_XML_NODE_EMPTY このノードは空要素ノードである < />, , , ?> の型
JBXL_XML_NOT_CLOSED 最終的にノードが閉じなかったが,解釈できるところまでは解釈した.
JBXL_XML_MULTI_ROOT アンカーノードにのみ設定される.このXMLツリーは 2つ以上の独立したツリーを持つ
JBXL_XML_ERROR tXML ライブラリのエラー
JBXL_XML_PARSE_ERROR 解釈エラー
JBXL_XML_SEQUENCE_ERROR アンカーを越えてツリーを作ろうとした.
JBXL_XML_MEMORY_ERROR メモリの確保エラー
@endcode
*/
typedef tTree tXML; ///<
// ノード種別 (ldat.id)
#define XML_ANCHOR_NODE JBXL_STATE_ANCHOR ///< アンカーノード
#define XML_NAME_NODE 1 ///< ネームノード
#define XML_CONTENT_NODE 2 ///< 内容(コンテント)ノード
#define XML_DOC_NODE 3 ///< xml... ?> ノード
#define XML_COMMENT_NODE 4 ///< コメントノード
#define XML_DATA_NODE 5 ///< ノード
#define XML_PROCESS_NODE 6 ///< XML_DOC_NODE 以外の ... ?>ノード
// XML Format
#define XML_ONELINE_FORMAT 0 ///< 改行なしの一行にする.
#define XML_CRLF_FORMAT 1 ///< ノードの終わりを CR(0x0d), LF(0x0a)で改行する.
#define XML_INDENT_FORMAT 2 ///< 先頭にインデント(TAB)をつけ,ノードごとに改行する.
// 代用ノード名 (ldat.key.buf)
#define XML_COMMENT_NODE_KEY "@COMMENT_NODE"
#define XML_DATA_NODE_KEY "@DATA_NODE"
/////////////////////////////////////////////////////////////////////////////////////////////
// XML Functions
#define new_xml_node() new_tTree_node() ///< new_tTree_node()
#define new_xml() new_tTree_node() ///< new_tTree_node()
#define new_xml_anchor_node() new_tTree_anchor_node() ///< new_tTree_anchor_node()
#define del_xml_anchor(t) del_tTree_anchor_node((t)) ///< del_tTree_anchor_node()
#define del_xml_anchor_nodet() del_tTree_anchor_node((t)) ///< del_tTree_anchor_node()
// Paser
tXML* xml_parse(char* pp); ///< 文字列のXMLデータを解釈して,tXMLのツリーを生成する.
tXML* xml_parse_file(const char* pp); ///< ファイルから読み込んでパースする.
tXML* xml_parse_seq(tXML* xml, char* pp); ///< 部分的な XMLデータを解釈して,tXMLのツリー構造に格納する.断片的にXMLデータを入力する場合に使用する.
tXML* xml_main_parse(tXML* xml, char* pp, int skip); ///< 部分的な XMLデータを解釈して,tXMLのツリー構造に格納する.パーサの内部的なメイン関数.
int xml_parse_start_node(char* pp, char** node_name, char** node_attr, int* node_end); ///< XMLの開始ノードを処理する.
int xml_parse_end_node(char* pp, char** node_name); ///< XMLの終了ノードを処理する.
int xml_parse_content(char* pp, char** content); ///< XMLのコンテントを処理する.
int xml_parse_comment_node(char* pp, char** comment); ///< XMLのコメントノードを処理する.
int xml_parse_data_node(char* pp, char** data); ///< XMLのデータノード(その他エレメントノードなど)を処理する.
int xml_parse_processing_node(char* pp, char** node_name, char** node_attr); ///< XMLのプロセッシングノードを処理する
tList* xml_parse_attr(char* pp); ///< XMLのノード属性を解釈して,リスト(tList)にする.
void close_xml(tXML* pp); ///< パースエラーを起こしたツリーを強制的に正常化する.
int isnot_xml_name(unsigned char* pp); ///< XML名として不適切かどうかを大まかに判断する.
#define find_xml_top(p) find_tList_top(p) ///< find_tList_top()
#define find_xml_end(p) find_tTree_end(p) ///< find_tTree_end()
// 逆パース
Buffer xml_inverse_parse(tXML* pp, int mode); ///< ppに格納された XMLデータを元の書式に戻して Bufferに格納する.xml_parse() の逆.
void xml_to_Buffer(tXML* pp, Buffer* buf, int mode, int indent); ///< xml_inverse_parse()用の補助関数.
void xml_open_node_Buffer (tXML* pp, Buffer* buf, int mode, int indent); ///< ツリー中のXMLのオープンノードのデータを元の書式に戻して Bufferに格納する.
void xml_close_node_Buffer(tXML* pp, Buffer* buf, int mode, int indent); ///< ツリー中のXMLのクローズノードのデータを元の書式に戻して Bufferに格納する.
void xml_attr_to_Buffer(tList* pp, Buffer* buf); ///< リストに保存されたノードの属性をテキストへ戻す.
// Operation
tXML* init_xml_doc(void); ///< XML のドキュメントヘッダを作成する.
char* get_first_xml_nodename(tXML* xml); ///< XMLツリーの最初のノードの名前を返す.
tXML* add_xml_node(tXML* xml, const char* name); ///< XMLツリーのxml の直下(姉妹の一番下:末っ子)にノード(属性は指定しない)を挿入する.
tXML* insert_xml_node(tXML* xml, const char* name); ///< XMLツリーのxml の直下(姉妹の一番上:長子)にノード(属性は指定しない)を挿入する.
tXML* add_xml_attr(tXML* xml, const char* attr); ///< xml に属性(attr)を追加する.
tXML* add_xml_attr_str (tXML* xml, const char* name, const char* value);///< xml に属性名 name, 文字列の属性値 value を持つノードを追加する.
tXML* add_xml_attr_int (tXML* xml, const char* name, int value); ///< xml に属性名 name, 整数の属性値 value を持つノードを追加する.
tXML* add_xml_attr_float (tXML* xml, const char* name, float value); ///< xml に属性名 name, float型実数の属性値 value を持つノードを追加する.
tXML* add_xml_attr_double(tXML* xml, const char* name, double value); ///< xml に属性名 name, double型実数の属性値 value を持つノードを追加する.
tXML* add_xml_content(tXML* xml, const char* value); ///< XMLツリーのxml の直下にコンテントを挿入する.
tXML* append_xml_content(tXML* xml, const char* value); ///< XMLツリーのxml の直下のコンテントノードにコンテンツを追加する.
int add_xml_content_area(tXML* xml, int len); ///< xml に空のコンテントノードを追加する.
#define join_xml(a, b) add_tTree_node((a), (b)) ///< add_tTree_node()
Buffer make_xml_attr_bystr (const char* name, const char* value); ///< 属性名 name, 文字列の属性値 value を持つ Buffer型変数を作成する.
Buffer make_xml_attr_byint (const char* name, int value); ///< 属性名 name, 整数の属性値 value を持つ Buffer型変数を作成する.
Buffer make_xml_attr_byfloat (const char* name, float value); ///< 属性名 name, float型実数の属性値 value を持つ Buffer型変数を作成する.
Buffer make_xml_attr_bydouble(const char* name, double value); ///< 属性名 name, double型実数の属性値 value を持つ Buffer型変数を作成する.
#define make_xml_attr_str(n, v) make_xml_attr_bystr ((n), (v)) ///< make_xml_attr_bystr()
#define make_xml_attr_int(n, v) make_xml_attr_byint ((n), (v)) ///< make_xml_attr_byint()
#define make_xml_attr_float(n, v) make_xml_attr_byfloat ((n), (v)) ///< make_xml_attr_byfloat()
#define make_xml_attr_double(n, v) make_xml_attr_bydouble((n), (v)) ///< make_xml_attr_bydouble()
char* xml_get_node_content(tXML* node); ///< コンテントへのポインタを返す.free() してはいけない.
char* xml_get_node_attr(tXML* node, const char* attr); ///< 属性値を持つノードのポインタから,指定された属性値へのポインタを返す.free() してはいけない.
tXML* dup_merge_xml(tXML* pp, tXML* tp); ///< XMLツリー ppの直下にXMLツリー tpを複製する.
#define free_xml(p) free_tTree_node((p)) ///< free_tTree_node()
#define del_xml(p) del_tTree((p)) ///< 指定したノード以下のXMLツリー(ppの姉妹は含まない)を削除する.
#define del_all_xml(p) del_all_tTree((p)) ///< XMLツリーの全ノードの削除.ポインタ ppのノードを含むXMLツリー全体を削除する.
#define del_sisters_xml(p) del_sisters_tTree((p)) ///< 指定したノード以下のXMLツリー(ppの姉妹を含む)を削除する.
#define del_sisters_children_xml(p) del_sisters_children_tTree((p)) ///< 指定したノードの姉妹XMLツリー,子XMLツリーを削除する.指定したXMLノードも削除する.
void print_xml(FILE* fp, tXML* pp, int mode); ///< XMLの表示(出力).
void print_xml_tree(FILE* fp, tXML* pp, const char* space); ///< XMLツリーをそのままツリー表示する.デバッグ用.
void print_xml_node(FILE* fp, tXML* pp); ///< MLのノード情報を表示する.デバッグ用.
void print_sister_xml_tree(FILE* fp, tXML* pp, const char* space); ///< XMLツリーの表示.ppの姉妹ノードも出力する.
#define print_tXML(f, x) print_tTree((f), (x))
#define print_tXML_tree(f, x, s) print_tTree_tree((f), (x), (s))
///////////////////////////////////////////////////////////////////////////////////////////
// Search and Get/Set 操作対象は1番最初に一致したもの
tXML* get_xml_node(tXML* pp, tXML* pt); ///< 同じパターンの枝を探し,ptに最初に一致した枝の,ptの最後のノードに対応したノードへのポインタを返す.
int set_xml_node(tXML* pp, tXML* pt, const char* val); ///< 同じパターンの枝を探し,ptに最初に一致した枝の,ptの最後のノード対応したノードにノード名をコピーする.
int set_xml_end_node(tXML* pp, tXML* pt); ///< 同じパターンの枝を探し,ptに最初に一致した枝の,
tXML* get_xml_content(tXML* pp, tXML* pt); ///< 同じパターンの枝を探し,ptに最初に一致した枝の,ptの最後のノードに対応したノードのコンテントへのポインタを返す.
int set_xml_content(tXML* pp, tXML* pt, const char* val);///< 同じパターンの枝を探し,ptに最初に一致した枝の,ptの最後ノードに対応したのノードのコンテントを contentで置き換える.
tList* get_xml_attr(tXML* pp, tXML* pt); ///< 同じパターンの枝を探し,ptに最初に一致した枝の,ptの最後のノードに対応したノードのノード属性値へのリストを返す.
int set_xml_attr(tXML* pp, tXML* pt, tList* at); ///< 同じパターンの枝を探し,ptに最初に一致した枝の,ptの最後のノードに対応したノードのノードの属性としてatの値をコピーする.
tXML* get_xml_node_bystr(tXML* pp, const char* str); ///< get_xml_node(tXML* pp, tXML* pt) の _bystr バージョン
int set_xml_node_bystr(tXML* pp, const char* str, const char* val); ///< set_xml_node(tXML* pp, tXML* pt, const char* val) の _bystr バージョン
int set_xml_end_node_bystr(tXML* pp, const char* str); ///< set_xml_end_node(tXML* pp, tXML* pt) の _bystr バージョン
tXML* get_xml_content_bystr(tXML* pp, const char* str); ///< get_xml_content(tXML* pp, tXML* pt) の _bystr バージョン
int set_xml_content_bystr(tXML* pp, const char* str, const char* val); ///< set_xml_content(tXML* pp, tXML* pt, char* val) の _bystr バージョン
tList* get_xml_attr_bystr(tXML* pp, const char* str); ///< get_xml_attr(tXML* pp, tXML* pt, tList* at) の _bystr バージョン.
int set_xml_attr_bystr(tXML* pp, const char* pt, tList* at); ///< set_xml_attr(tXML* pp, tXML* pt, tList* at) の _bystr バージョン.
int get_xml_int_content(tXML* pp, tXML* pt); ///< get_xml_content() を使用し,XML コンテンツの内容を int型で返す.
int get_xml_int_content_bystr(tXML* pp, const char* str); ///< get_xml_int_content(tXML* pp, tXML* pt) の _bystr バージョン
float get_xml_float_content(tXML* pp, tXML* pt); ///< get_xml_content() を使用し,XML コンテンツの内容を float型で返す.
float get_xml_float_content_bystr(tXML* pp, const char* str); ///< get_xml_float_content(tXML* pp, tXML* pt) の _bystr バージョン.
double get_xml_double_content(tXML* pp, tXML* pt); ///< get_xml_content() を使用し,XML コンテンツの内容を double型で返す.
double get_xml_double_content_bystr(tXML* pp, const char* str); ///< get_xml_double_content(tXML* pp, tXML* pt) の _bystr バージョン.
char* get_xml_char_content(tXML* pp, tXML* pt); ///< get_xml_content() を使用し,XML コンテンツの内容を char*型で返す.free() してはいけない.
char* get_xml_char_content_bystr(tXML* pp, const char* str); ///< get_xml_char_content(tXML* pp, tXML* pt) の _bystr バージョン.free() してはいけない.
char* get_xml_char_attr(tXML* pp, tXML* pt, const char* attr); ///< get_xml_node() で検索したノードから,属性値 attrの値を char*型で取り出す.free() してはいけない.
char* get_xml_char_attr_bystr(tXML* pp, const char* str, const char* attr); ///< get_xml_char_attr() の _bystr バージョン.free() してはいけない.
int get_xml_int_attr(tXML* pp, tXML* pt, const char* attr); ///< get_xml_node() で検索したノードから,属性値 attrの値を int型で取り出す.
int get_xml_int_attr_bystr(tXML* pp, const char* str, const char* attr); ///< get_xml_int_attr() の _bystr バージョン.
double get_xml_double_attr(tXML* pp, tXML* pt, const char* attr); ///< get_xml_node() で検索したノードから,属性値 attrの値を double型で取り出す.
double get_xml_double_attr_bystr(tXML* pp, const char* str, const char* attr); ///< get_xml_double_attr() の _bystr バージョン.
int replace_xml_content(tXML*pp, tXML* pt, const char* src, const char* dst); ///< get_xml_content() を使用し,XMLキーの src部分を dstで書き換える.
int replace_xml_content_bystr(tXML*pp, const char* str, const char* src, const char* dst); ///< replace_xml_content(tXML*pp, tXML* pt, char* src, char* dst) の _bystr バージョン.
#define get_xml_node_str(p, s) get_xml_node_bystr((p), (s)) ///< get_xml_node_bystr()
#define set_xml_node_str(p, s, v) set_xml_node_bystr((p), (s), (v)) ///< set_xml_node_bystr()
#define set_xml_end_node_str(p, s) set_xml_end_node_bystr((p), (s)) ///< set_xml_end_node_bystr()
#define get_xml_content_str(p, s) get_xml_content_bystr((p), (s)) ///< get_xml_content_bystr()
#define set_xml_content_str(p, s, v) set_xml_content_bystr((p), (s), (v)) ///< set_xml_content_bystr()
#define get_xml_attr_str(p, s) get_xml_attr_bystr((p), (s)) ///< get_xml_attr_bystr()
#define set_xml_attr_str(p, t, a) set_xml_attr_bystr((p), (t), (a)) ///< set_xml_attr_bystr()
#define replace_xml_content_str(p, t, r, d) replace_xml_content_bystr((p), (t), (r), (d)) ///< replace_xml_content_bystr()
#define get_xml_int_content_str(p, s) get_xml_int_content_bystr((p), (s)) ///< get_xml_int_content_bystr()
#define get_xml_double_content_str(p, s) get_xml_double_content_bystr((p), (s)) ///< get_xml_double_content_bystr()
#define get_xml_char_content_str(p, s) get_xml_char_content_bystr((p), (s)) ///< get_xml_char_content_bystr()
#define get_xml_char_attr_str(p, s, v) get_xml_char_sttr_bystr((p), (s), (v)) ///< get_xml_char_sttr_bystr()
#define get_xml_str_content(p, s) get_xml_char_content((p), (s)) ///< get_xml_char_content()
#define get_xml_str_content_str(p, s) get_xml_char_content_bystr((p), (s)) ///< get_xml_char_content_bystr()
#define get_xml_str_content_bystr(p, s) get_xml_char_content_bystr((p), (s)) ///< get_xml_char_content_bystr()
#define get_xml_str_attr(p, s) get_xml_char_attr((p), (s)) ///< get_xml_char_attr()
#define get_xml_str_attr_str(p, s, v) get_xml_char_attr_bystr((p), (s), (v)) ///< get_xml_char_attr_bystr()
#define get_xml_str_attr_bystr(p, s, v) get_xml_char_attr_bystr((p), (s), (v)) ///< get_xml_char_attr_bystr()
#define get_xml_int_attr_str(p, s, v) get_xml_int_attr_bystr((p), (s), (v)) ///< get_xml_int_attr_bystr()
#define get_xml_double_attr_str(p, s, v) get_xml_double_attr_bystr((p), (s), (v)) ///< get_xml_double_attr_bystr()
// Operation for Multi Node
tList* get_xml_node_list(tXML* pp, tXML* pt); ///< XMLツリー pp内で XMLツリー ptと同じパターンの枝を探し,ptに一致した枝の,ptの最後のノードに対応するノードへのポインタをリストに格納して返す.
tList* get_xml_content_list(tXML* pp, tXML* pt); ///< XMLツリー pp内で XMLツリー ptと同じパターンの枝を探し,ptに一致した枝の,ptの最後のノードに対応するノードのコンテントへのポインタをリストに格納して返す.
int set_xml_content_list(tXML* pp, tXML* pt, const char* content); ///< get_xml_content_list() で検出したコンテントを, content で置き換える.
tList* get_xml_node_list_bystr(tXML* pp, const char* str); ///< get_xml_node_list() の _bystr バージョン.
tList* get_xml_content_list_bystr(tXML* pp, const char* str); ///< get_xml_conetnt_list_bystr() の _bystr バージョン.
int set_xml_content_list_bystr(tXML* pp, const char* str, const char* content); ///< set_xml_content_list_bystr() の _bystr バージョン.
#define get_xml_node_list_str(p, s) get_xml_node_list_bystr((p), (s)) ///< get_xml_node_list_bystr()
#define get_xml_content_list_str(p, s) get_xml_content_list_bystr((p), (s)) ///< get_xml_content_list_bystr()
#define set_xml_content_list_str(p, s, c) set_xml_content_list_bystr((p), (s), (c)) ///< set_xml_content_list_bystr()
///////////////////////////////////////////////////////////////////////////////////////////
// Search XML Node (tTree用の関数とほぼ同じ)
int find_match_xml(tXML* pp, tXML* pt); ///< ツリー pp内で ツリー ptと同じパターンの枝を探す.姉妹ツリーも検索するので注意.
tXML* find_match_xml_endlist(tXML* pp, tXML* pt); ///< ツリー pp内で ツリー ptと同じパターンの枝を全て探して,その枝のptの最後のノードに対応するノードの情報をリストにして返す.
tList* find_match_xml_endlist_rcsv(tXML* pp, tXML* pt, tXML* te); ///< find_match_xml_endlist() の補助関数
tXML* find_match_xml_end_node(tXML* pp, tXML* pt); ///< XMLツリー pp内で XMLツリー ptと同じパターンの枝を探し,ptの最後のノードに対応する pp内のノードへのポインタを返す.
int check_match_xml(tXML* tp, tXML* tr); ///< XMLツリー tpが XMLツリー trと同じかどうかを検査する.
tXML* cmp_sisters_xml(tXML* tp, tXML* tr); ///< XMLノード tpの姉妹ノードが trの姉妹ノードと同じ XMLノードまたはコンテントであるかを比較する.
/////////////////////////////////////////////////////////////////////////////////////////////
// Simple Node Functions.
int get_node_integer(tXML* tp, const char* name, int no); ///< tp中のXMLデータから no番目のノード '@node_content(整数)@' の node_content(整数)を得る.
Buffer get_node_content(tXML* tp, const char* name, int no); ///< tp中のXMLデータから no番目のノード '@node_content@' のnode_contentのコピーを得る.
int return_exist_node(tXML* tp, const char* name, int no, Buffer* value); ///< bufの中に ノード '@content@' が存在するかどうかチェックする.
int replace_all_node_integer (tXML* tp, const char* name, int src, int dst); ///< XMLツリー pp内で ノード名が nameである全てのノードのコンテント(整数)を,srcから dstに書き換える.
int replace_all_node_contents(tXML* tp, const char* name, const char* src, const char* dst); ///< XMLツリー pp内で ノード名が nameである全てのノードのコンテントを,srcから dstに書き換える.
int replace_all_node_contents_rcsv(tXML* tp, const char* name, const char* src, const char* dst); ///< replace_all_node_content() の補助関数
int replace_all_node_byid(tXML* tp, const char* src, const char* dst, int id); ///< XMLツリー pp内で ノードの種別が idである全てのノードの内容を srcから dstに書き換える.
int replace_all_node_byid_rcsv(tXML* tp, const char* src, const char* dst, int id); ///< replace_all_node_byid() の補助関数
/////////////////////////////////////////////////////////////////////////////////////////////
// XML-RPC
Buffer xml_rpc_request_pack(const char* method, tXML* xml); ///< XML-RPC用のデータを生成する.
tXML* xml_rpc_add_member(tXML* xml, char* name, char* value, char* kind); ///< XML-RPC の @ データを作って,繋げていく.
tXML* xml_rpc_end_member(tXML* xml); ///< @@ データを閉じて,@ データを作り出す.
tXML* xml_rpc_add_array(tXML* xml, tXML* arry); ///< @@ データから 配列データ @...@ を作って繋げていく.
tXML* xml_rpc_end_array(tXML* xml); ///< 配列データを閉じて,送信用データを生成する.
#endif // __JBXL_TINY_XML_H_