XMLパーサーとは何ですか? Expatを使用する
-
03-07-2019 - |
質問
これは簡単な質問のように思えるかもしれません。
しかし、Linuxで実行されているアプリケーションの1つで使用するXMLパーサーを探しています。
Expat を使用しており、XMLファイルを読み取って解析しましたin。ただし、出力は入力と同じです。
これは私が読んでいる私のファイルです:
<?xml version="1.0" encoding="utf-8"?>
<books>
<book>
<id>1</id>
<name>Hello, world!</name>
</book>
</books>
ただし、これに合格した後は、出力とまったく同じになります。パーサーは何のためにあるのだろうと思いますか?
もう1つ。 Expatを使用しています。これは非常に使いにくいようです。私のコードは以下のとおりです。これはファイルを読み込みます。しかし、私のアプリケーションは、ファイルからではなく、ソケットによって受信されるバッファーを解析する必要があります。誰かが持っているこのサンプルはありますか?
int parse_xml(char *buff)
{
FILE *fp;
fp = fopen("mybook.xml", "r");
if(fp == NULL)
{
printf("Failed to open file\n");
return 1;
}
/* Obtain the file size. */
fseek (fp, 0, SEEK_END);
size_t file_size = ftell(fp);
rewind(fp);
XML_Parser parser = XML_ParserCreate(NULL);
int done;
memset(buff, 0, sizeof(buff));
do
{
size_t len = fread(buff, 1, file_size, fp);
done = len < sizeof(buff);
if(XML_Parse(parser, buff, len, done) == XML_STATUS_ERROR)
{
printf("%s at line %d\n", XML_ErrorString(XML_GetErrorCode(parser)),
XML_GetCurrentLineNumber(parser));
return 1;
}
}
while(!done);
fclose(fp);
XML_ParserFree(parser);
return 0;
}
解決
XML構文解析に頭を包むのに時間がかかりました(ただし、CではなくPerlで行います)。基本的に、コールバック関数を登録します。パーサーは、各ノードに対してコールバックをpingし、あらゆる種類のジューシーなビット(プレーンテキスト、属性、子ノードなど)を含むデータ構造を渡します。何らかの種類の状態情報を保持する必要があります。たとえば、ハッシュツリーを挿入したり、すべての内臓を含むがXMLをまったく含まない文字列などです。
XMLは線形ではなく、長いテキストの塊のようにXMLを解析することはあまり意味がないことを覚えておいてください。代わりに、ツリーのように解析します。幸運を祈ります。
他のヒント
Expatは偶数駆動のパーサーです。タグ、属性などを処理するコードを作成してから、パーサーにコードを登録する必要があります。方法を説明した記事こちらがあります。これ。
ソケットからの読み取りについては、プラットフォームによっては、ソケットをファイルハンドルのように扱うことができる場合があります。それ以外の場合は、ソケットから独自の読み取りを実行してから、データを明示的にexpatに渡す必要があります。これを行うAPIがあります。ただし、最初に通常のファイルで動作するようにしようと思います。
expatの代わりに、おそらくディストリビューションに既に含まれているlibxml2を調べてください。 expatよりもはるかに強力であり、DOM(ツリーモード)、SAX(ストリーミングモード)、XPath(XML IMHOで複雑なことを行うために不可欠)など、あらゆる種類の機能を提供します。 expatほど軽量ではありませんが、使いやすいです。
まあ、あなたは最も複雑なXMLパーサーを選択しました(イベント駆動型パーサーの処理はより困難です)。 libxml ではなくExpatを使用する理由