]> git.sesse.net Git - xml-template/blob - xml-template.php
5c3d2b492e85f045d0e4eab6125c3895104515db
[xml-template] / xml-template.php
1 <?php
2
3 function XML_Template_process_file($filename, $obj, $clean = 1)
4 {
5         $doc = domxml_open_file($filename);
6         XML_Template_process($doc, $obj, $clean);
7         return $doc;
8 }
9
10 function XML_Template_process($node, $obj, $clean = 1)
11 {
12         if (!is_array($obj)) {                                # overwrite
13                 foreach ($node->child_nodes() as $child) {
14                         $node->remove_child($child);
15                 }
16                 $doc = $node->owner_document();
17                 $node->add_child($doc->create_text_node($obj));
18         # handle overwrite with a DOM object here
19         } else if (is_associative_array($obj)) {              # substitute
20                 foreach ($node->child_nodes() as $child) {
21                         $processed = false;
22
23                         if ($child->node_type() == XML_ELEMENT_NODE) {
24                                 $tag = $child->node_name();
25                                 $attrs = $child->attributes();
26                                 if ($attrs != null) {
27                                         foreach ($child->attributes() as $attr) {
28                                                 if ($attr->namespace_uri() == 'http://template.sesse.net/' && $attr->name() == 'id') {
29                                                         $id = $attr->value();
30                                                         if ($clean) {
31                                                                 $child->remove_attribute($attr->name());
32                                                         }
33                                                 }
34                                         }
35                                 }
36                         
37                                 # check all substitutions to see if we found anything
38                                 # appropriate
39                                 foreach (array_keys($obj) as $key) {
40                                         # FIXME: we would want something like \Q and \E here...
41                                         if (preg_match('/^' . $tag . '\.(.*)$/', $key, $matches) ||
42                                             ($id != null && preg_match('/^#' . $id . '\.(.*)$/', $key, $matches))) {
43                                                 $child->set_attribute($matches[1], $obj[$key]);
44                                         }
45
46                                         if ($processed) {
47                                                 continue;
48                                         }
49                                         if ($key == $tag || ($id != null && $key == ('#'.$id))) {
50                                                 XML_Template_process($child, $obj[$key], $clean);
51                                                 $processed = true;
52                                         }
53                                 }
54                         }
55
56                         if (!$processed) {
57                                 XML_Template_process($child, $obj, $clean);
58                         }
59                 }
60         } else {                                                # repeat
61                 $doc = $node->owner_document();
62                 $frag = $doc->create_element("temporary-fragment");    # ugh
63
64                 foreach ($node->child_nodes() as $child) {
65                         $frag->append_child($child);
66                         $node->remove_child($child);
67                 }
68
69                 foreach ($obj as $instance) {
70                         $newnode = $frag->clone_node(true);
71                         $node->append_child($newnode);
72                         XML_Template_process($newnode, $instance, $clean);
73                         if ($clean) {
74                                 XML_Template_clean($newnode);
75                         }
76                 }
77
78                 # remove all the <fragment> tags
79
80                 foreach ($node->child_nodes() as $child) {
81                         if ($child->name() != 'temporary-fragment') {
82                                 continue;
83                         }
84                         foreach ($child->child_nodes() as $child2) {
85                                 $node->append_child($child2);
86                         }
87                         $node->remove_child($child);
88                 }       
89
90                 return;
91         }
92
93         if ($clean) {
94                 XML_Template_clean($node);
95         }
96 }
97
98 function XML_Template_clean($node)
99 {
100         if ($node->node_type() == XML_ELEMENT_NODE) {
101                 if ($node->namespace_uri() != 'http://template.sesse.net/') {
102                         return;
103                 }
104
105                 # as this is a dummy node, we want to remove it and move everything further up
106                 # after we've done any required replacements
107                 $doc = $node->owner_document();
108                 $parent = $node->parent_node();
109                 foreach ($node->child_nodes() as $child) {
110                         $node->remove_child($child);
111                         $node->insert_before($child, $node);
112                 }
113                 $parent->remove_child($node);
114         }
115 }
116
117 function is_associative_array($arr)
118 {
119         if (!is_array($arr)) {
120                 return false;
121         }
122         $diff = array_diff(range(0, count($arr) - 1), array_keys($arr));
123         return (count($diff) > 0);
124 }
125 ?>