Domanda

Ho una serie di report HTML che contengono ciascuno due elementi DIV con ID specifici che devo rimuovere e compilare in un report di riepilogo generale (di nuovo, un file HTML).

Il mio pensiero iniziale è che questo è un lavoro ideale per uno script Perl, tuttavia non abbiamo competenze Perl interne aggiornate (siamo un negozio .NET C #).

Pensieri e suggerimenti sugli approcci raccomandati sarebbero i benvenuti ...

È stato utile?

Soluzione

Utilizza un parser HTML adatto; c'è HTML :: Parser per Perl e sono sicuro che ce ne sono molti per C # as bene.

Altri suggerimenti

Utilizzo di Perl, HTML :: TokeParser e HTML :: Template può aiutarti. Ecco un breve esempio:

#!/usr/bin/perl

use strict;
use warnings;

use HTML::TokeParser;
use HTML::Template;

use Data::Dumper;

my ($html_file) = @ARGV;

open my $html_handle, '<:utf8', $html_file
    or die "Cannot open '$html_file': $!";

my $parser = HTML::TokeParser->new( $html_handle );

my @divs;

while ( my $tag = $parser->get_tag('div') ) {
    my $attr = $tag->[1];
    next unless ref $attr eq 'HASH';
    next unless defined( my $id = $attr->{id} );
    next unless $id eq 'div1' or $id eq 'div2';

    my $div = $tag->[-1];
    my $in_wanted = 1;

    while ( $in_wanted ) {
        my $token = $parser->get_token;
        if ( $token->[0] eq 'T' ) {
            $div .= $token->[1];
        }
        else {
            $div .= $token->[-1];
        }
        my ($type, $name) = @$token[0, 1];
        if ( $name eq 'div' ) {
            $in_wanted += $type eq 'S' ?  1
                        : $type eq 'E' ? -1
                        : 0;
            next;
        }
        if ( $type eq 'E' and $name eq 'html' ) {
            warn "Warning: Reached the end of '$html_file'\n";
            last;
        }
    }

    push @divs, {DIV => $div};
}

print output( @divs );

sub output {
    my $tmpl_html = <<EO_TMPL;
<html>
<body>
<TMPL_LOOP DIVS>
    <TMPL_VAR DIV>
</TMPL_LOOP>
</body>
</html>
EO_TMPL
    my $tmpl = HTML::Template->new(
        scalarref => \$tmpl_html,
    );
    $tmpl->param( DIVS => \@_ );
    return $tmpl->output;
}

Le espressioni regolari semplici potrebbero non essere sufficienti se il div contiene div nidificati. Questo perché l'elemento div di chiusura non contiene l'ID, quindi è difficile che un regexp corrisponda al tag di chiusura.

Se il tuo div è:

<div id="findme">
    <!-- No other divs here! -->
</div>

Quindi potresti usare un'espressione regolare (fai solo attenzione all'avidità), una versione più elegante di questo:

<div id="findme">(.*?)</div>

nota: sono abbastanza sicuro che regexp non funzionerà, è passato del tempo!

Vorrei esaminare l'uso di una libreria di parser HTML per analizzare la struttura e ottenere offset dei caratteri per l'interno del div, quindi prendere quell'intervallo dal buffer. L'uso di una libreria HTML ti permetterà di analizzare e trovare dove finisce il div che desideri.

Qualcosa come questo tutorial potrebbe essere utile. Questi parser probabilmente ti permetteranno di estrarre accuratamente i dati racchiusi in un tag come il tuo div.

Puoi anche utilizzare un parser HTML C # , fanno tutti un lavoro simile, basta guardare attraverso la documentazione per assicurarsi che non si limitino a costruire alberi e permettervi di ottenere offset dei caratteri per i dati div racchiusi (in modo da poterli estrarre) o consentire l'accesso a tali dati.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top