Schrift
[thread]9022[/thread]

hash undef bei erstem Aufruf in while()?!: perplex



<< >> 3 Einträge, 1 Seite
dukeofnukem
 2007-05-21 19:24
#76811 #76811
User since
2007-01-15
47 Artikel
BenutzerIn
[default_avatar]
Alohá!

Folgender Auszug aus einem selbstgebasteltem XML-Differ:

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
43
44
45
46
47
48
sub pro {
my $self = shift;

sub attr {
my $node = shift;
my $map = $node->getAttributes;

my @tmp = %$map;

while ( my ( $key, $value ) = each %$map ) {
next unless ( ref( $value ) eq 'XML::DOM::Attr' );
my $val = $value->getValue;
return "\[\@$key=\'$val\'\]";
}
return undef;
}

sub trace {
my $node = shift;
my $attr = attr($node);

# base case
if ( $node->getParentNode->getNodeType == 9 ) {
$attr ?

return "//" . $node->getNodeName . $attr :

return "//" . $node->getNodeName;
}

# return unique path
$attr ?
return trace( $node->getParentNode ) . "/" . $node->getNodeName . $attr :
return trace( $node->getParentNode ) . "/" . $node->getNodeName;
}

# "main"
my @paths = map { trace($_) } $self->{'xml1'}->findnodes( '//*' );
print join "\n", @paths;
exit;
for my $path ( @paths ) {
print "\nPath: ", $path;
for ( $self->{'xml2'}->findnodes( $path ) ) {
print "\nFound node: ", $_->getNodeName;
print "\thas Value: ", $_->getFirstChild->getNodeValue if $_->getFirstChild;
}
}
}


Hoffe das ist nicht zu unübersichtlich; habe der Vollständigkeit halber die ganze sub reingepackt.

Der Knackpunkt:
Wenn ich in attr die namedNodeMap %$map nicht vor der while-Schleife benutze (my @tmp = %$map;), ist %$map genau bei jedem zweiten Aufruf von attr mit der selben $node leer, bzw. es wird kein Attribut zurückgegeben!
So lange ich jedoch irgendeine operation auf %$map ausführe, wird immer das Attribut zurückgeliefert.

Zur Erklärung:
XML::DOM::Node
getAttributes

A NamedNodeMap containing the attributes (Attr nodes) of this node (if it is an Element) or undef otherwise. [...]
##############
XML::DOM::Attr
getValue

On retrieval, the value of the attribute is returned as a string. Character and general entity references are replaced with their values.
##############
XML::DOM::NamedNodeMap - A hash table interface for XML::DOM
DESCRIPTION ^

Objects implementing the NamedNodeMap interface are used to represent collections of nodes that can be accessed by name. [...]

Faszinierend, aber nervig.

Interessanterweise funktioniert

Code: (dl )
1
2
3
4
5
6
7
8
9
10
    sub attr {
my $node = shift;
my $map = $node->getAttributes;
for my $key ( keys %$map ) {
next unless ( ref( $$map{$key} ) eq 'XML::DOM::Attr' );
my $val = $map->getNamedItem($key)->getValue;
return "\[\@$key=\'$val\'\]";
}
return undef;
}


Zugegebenermaßen nutzt diese Variante die API von XML::DOM sehr viel sauberer (wobei das next unless immer noch nötig ist, sonst knallts mit der objectref), aber es hat mich doch etwas stutzig gemacht...

Hat dieser Aussetzer bei jedem zweiten Aufruf bei der ersten Variante was mit AUTOLOAD oder autovivification zu tun?

Klappt ja jetzt, aber mich würde interessieren woran es liegt, daß genau jeder zweite Aufruf scheitert wenn der hash nicht vorher "benutzt" wurde.

TIA!
drum&bass is a state of mind
renee
 2007-05-21 20:22
#76812 #76812
User since
2003-08-04
14371 Artikel
ModeratorIn
[Homepage] [default_avatar]
Am besten schaust Du Dir mal mit CPAN:Data::Dumper den Dump von $map an!
OTRS-Erweiterungen (http://feature-addons.de/)
Frankfurt Perlmongers (http://frankfurt.pm/)
--

Unterlagen OTRS-Workshop 2012: http://otrs.perl-services.de/workshop.html
Perl-Entwicklung: http://perl-services.de/
dukeofnukem
 2007-05-21 20:53
#76813 #76813
User since
2007-01-15
47 Artikel
BenutzerIn
[default_avatar]
das ist ok, da finden sich dann das namedNodeMap-Object und das XML::DOM::Attr-Object. Immer.

Ist nicht das print Dumper ($map) schon ein evtl. autovivifizierender Zugriff auf den hash / das Object?
drum&bass is a state of mind
<< >> 3 Einträge, 1 Seite



View all threads created 2007-05-21 19:24.