2012-02-23 12 views
7

おはよう!私はDelphi XEとIndy TIdHTTPを使用しています。 Getメソッドを使用すると、リモートディレクトリのリストが取得され、解析する必要があります。サイズとタイムスタンプを持つファイルのリストを取得し、ファイルとサブディレクトリを区別します。してください、それを行う良いルーチンがありますか?前もって感謝します! VojtechHTTPディレクトリ一覧を解析する

ここではサンプルです:コードサンプルを考えると

<head> 
    <title>127.0.0.1 - /</title> 
</head> 
<body> 
    <H1>127.0.0.1 - /</H1><hr> 
<pre>  
    Mittwoch, 30. März 2011 12:01  &lt;dir&gt; <A HREF="/SubDir/">SubDir</A><br /> 
    Mittwoch, 9. Februar 2005 17:14   113 <A HREF="/file.txt">file.txt</A><br /> 
</pre> 
<hr> 
</body> 
+4

サンプルがありますか?実際には標準的な "ディレクトリリスト"はありません(実際には、サーバーやOSに応じて*いくつかの*があります)。また、作業していることがわからなくても、する必要があります。 –

+1

あなたが必要とするのはツリーを作成するHTMLパーサです。したがって、すべての "A"タグを見つけて必要に応じて動作させるのは簡単でしょう。 – ComputerSaysNo

+1

サーバがWebDAVをサポートしている場合、より堅牢なソリューションはWebDAVクライアントライブラリで簡単に実装できます。すべてのサーバーバージョンの更新またはソフトウェアの変更により、このHTML出力に固有のパーサーが破損します。 – mjn

答えて

7

は、私はそれを解析する最速の方法は、このようなものだと思います:

  • すべて含む<pre>...</pre>ブロックを特定しますリストライン。簡単にする必要があります。
  • <pre></pre>の間のすべてをTStringListに入れます。各行はファイルまたはフォルダであり、形式は非常に単純です。
  • 各行のリンクを抽出し、必要に応じて日付、時刻、サイズを抽出します。正規表現を使った方がいい(Delphi XEを持っているのでRegexが組み込まれている)。
+6

+1。サンプルがあれば簡単です。私は尋ねてうれしいですか? :) –

7

これはあなたのDOMを使用して良いスタートとアイデアを与える必要があります。

uses 
    MSHTML, 
    ActiveX, 
    ComObj; 

procedure DocumentFromString(Document: IHTMLDocument2; const S: WideString); 
var 
    v: OleVariant; 
begin 
    v := VarArrayCreate([0, 0], varVariant); 
    v[0] := S; 
    Document.Write(PSafeArray(TVarData(v).VArray)); 
    Document.Close; 
end; 

function StripMultipleChar(const S: string; const C: Char): string; 
begin 
    Result := S; 
    while Pos(C + C, Result) <> 0 do 
    Result := StringReplace(Result, C + C, C, [rfReplaceAll]); 
end; 

procedure TForm1.Button1Click(Sender: TObject); 
var 
    Document: IHTMLDocument2; 
    Elements: IHTMLElementCollection; 
    Element: IHTMLElement; 
    I: Integer; 
    Line: string; 
begin 
    Document := CreateComObject(CLASS_HTMLDocument) as IHTMLDocument2; 
    DocumentFromString(Document, '<head>...'); // your HTML here 

    Elements := Document.all.tags('A') as IHTMLElementCollection; 
    for I := 0 to Elements.length - 1 do 
    begin 
    Element := Elements.item(I, '') as IHTMLElement; 
    Memo1.Lines.Add('A HREF=' + Element.getAttribute('HREF', 2)); 
    Memo1.Lines.Add('A innerText=' + Element.innerText); 

    // Text is returned immediately before the element 
    Line := (Element as IHTMLElement2).getAdjacentText('beforeBegin'); 

    // Line => "Mittwoch, 30. März 2011 12:01 <dir>" OR: 
    // Line => "Mittwoch, 9. Februar 2005 17:14 113"... 
    // I don't know what is the actual delimiter: 
    // It could be [space] or [tab] so we need to normalize the Line 
    // If it's tabs then it's easier because the timestamps also contains spaces 

    Line := Trim(Line); 
    Line := StripMultipleChar(Line, #32); // strip multiple Spaces sequences 
    Line := StripMultipleChar(Line, #9); // strip multiple Tabs sequences 

    // TODO: ParseLine (from right to left) 

    Memo1.Lines.Add(Line); 
    Memo1.Lines.Add('-------------'); 
    end; 
end; 

出力:

A HREF=/SubDir/ 
A innerText=SubDir 
Mittwoch, 30. März 2011 12:01 <dir> 
------------- 
A HREF=/file.txt 
A innerText=file.txt 
Mittwoch, 9. Februar 2005 17:14 113 
------------- 

編集:私はを変更した
の実装は、を簡略化したです。しかし、私は以前のバージョンを信じてより多くのを高速化されました。ラインの長さが非常に短いという事実を考慮すると、パフォーマンスに大きな違いはありません。

+0

+1すると動作します。 'StripMultipleChar'は少し単純化することができます。 –

+0

*簡略化*最適化*することができます。 *ループがたくさんあるので、頭が回転します。必要なのは、単一直線のforループです。 –

+0

@Cosmin Prund、私の編集を参照してください。前者の機能は実際にJCLユニットの1つに基づいていました... – kobik

関連する問題