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
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
|
package Build::SimpleXML;
use strict;
# very simple xml parser, just good enough to parse kiwi and _service files...
# can't use standard XML parsers, unfortunatelly, as the build script
# must not rely on external libraries
#
sub parse {
my ($xml) = @_;
my @nodestack;
my $node = {};
my $c = '';
$xml =~ s/^\s*\<\?.*?\?\>//s;
while ($xml =~ /^(.*?)\</s) {
if ($1 ne '') {
$c .= $1;
$xml = substr($xml, length($1));
}
if (substr($xml, 0, 4) eq '<!--') {
$xml =~ s/.*?-->//s;
next;
}
die("bad xml\n") unless $xml =~ /(.*?\>)/s;
my $tag = $1;
$xml = substr($xml, length($tag));
my $mode = 0;
if ($tag =~ s/^\<\///s) {
chop $tag;
$mode = 1; # end
} elsif ($tag =~ s/\/\>$//s) {
$mode = 2; # start & end
$tag = substr($tag, 1);
} else {
$tag = substr($tag, 1);
chop $tag;
}
my @tag = split(/(=(?:\"[^\"]*\"|\'[^\']*\'|[^\"\s]*))?\s+/, "$tag ");
$tag = shift @tag;
shift @tag;
push @tag, undef if @tag & 1;
my %atts = @tag;
for (values %atts) {
next unless defined $_;
s/^=\"([^\"]*)\"$/=$1/s or s/^=\'([^\']*)\'$/=$1/s;
s/^=//s;
s/</</g;
s/>/>/g;
s/&/&/g;
s/'/\'/g;
s/"/\"/g;
}
if ($mode == 0 || $mode == 2) {
my $n = {};
push @{$node->{$tag}}, $n;
for (sort keys %atts) {
$n->{$_} = $atts{$_};
}
if ($mode == 0) {
push @nodestack, [ $tag, $node, $c ];
$c = '';
$node = $n;
}
} else {
die("element '$tag' closes without open\n") unless @nodestack;
die("element '$tag' closes, but I expected '$nodestack[-1]->[0]'\n") unless $nodestack[-1]->[0] eq $tag;
$c =~ s/^\s*//s;
$c =~ s/\s*$//s;
$node->{'_content'} = $c if $c ne '';
$node = $nodestack[-1]->[1];
$c = $nodestack[-1]->[2];
pop @nodestack;
}
}
$c .= $xml;
$c =~ s/^\s*//s;
$c =~ s/\s*$//s;
$node->{'_content'} = $c if $c ne '';
return $node;
}
1;
|