4 use XML::NamespaceSupport;
9 my ($filename, $obj, $clean) = @_;
11 my $parser = XML::DOM::Parser->new;
12 my $doc = $parser->parsefile($filename);
14 process($doc, $obj, $clean);
20 my ($node, $obj, $clean, $nsup) = @_;
21 $clean = 1 unless (defined($clean));
23 if (!defined($nsup)) {
24 $nsup = XML::NamespaceSupport->new;
27 if (!ref($obj)) { # overwrite
28 for my $child ($node->getChildNodes) {
29 $node->removeChild($child);
32 } elsif (Scalar::Util::blessed($obj) && $obj->isa('XML::DOM::Node')) { # overwrite
33 for my $child ($node->getChildNodes) {
34 $node->removeChild($child);
37 if ($obj->isa('XML::DOM::Document')) {
38 $obj = $obj->getDocumentElement;
41 my $newobj = $obj->cloneNode(1);
42 if ($node->isa('XML::DOM::Document')) {
43 $newobj->setOwnerDocument($node);
45 $newobj->setOwnerDocument($node->getOwnerDocument);
47 $node->appendChild($newobj);
48 } elsif (ref($obj) eq 'HASH') { # substitute
49 for my $child ($node->getChildNodes) {
53 if ($child->getNodeType == XML::DOM::ELEMENT_NODE) {
54 # see if this node contains any namespace declarations that are relevant
56 my $attrs = $child->getAttributes;
57 if (defined($attrs)) {
58 for my $attr ($attrs->getValues) {
59 my $name = $attr->getName;
60 if ($name =~ /^xmlns:(.*)$/) {
61 $nsup->declare_prefix($1, $attr->getValue);
62 $child->removeAttribute($name) if ($clean);
66 print $child->getTagName, "\n";
68 my (undef, undef, $tag) = $nsup->process_element_name($child->getTagName);
71 my $attrs = $child->getAttributes;
72 if (defined($attrs)) {
73 for my $attr ($attrs->getValues) {
74 next if ($attr->getName =~ /^xmlns(:|$)/);
76 my ($nsuri, undef, $tag) = $nsup->process_attribute_name($attr->getName);
77 if ($nsuri eq 'http://template.sesse.net/' && $tag eq 'id') {
78 $id = $attr->getValue;
79 $child->removeAttribute($attr->getName) if ($clean);
84 # check all substitutions to see if we found anything
86 for my $key (keys %$obj) {
87 if (($key =~ /^\Q$tag\E\/(.*)$/) ||
88 (defined($id) && $key =~ /^#\Q$id\E\/(.*)$/)) {
89 $child->setAttribute($1, $obj->{$key});
93 if ($key eq $tag || (defined($id) && $key eq ('#'.$id))) {
94 process($child, $obj->{$key}, $clean, $nsup);
100 process($child, $obj, $clean, $nsup) unless ($processed);
103 } elsif (ref($obj) eq 'ARRAY') { # repeat
104 my $doc = $node->getOwnerDocument;
105 my $frag = $doc->createDocumentFragment;
107 for my $child ($node->getChildNodes) {
108 $frag->appendChild($child);
110 for my $child ($node->getChildNodes) {
111 $node->removeChild($child);
114 for my $instance (@$obj) {
116 my $newnode = $frag->cloneNode(1);
117 process($newnode, $instance, $clean, $nsup);
118 $node->appendChild($newnode);
119 clean($newnode, $nsup) if ($clean);
126 clean($node, $nsup) if $clean;
130 my ($node, $nsup) = @_;
132 if ($node->getNodeType == XML::DOM::ELEMENT_NODE) {
133 my ($nsuri) = $nsup->process_element_name($node->getTagName);
134 return unless ($nsuri eq 'http://template.sesse.net/');
136 # as this is a dummy node, we want to remove it and move everything further up
137 # after we've done any required replacements
138 my $doc = $node->getOwnerDocument;
139 my $frag = $doc->createDocumentFragment;
141 for my $child ($node->getChildNodes) {
142 $frag->appendChild($child);
144 for my $child ($node->getChildNodes) {
145 $node->removeChild($child);
148 my $parent = $node->getParentNode;
150 $parent->replaceChild($frag, $node);
155 my ($tag, $array, @elems) = @_;
158 my $num = scalar @elems;
160 for my $ref (@$array) {
161 $ref->{$tag} = $elems[$i++ % $num];