/[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 - (show 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 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