1<?php
2
3/**
4 * Converts HTMLPurifier_ConfigSchema_Interchange to an XML format,
5 * which can be further processed to generate documentation.
6 */
7class HTMLPurifier_ConfigSchema_Builder_Xml extends XMLWriter
8{
9
10    protected $interchange;
11    private $namespace;
12
13    protected function writeHTMLDiv($html) {
14        $this->startElement('div');
15
16        $purifier = HTMLPurifier::getInstance();
17        $html = $purifier->purify($html);
18        $this->writeAttribute('xmlns', 'http://www.w3.org/1999/xhtml');
19        $this->writeRaw($html);
20
21        $this->endElement(); // div
22    }
23
24    protected function export($var) {
25        if ($var === array()) return 'array()';
26        return var_export($var, true);
27    }
28
29    public function build($interchange) {
30        // global access, only use as last resort
31        $this->interchange = $interchange;
32
33        $this->setIndent(true);
34        $this->startDocument('1.0', 'UTF-8');
35        $this->startElement('configdoc');
36        $this->writeElement('title', $interchange->name);
37
38        foreach ($interchange->directives as $directive) {
39            $this->buildDirective($directive);
40        }
41
42        if ($this->namespace) $this->endElement(); // namespace
43
44        $this->endElement(); // configdoc
45        $this->flush();
46    }
47
48    public function buildDirective($directive) {
49
50        // Kludge, although I suppose having a notion of a "root namespace"
51        // certainly makes things look nicer when documentation is built.
52        // Depends on things being sorted.
53        if (!$this->namespace || $this->namespace !== $directive->id->getRootNamespace()) {
54            if ($this->namespace) $this->endElement(); // namespace
55            $this->namespace = $directive->id->getRootNamespace();
56            $this->startElement('namespace');
57            $this->writeAttribute('id', $this->namespace);
58            $this->writeElement('name', $this->namespace);
59        }
60
61        $this->startElement('directive');
62        $this->writeAttribute('id', $directive->id->toString());
63
64        $this->writeElement('name', $directive->id->getDirective());
65
66        $this->startElement('aliases');
67            foreach ($directive->aliases as $alias) $this->writeElement('alias', $alias->toString());
68        $this->endElement(); // aliases
69
70        $this->startElement('constraints');
71            if ($directive->version) $this->writeElement('version', $directive->version);
72            $this->startElement('type');
73                if ($directive->typeAllowsNull) $this->writeAttribute('allow-null', 'yes');
74                $this->text($directive->type);
75            $this->endElement(); // type
76            if ($directive->allowed) {
77                $this->startElement('allowed');
78                    foreach ($directive->allowed as $value => $x) $this->writeElement('value', $value);
79                $this->endElement(); // allowed
80            }
81            $this->writeElement('default', $this->export($directive->default));
82            $this->writeAttribute('xml:space', 'preserve');
83            if ($directive->external) {
84                $this->startElement('external');
85                    foreach ($directive->external as $project) $this->writeElement('project', $project);
86                $this->endElement();
87            }
88        $this->endElement(); // constraints
89
90        if ($directive->deprecatedVersion) {
91            $this->startElement('deprecated');
92                $this->writeElement('version', $directive->deprecatedVersion);
93                $this->writeElement('use', $directive->deprecatedUse->toString());
94            $this->endElement(); // deprecated
95        }
96
97        $this->startElement('description');
98            $this->writeHTMLDiv($directive->description);
99        $this->endElement(); // description
100
101        $this->endElement(); // directive
102    }
103
104}
105
106// vim: et sw=4 sts=4
107