-
Notifications
You must be signed in to change notification settings - Fork 46
Expand file tree
/
Copy path00_Intro.php
More file actions
328 lines (243 loc) · 11.2 KB
/
Copy path00_Intro.php
File metadata and controls
328 lines (243 loc) · 11.2 KB
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
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
<?php
$DS = DIRECTORY_SEPARATOR;
$back = '..' . $DS;
$source = __DIR__ . $DS . $back . $back . 'source';
\set_include_path($source . PATH_SEPARATOR . \get_include_path());
////////////////////////////////////////////////////////////////////////////////
require_once 'FluidXml.php';
use \FluidXml\FluidXml;
use \FluidXml\FluidNamespace;
use function \FluidXml\fluidxml;
use function \FluidXml\fluidns;
use function \FluidXml\fluidify;
/*****************************
* Creating An XML Document. *
******************************/
$book = new FluidXml('book');
// or
$book = new FluidXml(null, ['root' => 'book']);
// $book is an XML document with 'book' as root node.
// The default options are:
// [ 'root' => 'doc', // The root node of the document.
// 'version' => '1.0', // The version for the XML header.
// 'encoding' => 'UTF-8', // The encoding for the XML header.
// 'stylesheet' => null ]; // An url pointing to an XSL file.
$booksheet = new FluidXml('book', ['stylesheet' => 'http://domain.com/style.xsl']);
// With PHP 7 this is valid too:
// $booksheet = FluidXml::new('book', ['stylesheet' => 'http://domain.com/style.xsl']);
$book->setAttribute('type', 'science') // It sets an attribute of the root node ('book').
->addChild([ 'title' => 'The Theory Of Everything',
'author' => 'S. Hawking' ]); // It creates two nodes, each one with some text inside.
echo $book->xml(); // Exports the xml document as a string.
echo "————————————————————————————————————————————————————————————————————————————————\n";
/**********************
* Context Switching. *
***********************/
/*
* Passing a 'true' boolean value to any method that performs an insertion of a node,
* returns the newly created node instead of the parent.
* This operation is called Context Switch.
* Methods that support this context switch are:
* - addChild($child, ...$optionals);
* - prependSibling($sibling, ...$optionals);
* - appendSibling($sibling, ...$optionals);
* and their alias methods (of course).
*/
$book->addChild('chapters', true) // true forces the return of the 'chapters' node.
->addChild('chapter', 'Ideas About The Universe', ['id' => 123, 'first' => ''])
->addChild('chapter', 'The Expanding Universe', ['id' => 321])
->addChild('chapter', 'Black Holes', ['id' => 432])
->addChild('chapter', 'Black Holes Ain\'t So Black', ['id' =>234]);
/********************
* Appending Nodes. *
*********************/
/*
* Inserting a node can be performed in different ways,
* each one with its pros and cons.
*/
/*
* In this examples, it is used the concise syntax, but the same concepts
* are applicable to the standard syntax.
*/
$food = fluidxml('food');
$food->add('fruit') // A 'fruit' node with an empty content.
->add('fruit', 'orange'); // A 'fruit' node with 'orange' as content.
// A node can have even a bunch of attributes.
$food->add('fruit', 'apple', [ 'price' => 'expensive',
'color' => 'red' ]);
// Batch insertion of nodes.
$food->add([ 'cake' => 'Tiramisu',
'pizza' => 'Margherita' ]);
// PHP arrays can't contain identical keys.
// But it's still possible to create, in a batch operation, nodes with the same tag.
$food->add([ [ 'pasta' => 'Carbonara' ],
[ 'pasta' => 'Matriciana' ] ]);
// A bunch of egg's all with the same price.
$food->add([ ['egg'], ['egg'], ['egg'] ], ['price' => '0.25']);
// Complex array structures are supported too.
$food->add([ 'menu' => [
'pasta' => [
'spaghetti' => [
'@id' => '123',
'@country' => 'Italy',
'@' => 'Spaghetti are an Italian dish...',
'variants' => [
'tomato' => [ '@type' => 'vegan' ],
'egg' => [ '@type' => 'vegetarian' ] ]]]]]);
echo $food->xml();
echo "————————————————————————————————————————————————————————————————————————————————\n";
/*************************
* Importing XML strings.*
**************************/
/*
* Raw XML/XHTML strings che be injected at any point of the document too.
*/
$book->add('cover', true)
->add(<<<XML
<h1>The Theory Of Everything</h1>
<img src="http://goo.gl/kO3Iov"/>
XML
);
/*
* The document can be filled with a raw XML string.
*/
$html = fluidxml(null);
$html->add(<<<XML
<html>
<head>
<meta/>
</head>
<body>
<p/>
</body>
</html>
XML
);
/*
* Sometimes XML/XHTML comes from legacy templating systems or external sources.
*/
$string = $html->xml();
// XML string import.
$fluid = fluidxml($string);
echo $fluid->xml();
echo "————————————————————————————————————————————————————————————————————————————————\n";
$dom = new DOMDocument();
$dom->loadXML($fluid->xml());
$dom->formatOutput = true;
$dom->preserveWhiteSpace = false;
// DOMDocument import.
$fluid = fluidxml($dom);
echo $fluid->xml();
echo "————————————————————————————————————————————————————————————————————————————————\n";
$simplexml = new SimpleXMLElement($fluid->xml());
// SimpleXMLElement import.
$fluid = fluidxml($simplexml);
echo $fluid->xml();
echo "————————————————————————————————————————————————————————————————————————————————\n";
// XML file import.
// $fluid = fluidify('path/to/file.xml');
$other = fluidxml($fluid->xml());
$fluid = fluidxml();
$fluid->add($other) // Imports a FluidXml instance.
->add([ 'query' => $fluid->query('//meta'), // Imports a FluidXml query.
'dom' => $dom, // Imports a DOMDocument.
'domnodes' => $dom->childNodes, // Imports a DOMNodeList.
'simplexml' => $simplexml ]); // Imports a SimpleXMLElement.
/******************
* XPath Queries. *
*******************/
/*
* XPath queries can be absolute or relative to the context over they are executed.
*/
$eggs = $food->query('//egg');
$fruits = $food->query('//fruit[@price="expensive"]');
echo "We have {$eggs->length()} eggs and {$fruits->length()} expensive fruit.\n";
echo "————————————————————————————————————————————————————————————————————————————————\n";
$book->query('//chapter')
->attr('lang', 'en')
->query('..')
->attr('lang', 'en')
->query('../title')
->attr('lang', 'en');
/*
* The previous code presents a repetition: all 'setAttribute' calls are identical.
* It can be refactored taking advantage of an advanced feature of 'query'.
*/
$book->query('//chapter', '//chapters', '/book/title')
->attr('lang', 'en');
/*******************************
* Accessing The Node Content. *
********************************/
/*
* The result of a query can be accessed even as array.
* Accessing the result of a query as array performs the unwrapping of the node
* and returns a raw instance of DOMNode.
* You loose the FluidXML interface but gain direct access to the DOMNode apis.
*/
$chapters = $book->query('//chapter');
$l = $chapters->length();
// DOMNode access.
$chapters[0]->setAttribute('first', '');
$chapters[$l - 1]->setAttribute('last', '');
/*
* The previous ->setAttribute is the DOMNode::setAttribute.
* not the FluidXml::setAttribute().
* Many other methods/properties are available like:
* - hasAttribute()
* - getAttribute()
* - nodeValue
* See http://php.net/manual/en/class.domnode.php for the reference documentation.
*/
echo $book->xml();
echo "————————————————————————————————————————————————————————————————————————————————\n";
/*
* Because the result of a query behaves like an array, it can be iterated too.
*/
foreach ($chapters as $i => $chapter) {
// $chapter is an instance of DOMNode.
$title = $chapter->nodeValue;
$id = $chapter->getAttribute('id');
$has_first_attr = $chapter->hasAttribute('first');
if ($has_first_attr) {
echo "The first chapter has title '{$title}' with id '{$id}'.\n";
} else {
$ii = $i + 1;
echo "Chapter {$ii} has title '{$title}' with id '{$id}'.\n";
}
}
/*
* To retrieve all DOMNode in one operation there is the ->asArray() method.
*/
$chapters_nodes = $chapters->array(); // Returns an array of DOMNode.
echo "————————————————————————————————————————————————————————————————————————————————\n";
/***************
* Namespaces. *
***************/
/*
* To use a namespace you have to register its identifier together with its uri.
*/
$xhtml = fluidns('xhtml', 'http://www.w3.org/1999/xhtml');
$book->namespace($xhtml)
->namespace('svg', 'http://www.w3.org/2000/svg')
->namespace('xsl', 'http://www.w3.org/TR/xsl', FluidNamespace::MODE_IMPLICIT)
->add('xhtml:h1')
->add([ 'xsl:template' => [ 'xsl:variable' ] ])
->query('//xhtml:h1')
->add('svg:shape');
echo $book->xml();
echo "————————————————————————————————————————————————————————————————————————————————\n";
/*******************
* Removing Nodes. *
*******************/
$food->remove('//egg'); // Removes all the eggs.
// Which is the same of
// $food->query('//egg')->remove(); // Removes all the eggs using a query.
// $food->query('/doc')->remove('egg'); // Removes all the eggs using a relative XPath.
/* ->remove(...$xpath)
* accepts the same arguments of
* ->query(...$xpath)
* Remember that, like `->query()`, even `->remove()` accepts multiple XPath strings.
*/
$food->remove('//fruit', '//cake', '//pasta', '//pizza');
echo $food->xml();
echo "————————————————————————————————————————————————————————————————————————————————\n";