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