/[suikacvs]/webroot/swe/lib/SWE/DB/DOM.pm
Suika

Contents of /webroot/swe/lib/SWE/DB/DOM.pm

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.1 - (hide annotations) (download)
Sat Nov 8 09:29:09 2008 UTC (16 years, 5 months ago) by wakaba
Branch: MAIN
CVS Tags: HEAD
++ swe/lib/SWE/DB/ChangeLog	8 Nov 2008 09:29:03 -0000
	* DOM.pm: New module (some code moved from
	/webroot/gate/2008/sw.cgi).

	* SuikaWiki3.pm: Make a copy of key argument such that the
	original value will not be modified in the method code.

2008-11-08  Wakaba  <wakaba@suika.fam.cx>

1 wakaba 1.1 package SWE::DB::DOM;
2     use strict;
3    
4     require Message::DOM::DOMImplementation;
5    
6     sub new ($) {
7     my $self = bless {
8     root_directory_name => './',
9     root_key => ['HomePage'],
10     leaf_suffix => '.txt',
11     }, shift;
12     return $self;
13     } # new
14    
15     my $get_file_name = sub {
16     my ($self, $key) = @_;
17     $key = $self->{root_key} if @$key == 0;
18    
19     my $file_name = $self->{root_directory_name} .
20     join '-', map { s/(.)/sprintf '%02X', ord $1/ges; $_ } @$key;
21     $file_name .= $self->{leaf_suffix};
22    
23     return $file_name;
24     }; # $get_file_name
25    
26     sub get_data ($$) {
27     my $self = $_[0];
28     my $key = [@{$_[1]}];
29    
30     my $file_name = $get_file_name->($self, $key);
31    
32     unless (-f $file_name) {
33     return undef;
34     }
35    
36     open my $file, '<:encoding(utf8)', $file_name or die "$0: $file_name: $!";
37     return _load_dom ($file);
38     } # get_data
39    
40     sub set_data ($$$) {
41     my $self = $_[0];
42     my $key = [@{$_[1]}];
43     my $dom = $_[2];
44    
45     my $file_name = $get_file_name->($self, $key);
46    
47     open my $file, '>:encoding(utf8)', $file_name or die "$0: $file_name: $!";
48     _store_dom ($file, $dom);
49     } # set_data
50    
51     sub _load_dom ($) {
52     my $handle = shift;
53    
54     my $dom = Message::DOM::DOMImplementation->new;
55     my @node = ($dom->create_document);
56    
57     $node[0]->strict_error_checking (0);
58     $node[0]->dom_config->set_parameter
59     ('http://suika.fam.cx/www/2006/dom-config/strict-document-children' => 0);
60    
61     my $unescape = sub {
62     my $s = shift;
63     $s =~ s/\\([0-9A-Fa-f]{2})/pack 'C', hex $1/ge;
64     return $s;
65     }; # $unescape
66    
67     while (<$handle>) {
68     tr/\x0D\x0A//d;
69     if (s/^n(\d+);//) {
70     $node[$1] = $unescape->($_);
71     } elsif (s/^t(\d+);//) {
72     my $parent_id = $1;
73     $node[$parent_id]->append_child
74     ($node[0]->create_text_node ($unescape->($_)));
75     } elsif (s/^e(\d+);(\d+);(\d+);//) {
76     my ($this_id, $parent_id, $ns_id) = ($1, $2, $3);
77     $node[$this_id] = $node[0]->create_element_ns
78     ($node[$ns_id], [undef, $unescape->($_)]);
79     $node[$parent_id]->append_child ($node[$this_id]);
80     } elsif (s/^a(\d+);(\d+);([^;]+);//) {
81     my ($parent_id, $ns_id, $ln) = ($1, $2, $3);
82     $node[$parent_id]->set_attribute_ns
83     ($node[$ns_id], [undef, $unescape->($ln)], $unescape->($_));
84     }
85     }
86    
87     return $node[0];
88     } # _load_dom
89    
90     sub _store_dom ($$) {
91     my $handle = shift;
92     my @item = ([0, shift]);
93    
94     my $escape = sub {
95     my $v = $_[0];
96     $v =~ s/([;\\\x0D\x0A])/sprintf '\\%02X', ord $1/ge;
97     return $v;
98     }; # $escape
99    
100     my $ns;
101     my $next_id = 1;
102     while (@item) {
103     my ($parent_id, $node) = @{shift @item};
104     if ($node->node_type == $node->ELEMENT_NODE) {
105     my $nsuri = $node->namespace_uri // '';
106     my $nsid = $ns->{$nsuri};
107     unless (defined $nsid) {
108     $nsid = $next_id++;
109     $ns->{$nsuri} = $nsid;
110     print $handle "n", $nsid, ';', $escape->($nsuri), "\n";
111     }
112     my $el_id = $next_id++;
113     print $handle "e", $el_id, ';', $parent_id, ';', $nsid, ';',
114     $escape->($node->manakai_local_name), "\n";
115     for my $attr (@{$node->attributes}) {
116     my $nsuri = $attr->namespace_uri // '';
117     my $nsid = $ns->{$nsuri};
118     unless (defined $nsid) {
119     $nsid = $next_id++;
120     $ns->{$nsuri} = $nsid;
121     print $handle "n", $nsid, ';', $escape->($nsuri), "\n";
122     }
123     print $handle "a", $el_id, ';', $nsid, ';',
124     $escape->($attr->manakai_local_name), ';',
125     $escape->($attr->value), "\n";
126     }
127     unshift @item, map {[$el_id, $_]} @{$node->child_nodes};
128     } elsif ($node->node_type == $node->TEXT_NODE or
129     $node->node_type == $node->CDATA_SECTION_NODE) {
130     print $handle "t", $parent_id, ';', $escape->($node->data), "\n";
131     } elsif ($node->node_type == $node->DOCUMENT_NODE or
132     $node->node_type == $node->DOCUMENT_FRAGMENT_NODE) {
133     unshift @item, map {[0, $_]} @{$node->child_nodes};
134     }
135     }
136     } # _store_dom
137    
138     1;

admin@suikawiki.org
ViewVC Help
Powered by ViewVC 1.1.24