SXML: C言語用簡易XML解析ライブラリ

更新履歴

[2007/09/04 (Tue)]
同梱の XML-RPC 用ライブラリ中の sxmlrpc_server() から呼ばれる callback 関数に接続元 IP アドレスを渡すように API が変更になりました。 そのため、sxml-1.0.5 を置き換えました。 XML 解析ライブラリ自身の変更はなし。

[2007/09/02 (Sun)]
XML の prolog 解析 API を実装した sxml-1.0.5 を公開。

[2007/08/29 (Wed)]
sxmlrpc_set_encoding() API を実装した sxml-1.0.4.2 を公開。

[2007/08/21 (Tue)]
ソースコードのリンクが間違っていたのを訂正。

[2007/07/06 (Fri)]
wyvern-2.2.7 のリリースに伴い sxml-1.0.4 を公開。

概要

SXML は、C 言語用簡易 XML 解析ライブラリです。 XML のタグと属性に対応した構文解析が可能です。 また、XML 形式の木構造を組み立てる API も実装してありますので、 C プログラムで XML 形式の文書ファイルを作成できます。 XML 形式で設定を記述するアプリケーションの設定ファイル用に実装しました。 ドキュメントがないので、 同梱のサンプルプログラムや以下のライブラリの使い方を参考にしてください。

ダウンロード

SXML 1.0.5-RELEASE(2007/09/02)

パッケージ名 サイズ MD5値
sxml-1.0.5.tar.gz 71,938 aa09a9caaf27852c37aaafc38664c49b
sxml-1.0.5.tar.bz2 61,771 e889de22e5f4e79b57cef22b994a09ee

ライブラリの使い方

XML 形式のファイルを解析する場合

SXML ライブラリの簡単な使い方を説明します。 ここでは例として、 次に示す XML 形式の内容を記述したファイル(ex.xmlとします)の構造を解析するプログラムを考えます。


  <server>
    <address>192.168.1.234</address>
    <port>25</port>
  </server>

下記ソースコードに XML を解析する場合に利用する SXML の基本的な関数が含まれています。


  #include <stdio.h>
  #include <stdlib.h>
  #include <unistd.h>
  #include <string.h>
  #include <fcntl.h>
  #include <sxml.h>

  #define TAG_ROOT        "server"
  #define ROOT_ATTR_NAME  NULL
  #define ROOT_ATTR_VALUE NULL
  #define TAG_ADDRESS     "address"
  #define TAG_PORT        "port"

  static void parse(sxml_node_t * node);

  int main(int argc, char * argv[])
  {
    int fd;

    if ((fd = open("ex.xml", O_RDONLY, 0400)) != -1) {
      sxml_node_t * root; /* 解析木を保存する変数 */

      /* XML の解析結果が root 変数に設定される */
      if ((root = sxml_parse_file(fd)) != NULL) {
        parse(root);
        sxml_delete_node(root); /* メモリ解放 */
      }
      close(fd);
    }

    return 0;
  }

  static void
  parse(sxml_node_t * root)
  {
    sxml_node_t * node;

    /*
     * TAG_ROOT の要素名で ROOT_ATTR_NAME 属性と
     * ROOT_ATTR_VALUE 値を持つタグから解析を開始する
     */
    node = sxml_find_element(root, TAG_ROOT, ROOT_ATTR_NAME,
                                          ROOT_ATTR_VALUE);
    if (node != NULL) {
      sxml_node_t * np;

      for (np = sxml_get_child(node); np != NULL;
           np = sxml_get_next_sibling(np)) {
        const char * content;

        /* タイプが要素でない場合はスキップ */
        if (sxml_get_type(np) != SXML_ELEMENT) { continue; }

        /* 要素名が存在しない場合はスキップ */
        if (sxml_get_element_name(np) == NULL) { continue; }

        /* np 変数で示される子要素の内容を content に設定 */
        content = sxml_get_content(sxml_get_child(np));

        /* <address> タグの処理 */
        if (strcmp(sxml_get_element_name(np), TAG_ADDRESS) == 0) {
          fprintf(stdout, "address: %s\n", content);
        }
        /* <port> タグの処理 */
        else if (strcmp(sxml_get_element_name(np), TAG_PORT) == 0) {
          fprintf(stdout, "port: %s\n", content);
        }
        else {
          /* 定義されていないタグ名をここで表示 */
          fprintf(stderr, "WARN: unknown tag: %s\n",
                  sxml_get_element_name(np));
        }
      }
    }
  }

上記のプログラムを "ex1.c" というファイル名で保存した場合、 次のようにコマンドを実行してコンパイルします。


  % gcc -I/usr/local/include -L/usr/local/lib ex1.c -o ex1 -lsxml

エラーが起きなければ、実行ファイル "ex1" が作成されます。 以下がプログラムの実行結果です。


  % ./ex1
  address: 192.168.1.234
  port: 25

XML 形式の設定ファイルを持つアプリケーションを実装する際には、 fprintf() 関数で表示しているコードを自作プログラムの変数への設定に改良すればよいでしょう。 ミニウェブサーバ Wyvern の設定ファイルは、 SXML を使って解析していますので、 具体的な実装例は、Wyvern のソースコードを参考にしてください。

XML 形式で出力する場合

ここでは、 次に示す XML 形式の出力を行う場合のプログラムについて考えます。


  <person>
    <name>Kouichi ABE (WALL)</name>
    <email>kouichi@MysticWALL.COM</email>
  </person>

下記ソースコードが XML 形式の出力を行う場合の基本的なプログラムです。


  #include <stdio.h>
  #include <sxml.h>

  int main(int argc, char * argv[])
  {
    sxml_node_t * root; /* XML 構文木用変数 */

    /* 新しい XML 構文木を root 変数に作成 */
    if ((root = sxml_new_vertex()) != NULL) {
      const char name[] = "Kouichi ABE (WALL)";
      const char email[] = "kouichi@MysticWALL.COM";
      sxml_node_t * ep;

      /* <person> タグ作成 */
      if ((ep = sxml_new_element(root, "person")) != NULL) {
        /* <name> タグを作成し、name 変数を要素の値とする */
        sxml_set_node(ep, "name", name);
        /* <email> タグを作成し、email 変数を要素の値とする */
        sxml_set_node(ep, "email", email);
      }
      sxml_print_tree(root, stdout); /* 標準出力に表示 */
      sxml_delete_node(root); /* メモリ解放 */
    }

    return 0;
  }

上記のプログラムを "ex2.c" というファイル名で保存した場合、 次のようにコマンドを実行してコンパイルします。


  % gcc -I/usr/local/include -L/usr/local/lib ex2.c -o ex2 -lsxml

エラーが起きなければ、実行ファイル "ex2" が作成されます。 実行すると最初に設計した通りの、XML 形式で出力されます。


  % ./ex2
  <person>
    <name>Kouichi ABE (WALL)</name>
    <email>kouichi@MysticWALL.COM</email>
  </person>

プログラミング講座の第三回郵便番号から住所を取得するでは、 sxmlrpc ライブラリを使った XML-RPC サーバ/クライアント・プログラムの実装について述べていますので、 こちらも参考にしてください。

Google