-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathREADME
435 lines (291 loc) · 12.1 KB
/
README
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
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
NAME
XML::Chain - chained way of manipulating and inspecting XML documents
SYNOPSIS
use XML::Chain qw(xc);
# basics
my $div = xc('div', class => 'pretty')
->c('h1')->t('hello')
->up
->c('p', class => 'intro')->t('world')
->root
->a( xc('p')->t('of chained XML.') );
say $div->as_string;
# <div class="pretty"><h1>hello</h1><p class="intro">world</p><p>of chained XML.</p></div>
my $sitemap =
xc('urlset', xmlns => 'http://www.sitemaps.org/schemas/sitemap/0.9')
->t("\n")
->c('url')
->a('loc', '-' => 'https://metacpan.org/pod/XML::Chain::Selector')
->a('lastmod', '-' => DateTime->from_epoch(epoch => 1507451828)->strftime('%Y-%m-%d'))
->a('changefreq', '-' => 'monthly')
->a('priority', '-' => '0.6')
->up->t("\n")
->c('url')
->a('loc', '-' => 'https://metacpan.org/pod/XML::Chain::Element')
->a('lastmod', '-' => DateTime->from_epoch(epoch => 1507279028)->strftime('%Y-%m-%d'))
->a('changefreq', '-' => 'monthly')
->a('priority', '-' => '0.5')
->up->t("\n");
say $sitemap->as_string;
# <urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
# <url><loc>https://metacpan.org/pod/XML::Chain::Selector</loc><lastmod>2017-10-08</lastmod><changefreq>monthly</changefreq><priority>0.6</priority></url>
# <url><loc>https://metacpan.org/pod/XML::Chain::Element</loc><lastmod>2017-10-06</lastmod><changefreq>monthly</changefreq><priority>0.5</priority></url>
# </urlset>
DESCRIPTION
This module provides fast and easy way to create and manipulate XML
elements via set of chained method calls.
EXPORTS
xc
Exported factory method creating new XML::Chain::Element object with a
document element as provided in parameters. For example:
my $icon = xc('i', class => 'icon-download icon-white');
# <i class="icon-download icon-white"/>
See also "c, append_and_current" in XML::Chain::Selector, from which
XML::Chain::Element inherits all methods, for the element parameter
description and "CHAINED METHODS" in XML::Chain::Selector for methods
of returned object.
xc($el_name, @attrs) scalar with 1+ arguments
Element with $el_name will be create as document element and @attrs
will be added to it in the same order.
In case of hash reference passed as argument, key + values will be set
as attributes, in alphabetical sorted key name order.
Attribute name "-" is a special case and the value will used for text
content inside the element.
xc($xml_libxml_ref)
In case of XML::LibXML, it will be set as document element.
xc($what_ref)
Any other reference will be passed to "slurp($what)" in IO::Any which
will be then parsed by "load_xml" in XML::LibXML and result set as
document element.
say xc([$tmp_dir, 't01.xml'])->as_string
say xc(\'<body><h1>and</h1><h1>head</h1></body>')
->find('//h1')->count
xc($scalar)
Element with $scalar will be create as document element.
say xc('body');
CHAINED METHODS, METHODS and ELEMENT METHODS
See XML::Chain::Selector and XML::Chain::Element.
CHAINED DOCUMENT METHODS
xc('body')->t('save me')->set_io_any([$tmp_dir, 't01.xml'])->store;
# $tmp_dir/t01.xml file now consists of:
<body>save me</body>
xc([$tmp_dir, 't01.xml'])->empty->c('div')->t('updated')->store;
# $tmp_dir/t01.xml file now consists of:
<body><div>updated</div></body>
set_io_any
Store $what , $options of IO::Any for future use with ->store()
store
Calls IO::Any-spew($io_any, $self->as_string, {atomic => 1}) > to save
XML back it it's original file of the the target set via set_io_any.
TODO
- partial/special tidy (on elements inside xml)
- per ->data() storage
- ->each(sub {...}) / ->map(sub {}) / ->grep(sub {})
- setting and handling namespaces and elements with ns prefixes
- ~ton of selectors and manipulators to be added
CONTRIBUTORS & CREDITS
Initially inspired by Strophe.Builder, then also by jQuery.
The following people have contributed to the XML::Chain by committing
their code, sending patches, reporting bugs, asking questions,
suggesting useful advice, nitpicking, chatting on IRC or commenting on
my blog (in no particular order):
Slaven Rezic
Vienna.pm (for listening to my talk and providing valuable feedback)
Mohammad S Anwar
you?
Also thanks to my current day-job-employer http://geizhals.at/.
BUGS
Please report any bugs or feature requests via
https://github.com/meon/XML-Chain/issues.
AUTHOR
Jozef Kutej
COPYRIGHT & LICENSE
Copyright 2017 Jozef Kutej, all rights reserved.
This program is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.
----------------------------------------------------------------------------
NAME
XML::Chain::Selector - selector for traversing the XML::Chain
SYNOPSIS
my $user = xc('user', xmlns => 'http://testns')->auto_indent({chars=>' 'x4})
->a('name', '-' => 'Johnny Thinker')
->a('username', '-' => 'jt')
->c('bio')
->c('div', xmlns => 'http://www.w3.org/1999/xhtml')
->a('h1', '-' => 'about')
->a('p', '-' => '...')
->up
->a('greeting', '-' => 'Hey')
->up
->a('active', '-' => '1')
->root;
say $user->as_string;
Will print:
<user xmlns="http://testns">
<name>Johnny Thinker</name>
<username>jt</username>
<bio>
<div xmlns="http://www.w3.org/1999/xhtml">
<h1>about</h1>
<p>...</p>
</div>
<greeting>Hey</greeting>
</bio>
<active>1</active>
</user>
DESCRIPTION
CHAINED METHODS
c, append_and_select
Appends new element to current elements and changes context to them.
New element is defined in parameters:
$xc->c('i', class => 'icon-download icon-white')
# <i class="icon-download icon-white"/>
First parameter is name of the element, then followed by optional
element attributes.
t, append_text
Appends text to current elements.
xc('span')->t('some')->t(' ')->t('more text')
# <span>some more text</span>
First parameter is name of the element, then followed by optional
element attributes.
root
Sets document element as current element.
say xc('p')
->t('this ')
->a(xc('b')->t('is'))
->t(' important!')
->root->as_string;
# <p>this <b>is</b> important!</p>
up, parent
Traverse current elements and replace them by their parents.
find
say $xc->find('//p/b[@class="less"]')->text_content;
say $xc->find('//xhtml:div', xhtml => 'http://www.w3.org/1999/xhtml')->count;
Look-up elements by xpath and set them as current elements. Optional
look-up namespace prefixes can be specified. Any global registered
namespace prefixes "reg_global_ns" can be used.
children
Set all current elements child nodes as current elements.
first
Set first current elements as current elements.
empty
Removes all child nodes from current elements.
rename
my $body = xc('bodyz')->rename('body');
# <body/>
Rename node name(s).
attr
my $img = xc('img')->attr('href' => '#', 'title' => 'imaget');
# <img href="#" title="imaget"/>
say $img->attr('title')
# imaget
say $img->attr('title' => undef)
# <img href="#"/>
Get or set elements attributes. With one argument returns attribute
value otherwise sets them. Setting attribute to undef will remove it
from the element.
each
# rename using each
$body->rename('body');
$body
->a(xc('p.1')->t(1))
->a(xc('p.2')->t(2))
->a(xc('div')->t(3))
->a(xc('p.3')->t(4))
->each(sub { $_->rename('p') if $_->name =~ m/^p[.]/ });
is($body, '<body><p>1</p><p>2</p><div>3</div><p>4</p></body>','rename using each()');
Loops through all selected elements and calls callback for each of
them.
remap
xc('body')->a('p', i => 1)->children->remap(
sub {
(map {xc('e', i => $_)} 1 .. 3), $_;
}
)->root;
# <body><e i="1"/><e i="2"/><e i="3"/><p i="1"/></body>
Replaces all selected elements by callback returned elements.
rm, remove_and_parent
my $pdiv = xc('base')
->a(xc('p')->t(1))
->a(xc('p')->t(2))
->a(xc('div')->t(3))
->a(xc('p')->t(4));
my $p = $pdiv->find('//p');
# $pdiv->find('//p[position()=3]')->rm->name eq 'base'
# $p->count == 2 # deleted elements are skipped also in old selectors
# <base><p>1</p><p>2</p><div>3</div></base>
Deletes current elements and returns their parent.
auto_indent
(experimental feature (good/usefull for debug, needs more testing),
works only on element for which as_string is called at this moment)
my $simple = xc('div')
->auto_indent(1)
->a('div', '-' => 'in1')
->a('div', '-' => 'in2')
->t('in2.1')
->a('div', '-' => 'in3')
;
say $simple->as_string;
Will print:
<div>
<div>in1</div>
<div>in2</div>
in2.1
<div>in3</div>
</div>
Turn on/off tidy/auto-indentation of document elements. Default
indentation characters are tabs.
Argument can be either true/false scalar or a hashref with indentation
options. Currently {chars=' 'x4} > will set indentation characters to
be four spaces.
CHAINED DOCUMENT METHODS
See "CHAINED DOCUMENT METHODS" in XML::Chain.
METHODS
as_string, toString
Returns string representation of current XML elements. Call root before
to get a string representing the whole document.
$xc->as_string
$xc->root->as_string
as_xml_libxml
Returns array of current elements as XML::LibXML objects.
text_content
Returns text content of all current XML elements.
count / size
say $xc->find('//b')->count;
Return the number of current elements.
single
my $lxml_el = $xc->find('//b')->first->as_xml_libxml;
Checks is there is exactly one element in current elements and return
it as XML::Chain::Element object.
reg_global_ns
$sitemap->reg_global_ns('i' => 'http://www.google.com/schemas/sitemap-image/1.1');
$sitemap->reg_global_ns('s' => 'http://www.sitemaps.org/schemas/sitemap/0.9');
say $sitemap->find('/s:urlset/s:url/i:image')->count
# 2
AUTHOR
Jozef Kutej
COPYRIGHT & LICENSE
Copyright 2017 Jozef Kutej, all rights reserved.
This program is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.
----------------------------------------------------------------------------
NAME
XML::Chain::Element - helper class for XML::Chain representing single
element
SYNOPSIS
xc('body')->c(h1)->t('title')->root
DESCRIPTION
Returned by "single" in XML::Chain::Selector call.
METHODS
name
return element name
as_xml_libxml
Returns XML::LibXML::Element object.
XML::Chain::Selector methods
All of the XML::Chain::Selector methods works too.
AUTHOR
Jozef Kutej
COPYRIGHT & LICENSE
Copyright 2017 Jozef Kutej, all rights reserved.
This program is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.