blob: ae3c10f766ebdb07e9f97006c707fe86110fe5b2 (
plain)
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
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
|
<?php
namespace HTML5\Serializer;
/**
* Traverser for walking a DOM tree.
*
* This is a concrete traverser designed to convert a DOM tree into an
* HTML5 document. It is not intended to be a generic DOMTreeWalker
* implementation.
*
* @see http://www.w3.org/TR/2012/CR-html5-20121217/syntax.html#serializing-html-fragments
*/
class Traverser {
/** Namespaces that should be treated as "local" to HTML5. */
static $local_ns = array(
'http://www.w3.org/1999/xhtml' => 'html',
'http://www.w3.org/1998/Math/MathML' => 'mathml',
'http://www.w3.org/2000/svg' => 'svg',
);
protected $dom;
protected $options;
protected $encode = FALSE;
protected $rules;
protected $out;
/**
* Create a traverser.
*
* @param DOMNode|DOMNodeList $dom
* The document or node to traverse.
* @param resource $out
* A stream that allows writing. The traverser will output into this
* stream.
* @param array $options
* An array or options for the traverser as key/value pairs. These include:
* - encode_entities: A bool to specify if full encding should happen for all named
* charachter references. Defaults to FALSE which escapes &'<>".
* - output_rules: The path to the class handling the output rules.
*/
public function __construct($dom, $out, $options = array()) {
$this->dom = $dom;
$this->out = $out;
$this->options = $options;
if (!isset($this->options['output_rules'])) {
throw new \HTML5\Exception('No Rules specified for output generation.');
}
$rulesClass = $this->options['output_rules'];
$this->rules = new $rulesClass($this, $out, $this->options);
}
/**
* Tell the traverser to walk the DOM.
*
* @return resource $out
* Returns the output stream.
*/
public function walk() {
if ($this->dom instanceof \DOMDocument) {
$this->rules->document($this->dom);
}
// If NodeList, loop
elseif ($this->dom instanceof \DOMNodeList) {
// If this is a NodeList of DOMDocuments this will not work.
$this->children($this->dom);
}
// Else assume this is a DOMNode-like datastructure.
else {
$this->node($this->dom);
}
return $this->out;
}
/**
* Process a node in the DOM.
*
* @param mixed $node
* A node implementing \DOMNode.
*/
public function node($node) {
// A listing of types is at http://php.net/manual/en/dom.constants.php
switch ($node->nodeType) {
case XML_ELEMENT_NODE:
$this->rules->element($node);
break;
case XML_TEXT_NODE:
$this->rules->text($node);
break;
case XML_CDATA_SECTION_NODE:
$this->rules->cdata($node);
break;
// FIXME: It appears that the parser doesn't do PI's.
case XML_PI_NODE:
$this->rules->processorInstruction($ele);
break;
case XML_COMMENT_NODE:
$this->rules->comment($node);
break;
// Currently we don't support embedding DTDs.
default:
print '<!-- Skipped -->';
break;
}
}
/**
* Walk through all the nodes on a node list.
*
* @param \DOMNodeList $nl
* A list of child elements to walk through.
*/
public function children($nl) {
foreach ($nl as $node) {
$this->node($node);
}
}
/**
* Is an element local?
*
* @param mixed $ele
* An element that implement \DOMNode.
*
* @return bool
* True if local and false otherwise.
*/
public function isLocalElement($ele) {
$uri = $ele->namespaceURI;
if (empty($uri)) {
return FALSE;
}
return isset(self::$local_ns[$uri]);
}
}
|