2008-12-17 32 views
1

我想解碼複雜數據結構中的所有HTML實體。基本上我正在尋找一個「超級地圖()」功能。這是我到目前爲止:如何在Perl中的複雜數據結構的每個元素上執行給定的函數?

sub _html_decode { 
    my $self = shift; 
    my $ref = shift; 

    if (ref($ref) eq "HASH") { 
     $self->_html_decode_hash($ref) 
    } 
    if (ref($ref) eq "ARRAY") { 
     $self->_html_decode_array($ref); 
    } 

} 

sub _html_decode_array { 
    my $self = shift; 
    my $ref = shift; 

    unless (@$ref) {return;} 

    foreach (0 .. (scalar(@$ref) - 1)) { 
     if (ref($ref->[$_]) eq "HASH") { 
      $self->_html_decode_hash($ref->[$_]); 
     } 
     if (ref($ref->[$_]) eq "ARRAY") { 
      $self->_html_decode_array($ref->[$_]); 
     } 
     else { 
      $ref->[$_] = decode_entities($ref->[$_]); 
     } 
    } 
} 

sub _html_decode_hash { 
    my $self = shift; 
    my $ref = shift; 

    unless (%$ref) {return;} 

    while (my ($k, $v) = each %$ref) { 
     if (ref($v) eq "HASH") { 
      $self->_html_decode_hash($v); 
     } 
     if (ref($v) eq "ARRAY") { 
      $self->_html_decode_array($v) 
     } 
     else { 
      $ref->{$k} = decode_entities($v); 
     } 
    } 
} 

回答

2

Data::Rmap似乎也這樣做。有沒有人有這個模塊的任何經驗?

+0

沒有經驗,但它聽起來像是問題的最佳解決方案。 – 2008-12-18 01:26:07

3

我認爲這應該做,但我沒有測試過它。

sub _html_decode { 
    my ($self, $ref) = @_; 

    if (ref($ref) eq "HASH") { 
     for my $value (values %{$ref}) { 
      $self->_html_decode($value); 
     } 
    } 
    elsif (ref($ref) eq "ARRAY") { 
     for my $value (@{$ref}) { 
      $self->_html_decode($value); 
     } 
    } 
    else { 
     $_[1] = decode_entities($_[1]); 
    } 
} 

雖然我承認最後一部分並不漂亮。

3

要對任意複雜數據結構的每個元素執行子例程,請查看Visitor設計模式。基本上,你的數據結構是一個知道哪些元素仍然需要處理的對象,它將你的子程序應用於它們。這裏還有一些Iterator模式,因爲你知道如何在我的Netscape::Bookmarks模塊中有一個例子。該數據結構與幾種不同類型的對象深深嵌套。通過使用訪問者模式,大部分複雜性都消失了。

除此之外,你可能想看看我的Object::Iterate模塊。它有一個imap函數,可用於對象而不是列表。我從Python盜取了__next__的想法並將其應用於Perl。

相關問題