Thread HTML::Parser - Attribute von HTML ändern, welche sich nicht(!) unterhalb <pre> oder <code> befinden (21 answers)
Opened by GwenDragon at 2023-01-30 18:12

GwenDragon
 2023-01-30 18:12
#194611 #194611
User since
2005-01-17
14533 Artikel
Admin1
[Homepage]
user image
Gibt es eine Möglichkeit bei HTML::Parser die Kind-Elemente de Eltern-Elemente <CODE> und <PRE> unverändert auszugeben?
CPAN:HTML::Parser ist immer so eine komplizierte Sache.

Meine Lösung (oder geht's noch einfacher oder robuster?):
Code (perl): (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
#!/usr/bin/perl

use strict;
use warnings;
use 5.024;
use utf8;

use HTML::Parser;
use URI;

my $current_uri = "https://example.org/tests/"
  ;    # enthält aktuelle URL (notwendig für relative URLs)

my $source = <<'HTML';
<ul>
<li><a href="." title="Anfang">Test</a>
<li><a href="test.html" title="Erster Test" class="c1">Test 1</a>
<li><a href="Test1/test.html">Test 2</a>
<li><a href="http://example.org/example/Test1/test.html">Test 3</a>
<li><a href="//example.org/example/Test1/test.html">Test 4</a>
<li><a href="./example/Test1/test.html">Test 5</a>
<li><a href="./example/.././../../Test1/test.html">Test 6</a>
<li><a href="a/s/d/f/g/h/j//test.html">Test 7</a>
</ul>

<?php
        # auch hier nix ändern 
        # <a href="test.html" title="Erster Test" class="c1">Test 1</a>
?>

<!-- Kommentarblock; auch hier nix ändern!!!!
<ul>
<li><a href="." title="Anfang">Test</a>
<li><a href="test.html" title="Erster Test" class="c1">Test 1</a>
<li><a href="Test1/test.html">Test 2</a>
<li><a href="http://example.org/example/Test1/test.html">Test 3</a>
<li><a href="//example.org/example/Test1/test.html">Test 4</a>
<li><a href="./example/Test1/test.html">Test 5</a>
<li><a href="./example/.././../../Test1/test.html">Test 6</a>
<li><a href="a/s/d/f/g/h/j//test.html">Test 7</a>
</ul>
-->

<pre><code> 
<!-- Hier im PRE oder CODE-Kindern erst recht niemals was ändern!!!! -->
<ul>
        <li><a href=".">Test</a>
        <li><a href="test.html">Test 1</a>
        <li><a href="Test1/test.html">Test 2</a>
        <li><a href="http://example.org/example/Test1/test.html">Test 3</a>
        <li><a href="//example.org/example/Test1/test.html">Test 4</a>
        <li><a href="./example/Test1/test.html">Test 5</a>
        <li><a href="./example/.././../../Test1/test.html">Test 6</a>
        <li><a href="a/s/d/f/g/h/j//test.html">Test 7</a>
</ul>
</code></pre>
HTML

### Hier kommt der Parser
{
    # HTML-Parser erzeugen
    my $p = HTML::Parser->new();

    $p->empty_element_tags( 1 );

    # Handlerroutine für bestimmte Startelemente registrieren
    $p->handler( start => \&start, "tagname,attr,self" );

    # Handlerroutine für normalen Textinhalt registrieren
    $p->handler( text => sub { print shift }, "dtext,self" );

    # Kommentare
    $p->handler( comment => sub { print shift }, "text" );

    # PHP oder anderes
    $p->handler( process => sub { print shift }, "text" );

    # HTML scannen
    $p->parse( $source );

    # Parsen beenden
    $p->eof;

    # Handler für HTML-Startelemente
    sub start {
        my ( $tag, $attr, $self ) = @_;

        # HTML-Element <PRE>
        if ( lc $tag eq "pre" ) {
            $self->handler( start => sub { print shift }, 'text' );
            $self->handler( end   => \&end,               "tagname,self" );
        }

        # <CODE>-Block
        if ( lc $tag eq "code" ) {
            $self->handler( start => sub { print shift }, 'text' );
            $self->handler( end   => \&end,               "tagname,self" );
        }

        # <A> HTML-Element a, ein Link
        if ( lc $tag eq "a" ) {
            $self->handler( end => \&end, "tagname,self" );

            # URLs in RFC-gültige URI umwandeln
            local $URI::ABS_REMOTE_LEADING_DOTS = 1;
            $attr->{ href } = URI->new( $attr->{ href } )->abs( $current_uri );
        }

        # andere HTML Elemente wieder ausgeben (samt Attributen!)
        print "<$tag";
        # zum HTML-Element Attribute und Werte ausgeben
        while ( my ( $att, $val ) = each %{ $attr } ) {
            print qq/ $att="$val"/;
        }
        print ">";
    } ## end sub start

    # Handler für HTML-Endelemente
    sub end {
        my ( $tag, $self ) = @_;

        # HTML-Endelement ausgeben
        print "</$tag>";
    }

}


Ergibt das dann:
Code: (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
<ul>
<li><a href="https://example.org/tests/" title="Anfang">Test</a>
<li><a class="c1" href="https://example.org/tests/test.html" title="Erster Test">Test 1</a>
<li><a href="https://example.org/tests/Test1/test.html">Test 2</a>
<li><a href="http://example.org/example/Test1/test.html">Test 3</a>
<li><a href="https://example.org/example/Test1/test.html">Test 4</a>
<li><a href="https://example.org/tests/example/Test1/test.html">Test 5</a>
<li><a href="https://example.org/Test1/test.html">Test 6</a>
<li><a href="https://example.org/tests/a/s/d/f/g/h/j//test.html">Test 7</a>
</ul>

<?php
# auch hier nix õndern
# <a href="test.html" title="Erster Test" class="c1">Test 1</a>
?>

<!-- Kommentarblock; auch hier nix õndern!!!!
<ul>
<li><a href="." title="Anfang">Test</a>
<li><a href="test.html" title="Erster Test" class="c1">Test 1</a>
<li><a href="Test1/test.html">Test 2</a>
<li><a href="http://example.org/example/Test1/test.html">Test 3</a>
<li><a href="//example.org/example/Test1/test.html">Test 4</a>
<li><a href="./example/Test1/test.html">Test 5</a>
<li><a href="./example/.././../../Test1/test.html">Test 6</a>
<li><a href="a/s/d/f/g/h/j//test.html">Test 7</a>
</ul>
-->

<pre><code>
<!-- Hier im PRE oder CODE-Kindern erst recht niemals was õndern!!!! -->
<ul>
<li><a href=".">Test</a>
<li><a href="test.html">Test 1</a>
<li><a href="Test1/test.html">Test 2</a>
<li><a href="http://example.org/example/Test1/test.html">Test 3</a>
<li><a href="//example.org/example/Test1/test.html">Test 4</a>
<li><a href="./example/Test1/test.html">Test 5</a>
<li><a href="./example/.././../../Test1/test.html">Test 6</a>
<li><a href="a/s/d/f/g/h/j//test.html">Test 7</a>
</ul>
</code></pre>


Lösung sieht sauber aus, aber ich frage euch trotzdem mal, vielleicht überseh’ ich was beim Parsen des HTML.




Mist, kaum ist da so ein Schnippsel im HTML:
Code: (dl )
1
2
3
4
5
6
7
8
9
<?php
# auch hier nix ändern
# <a href="test.html" title="Erster Test" class="c1">Test 1</a>
echo "<a href="test.html" title="Erster Test" class="c1">Test 1</a>";
?>

<?
echo "<a href="test.html" title="Erster Test" class="c1">Test 1</a>";
?>

dann erzeugt den Schnippsel:
Code: (dl )
1
2
3
4
5
6
7
8
9
<?php
# auch hier nix õndern
# <a href="test.html" title="Erster Test" class="c1">Test 1</a>
echo "<a title="Erster Test" class="c1" href="https://example.org/tests/test.html">Test 1</a>";
?>

<?
echo "<a href="test.html" title="Erster Test" class="c1">Test 1</a>";
?>


Seltsam, warum schlug das denn beim obigen Code nicht an?
Ich hachte Zeile 76 fängt das ab?
Last edited: 2023-02-01 12:20:00 +0100 (CET)
die Drachin, Gwendolyn


Unterschiedliche Perl-Versionen auf Windows (fast wie perlbrew) • Meine Perl-Artikel

View full thread HTML::Parser - Attribute von HTML ändern, welche sich nicht(!) unterhalb <pre> oder <code> befinden