ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/XML-DB/DB.pm
Revision: 1.5
Committed: Thu Apr 25 00:28:40 2002 UTC (22 years ago) by root
Branch: MAIN
CVS Tags: HEAD
Changes since 1.4: +1 -1 lines
Log Message:
*** empty log message ***

File Contents

# Content
1 =head1 NAME
2
3 XML::DB - emulate a native xml database using DBI
4
5 =head1 SYNOPSIS
6
7 =head1 DESCRIPTION
8
9 Ehrm... ;)
10
11 =head1 FUNCTIONS
12
13 =head1 SEE ALSO
14
15 =head1 AUTHOR
16
17 This perl extension was written by Marc Lehmann <pcg@goof.com>
18
19 =head1 BUGS
20
21 =cut
22
23 package XML::DB;
24
25 use XML::Parser;
26 use PApp::SQL;
27
28 #require Exporter;
29 BEGIN {
30 $VERSION = 0.01;
31
32 use base DynaLoader;
33
34 bootstrap XML::DB $VERSION;
35 }
36
37 sub new {
38 my $class = shift;
39 bless { @_ }, $class;
40 }
41
42 sub seq {
43 sql_insertid sql_exec "update $_[0]_seq set n = last_insert_id(n + 1)";
44 }
45
46 sub name_id {
47 # not threadsafe
48 sql_ufetch $_[0]{dbh}, "select i from name where n = ? and v = ?", "$_[1]", $_[2]
49 or sql_insertid sql_exec $_[0]{dbh}, "insert into name values (NULL, ?, ?)", "$_[1]", $_[2];
50
51 }
52
53 sub new_xml_insert_parser {
54 my $self = shift;
55 my $dbh = $self->{dbh};
56
57 my $did = 55;
58 my $max = 1 + sql_fetch $dbh, "select max(l) from node";
59
60 my $n = $max;
61
62 my @l;
63 my @attr;
64
65 new XML::Parser
66 Namespaces => 1,
67 NoExpand => 1,
68 Handlers => {
69 Comment => sub {
70 ++$n;
71 sql_exec $dbh, "insert into node values (?, ?, 'comment', NULL)",
72 $n, $n+1;
73 sql_exec $dbh, "insert into value values (?, ?)",
74 $n, $_[1];
75 ++$n;
76 },
77 Char => sub {
78 ++$n;
79 sql_exec $dbh, "insert into node values (?, ?, 'pcdata', NULL)",
80 $n, $n+1;
81 sql_exec $dbh, "insert into value values (?, ?)",
82 $n, $_[1];
83 ++$n;
84 },
85 Start => sub {
86 my ($parser, $element, @attrs) = @_;
87 push @l, ++$n;
88 push @attr, \@attrs;
89 },
90 End => sub {
91 my ($parser, $element) = @_;
92 my $attr = pop @attr;
93 my $l = pop @l;
94 sql_exec $dbh, "insert into node values (?, ?, 'element', ?)",
95 $l, ++$n, $self->name_id($parser->namespace($element), $element);
96
97 for (my $i = 0; $i < @$attr; $i += 2) {
98 sql_exec $dbh, "insert into attr values (?, ?, ?)",
99 $l, $self->name_id($parser->namespace($attr->[$i]), $attr->[$i]),
100 $attr->[$i+1];
101 }
102 },
103 Final => sub {
104 sql_exec $dbh, "insert into node values (?, ?, 'root', NULL)",
105 $max*1, ++$n;
106 },
107 },
108 @_,
109 ;
110 }
111
112 sub get_fragment {
113 my ($self, $ol) = @_;
114
115 my $or = sql_fetch $self->{dbh}, "select r from node where l = ?", $ol;
116 my $st = sql_exec $self->{dbh}, \my($l, $r, $t, $ns, $name, $value),
117 "select node.l, node.r, node.t, name.n, name.v, value.v
118 from node left join name on (node.n = name.i)
119 left join value on (node.l = value.l)
120 where node.l > ? and node.r < ? order by node.l",
121 $ol, $or;
122
123 my $ot;
124 my @stack;
125 my $doc = "";
126 my (%nsp, $nsps, $nso);
127 my $nsp = "a";
128
129 my $expand_name = sub {
130 $_[0] ? ($nsp{$_[0]} ||= do {
131 $nsps .= " xmlns:$nsp='$_[0]'";
132 $nsp++;
133 }) . ":$_[1]"
134 : $_[1];
135 };
136
137 while ($st->fetch) {
138 if ($l > $or) {
139 ($ol, $or, $oc) = @{pop @stack};
140
141 $doc .= "</$oc>";
142 }
143
144 if ($t eq "element") {
145 push @stack, [$ol, $or, $name];
146 ($ol, $or) = ($l, $r);
147
148 $doc .= "<" . $expand_name->($ns, $name);
149 $nso ||= length $doc;
150
151 my $st = sql_exec $self->{dbh}, \my($ns, $name, $value),
152 "select name.n, name.v, attr.v
153 from attr inner join name on (attr.k = name.i)
154 where attr.l = ?",
155 $l;
156 while ($st->fetch) {
157 $doc .= " " . $expand_name->($ns, $name) . "='" . $value ."'";
158 }
159
160 $doc .= ">";
161 } elsif ($t eq "pcdata" or $t eq "comment") {
162 $doc .= $value;
163 } elsif ($t eq "entity") {
164 } elsif ($t eq "pi") {
165 } elsif ($t eq "doctype") {
166 } else {
167 die "FATAL: database corrupt, unexpected nodetype '$t'";
168 }
169 }
170
171 substr $doc, $nso, 0, $nsps;
172 $doc;
173 }
174
175 1;
176
177
178
179
180