tck-lambdas 0.3.4 → 0.3.5

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,586 @@
1
+ //[4] NameStartChar ::= ":" | [A-Z] | "_" | [a-z] | [#xC0-#xD6] | [#xD8-#xF6] | [#xF8-#x2FF] | [#x370-#x37D] | [#x37F-#x1FFF] | [#x200C-#x200D] | [#x2070-#x218F] | [#x2C00-#x2FEF] | [#x3001-#xD7FF] | [#xF900-#xFDCF] | [#xFDF0-#xFFFD] | [#x10000-#xEFFFF]
2
+ //[4a] NameChar ::= NameStartChar | "-" | "." | [0-9] | #xB7 | [#x0300-#x036F] | [#x203F-#x2040]
3
+ //[5] Name ::= NameStartChar (NameChar)*
4
+ var nameStartChar = /[A-Z_a-z\xC0-\xD6\xD8-\xF6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD]///\u10000-\uEFFFF
5
+ var nameChar = new RegExp("[\\-\\.0-9"+nameStartChar.source.slice(1,-1)+"\u00B7\u0300-\u036F\\u203F-\u2040]");
6
+ var tagNamePattern = new RegExp('^'+nameStartChar.source+nameChar.source+'*(?:\:'+nameStartChar.source+nameChar.source+'*)?$');
7
+ //var tagNamePattern = /^[a-zA-Z_][\w\-\.]*(?:\:[a-zA-Z_][\w\-\.]*)?$/
8
+ //var handlers = 'resolveEntity,getExternalSubset,characters,endDocument,endElement,endPrefixMapping,ignorableWhitespace,processingInstruction,setDocumentLocator,skippedEntity,startDocument,startElement,startPrefixMapping,notationDecl,unparsedEntityDecl,error,fatalError,warning,attributeDecl,elementDecl,externalEntityDecl,internalEntityDecl,comment,endCDATA,endDTD,endEntity,startCDATA,startDTD,startEntity'.split(',')
9
+
10
+ //S_TAG, S_ATTR, S_EQ, S_V
11
+ //S_ATTR_S, S_E, S_S, S_C
12
+ var S_TAG = 0;//tag name offerring
13
+ var S_ATTR = 1;//attr name offerring
14
+ var S_ATTR_S=2;//attr name end and space offer
15
+ var S_EQ = 3;//=space?
16
+ var S_V = 4;//attr value(no quot value only)
17
+ var S_E = 5;//attr value end and no space(quot end)
18
+ var S_S = 6;//(attr value end || tag end ) && (space offer)
19
+ var S_C = 7;//closed el<el />
20
+
21
+ function XMLReader(){
22
+
23
+ }
24
+
25
+ XMLReader.prototype = {
26
+ parse:function(source,defaultNSMap,entityMap){
27
+ var domBuilder = this.domBuilder;
28
+ domBuilder.startDocument();
29
+ _copy(defaultNSMap ,defaultNSMap = {})
30
+ parse(source,defaultNSMap,entityMap,
31
+ domBuilder,this.errorHandler);
32
+ domBuilder.endDocument();
33
+ }
34
+ }
35
+ function parse(source,defaultNSMapCopy,entityMap,domBuilder,errorHandler){
36
+ function fixedFromCharCode(code) {
37
+ // String.prototype.fromCharCode does not supports
38
+ // > 2 bytes unicode chars directly
39
+ if (code > 0xffff) {
40
+ code -= 0x10000;
41
+ var surrogate1 = 0xd800 + (code >> 10)
42
+ , surrogate2 = 0xdc00 + (code & 0x3ff);
43
+
44
+ return String.fromCharCode(surrogate1, surrogate2);
45
+ } else {
46
+ return String.fromCharCode(code);
47
+ }
48
+ }
49
+ function entityReplacer(a){
50
+ var k = a.slice(1,-1);
51
+ if(k in entityMap){
52
+ return entityMap[k];
53
+ }else if(k.charAt(0) === '#'){
54
+ return fixedFromCharCode(parseInt(k.substr(1).replace('x','0x')))
55
+ }else{
56
+ errorHandler.error('entity not found:'+a);
57
+ return a;
58
+ }
59
+ }
60
+ function appendText(end){//has some bugs
61
+ if(end>start){
62
+ var xt = source.substring(start,end).replace(/&#?\w+;/g,entityReplacer);
63
+ locator&&position(start);
64
+ domBuilder.characters(xt,0,end-start);
65
+ start = end
66
+ }
67
+ }
68
+ function position(p,m){
69
+ while(p>=lineEnd && (m = linePattern.exec(source))){
70
+ lineStart = m.index;
71
+ lineEnd = lineStart + m[0].length;
72
+ locator.lineNumber++;
73
+ //console.log('line++:',locator,startPos,endPos)
74
+ }
75
+ locator.columnNumber = p-lineStart+1;
76
+ }
77
+ var lineStart = 0;
78
+ var lineEnd = 0;
79
+ var linePattern = /.+(?:\r\n?|\n)|.*$/g
80
+ var locator = domBuilder.locator;
81
+
82
+ var parseStack = [{currentNSMap:defaultNSMapCopy}]
83
+ var closeMap = {};
84
+ var start = 0;
85
+ while(true){
86
+ try{
87
+ var tagStart = source.indexOf('<',start);
88
+ if(tagStart<0){
89
+ if(!source.substr(start).match(/^\s*$/)){
90
+ var doc = domBuilder.document;
91
+ var text = doc.createTextNode(source.substr(start));
92
+ doc.appendChild(text);
93
+ domBuilder.currentElement = text;
94
+ }
95
+ return;
96
+ }
97
+ if(tagStart>start){
98
+ appendText(tagStart);
99
+ }
100
+ switch(source.charAt(tagStart+1)){
101
+ case '/':
102
+ var end = source.indexOf('>',tagStart+3);
103
+ var tagName = source.substring(tagStart+2,end);
104
+ var config = parseStack.pop();
105
+ var localNSMap = config.localNSMap;
106
+ if(config.tagName != tagName){
107
+ errorHandler.fatalError("end tag name: "+tagName+' is not match the current start tagName:'+config.tagName );
108
+ }
109
+ domBuilder.endElement(config.uri,config.localName,tagName);
110
+ if(localNSMap){
111
+ for(var prefix in localNSMap){
112
+ domBuilder.endPrefixMapping(prefix) ;
113
+ }
114
+ }
115
+ end++;
116
+ break;
117
+ // end elment
118
+ case '?':// <?...?>
119
+ locator&&position(tagStart);
120
+ end = parseInstruction(source,tagStart,domBuilder);
121
+ break;
122
+ case '!':// <!doctype,<![CDATA,<!--
123
+ locator&&position(tagStart);
124
+ end = parseDCC(source,tagStart,domBuilder,errorHandler);
125
+ break;
126
+ default:
127
+
128
+ locator&&position(tagStart);
129
+
130
+ var el = new ElementAttributes();
131
+
132
+ //elStartEnd
133
+ var end = parseElementStartPart(source,tagStart,el,entityReplacer,errorHandler);
134
+ var len = el.length;
135
+
136
+ if(locator){
137
+ if(len){
138
+ //attribute position fixed
139
+ for(var i = 0;i<len;i++){
140
+ var a = el[i];
141
+ position(a.offset);
142
+ a.offset = copyLocator(locator,{});
143
+ }
144
+ }
145
+ position(end);
146
+ }
147
+ if(!el.closed && fixSelfClosed(source,end,el.tagName,closeMap)){
148
+ el.closed = true;
149
+ if(!entityMap.nbsp){
150
+ errorHandler.warning('unclosed xml attribute');
151
+ }
152
+ }
153
+ appendElement(el,domBuilder,parseStack);
154
+
155
+
156
+ if(el.uri === 'http://www.w3.org/1999/xhtml' && !el.closed){
157
+ end = parseHtmlSpecialContent(source,end,el.tagName,entityReplacer,domBuilder)
158
+ }else{
159
+ end++;
160
+ }
161
+ }
162
+ }catch(e){
163
+ errorHandler.error('element parse error: '+e);
164
+ end = -1;
165
+ }
166
+ if(end>start){
167
+ start = end;
168
+ }else{
169
+ //TODO: 这里有可能sax回退,有位置错误风险
170
+ appendText(Math.max(tagStart,start)+1);
171
+ }
172
+ }
173
+ }
174
+ function copyLocator(f,t){
175
+ t.lineNumber = f.lineNumber;
176
+ t.columnNumber = f.columnNumber;
177
+ return t;
178
+ }
179
+
180
+ /**
181
+ * @see #appendElement(source,elStartEnd,el,selfClosed,entityReplacer,domBuilder,parseStack);
182
+ * @return end of the elementStartPart(end of elementEndPart for selfClosed el)
183
+ */
184
+ function parseElementStartPart(source,start,el,entityReplacer,errorHandler){
185
+ var attrName;
186
+ var value;
187
+ var p = ++start;
188
+ var s = S_TAG;//status
189
+ while(true){
190
+ var c = source.charAt(p);
191
+ switch(c){
192
+ case '=':
193
+ if(s === S_ATTR){//attrName
194
+ attrName = source.slice(start,p);
195
+ s = S_EQ;
196
+ }else if(s === S_ATTR_S){
197
+ s = S_EQ;
198
+ }else{
199
+ //fatalError: equal must after attrName or space after attrName
200
+ throw new Error('attribute equal must after attrName');
201
+ }
202
+ break;
203
+ case '\'':
204
+ case '"':
205
+ if(s === S_EQ){//equal
206
+ start = p+1;
207
+ p = source.indexOf(c,start)
208
+ if(p>0){
209
+ value = source.slice(start,p).replace(/&#?\w+;/g,entityReplacer);
210
+ el.add(attrName,value,start-1);
211
+ s = S_E;
212
+ }else{
213
+ //fatalError: no end quot match
214
+ throw new Error('attribute value no end \''+c+'\' match');
215
+ }
216
+ }else if(s == S_V){
217
+ value = source.slice(start,p).replace(/&#?\w+;/g,entityReplacer);
218
+ //console.log(attrName,value,start,p)
219
+ el.add(attrName,value,start);
220
+ //console.dir(el)
221
+ errorHandler.warning('attribute "'+attrName+'" missed start quot('+c+')!!');
222
+ start = p+1;
223
+ s = S_E
224
+ }else{
225
+ //fatalError: no equal before
226
+ throw new Error('attribute value must after "="');
227
+ }
228
+ break;
229
+ case '/':
230
+ switch(s){
231
+ case S_TAG:
232
+ el.setTagName(source.slice(start,p));
233
+ case S_E:
234
+ case S_S:
235
+ case S_C:
236
+ s = S_C;
237
+ el.closed = true;
238
+ case S_V:
239
+ case S_ATTR:
240
+ case S_ATTR_S:
241
+ break;
242
+ //case S_EQ:
243
+ default:
244
+ throw new Error("attribute invalid close char('/')")
245
+ }
246
+ break;
247
+ case ''://end document
248
+ //throw new Error('unexpected end of input')
249
+ errorHandler.error('unexpected end of input');
250
+ case '>':
251
+ switch(s){
252
+ case S_TAG:
253
+ el.setTagName(source.slice(start,p));
254
+ case S_E:
255
+ case S_S:
256
+ case S_C:
257
+ break;//normal
258
+ case S_V://Compatible state
259
+ case S_ATTR:
260
+ value = source.slice(start,p);
261
+ if(value.slice(-1) === '/'){
262
+ el.closed = true;
263
+ value = value.slice(0,-1)
264
+ }
265
+ case S_ATTR_S:
266
+ if(s === S_ATTR_S){
267
+ value = attrName;
268
+ }
269
+ if(s == S_V){
270
+ errorHandler.warning('attribute "'+value+'" missed quot(")!!');
271
+ el.add(attrName,value.replace(/&#?\w+;/g,entityReplacer),start)
272
+ }else{
273
+ errorHandler.warning('attribute "'+value+'" missed value!! "'+value+'" instead!!')
274
+ el.add(value,value,start)
275
+ }
276
+ break;
277
+ case S_EQ:
278
+ throw new Error('attribute value missed!!');
279
+ }
280
+ // console.log(tagName,tagNamePattern,tagNamePattern.test(tagName))
281
+ return p;
282
+ /*xml space '\x20' | #x9 | #xD | #xA; */
283
+ case '\u0080':
284
+ c = ' ';
285
+ default:
286
+ if(c<= ' '){//space
287
+ switch(s){
288
+ case S_TAG:
289
+ el.setTagName(source.slice(start,p));//tagName
290
+ s = S_S;
291
+ break;
292
+ case S_ATTR:
293
+ attrName = source.slice(start,p)
294
+ s = S_ATTR_S;
295
+ break;
296
+ case S_V:
297
+ var value = source.slice(start,p).replace(/&#?\w+;/g,entityReplacer);
298
+ errorHandler.warning('attribute "'+value+'" missed quot(")!!');
299
+ el.add(attrName,value,start)
300
+ case S_E:
301
+ s = S_S;
302
+ break;
303
+ //case S_S:
304
+ //case S_EQ:
305
+ //case S_ATTR_S:
306
+ // void();break;
307
+ //case S_C:
308
+ //ignore warning
309
+ }
310
+ }else{//not space
311
+ //S_TAG, S_ATTR, S_EQ, S_V
312
+ //S_ATTR_S, S_E, S_S, S_C
313
+ switch(s){
314
+ //case S_TAG:void();break;
315
+ //case S_ATTR:void();break;
316
+ //case S_V:void();break;
317
+ case S_ATTR_S:
318
+ errorHandler.warning('attribute "'+attrName+'" missed value!! "'+attrName+'" instead!!')
319
+ el.add(attrName,attrName,start);
320
+ start = p;
321
+ s = S_ATTR;
322
+ break;
323
+ case S_E:
324
+ errorHandler.warning('attribute space is required"'+attrName+'"!!')
325
+ case S_S:
326
+ s = S_ATTR;
327
+ start = p;
328
+ break;
329
+ case S_EQ:
330
+ s = S_V;
331
+ start = p;
332
+ break;
333
+ case S_C:
334
+ throw new Error("elements closed character '/' and '>' must be connected to");
335
+ }
336
+ }
337
+ }
338
+ p++;
339
+ }
340
+ }
341
+ /**
342
+ * @return end of the elementStartPart(end of elementEndPart for selfClosed el)
343
+ */
344
+ function appendElement(el,domBuilder,parseStack){
345
+ var tagName = el.tagName;
346
+ var localNSMap = null;
347
+ var currentNSMap = parseStack[parseStack.length-1].currentNSMap;
348
+ var i = el.length;
349
+ while(i--){
350
+ var a = el[i];
351
+ var qName = a.qName;
352
+ var value = a.value;
353
+ var nsp = qName.indexOf(':');
354
+ if(nsp>0){
355
+ var prefix = a.prefix = qName.slice(0,nsp);
356
+ var localName = qName.slice(nsp+1);
357
+ var nsPrefix = prefix === 'xmlns' && localName
358
+ }else{
359
+ localName = qName;
360
+ prefix = null
361
+ nsPrefix = qName === 'xmlns' && ''
362
+ }
363
+ //can not set prefix,because prefix !== ''
364
+ a.localName = localName ;
365
+ //prefix == null for no ns prefix attribute
366
+ if(nsPrefix !== false){//hack!!
367
+ if(localNSMap == null){
368
+ localNSMap = {}
369
+ //console.log(currentNSMap,0)
370
+ _copy(currentNSMap,currentNSMap={})
371
+ //console.log(currentNSMap,1)
372
+ }
373
+ currentNSMap[nsPrefix] = localNSMap[nsPrefix] = value;
374
+ a.uri = 'http://www.w3.org/2000/xmlns/'
375
+ domBuilder.startPrefixMapping(nsPrefix, value)
376
+ }
377
+ }
378
+ var i = el.length;
379
+ while(i--){
380
+ a = el[i];
381
+ var prefix = a.prefix;
382
+ if(prefix){//no prefix attribute has no namespace
383
+ if(prefix === 'xml'){
384
+ a.uri = 'http://www.w3.org/XML/1998/namespace';
385
+ }if(prefix !== 'xmlns'){
386
+ a.uri = currentNSMap[prefix]
387
+
388
+ //{console.log('###'+a.qName,domBuilder.locator.systemId+'',currentNSMap,a.uri)}
389
+ }
390
+ }
391
+ }
392
+ var nsp = tagName.indexOf(':');
393
+ if(nsp>0){
394
+ prefix = el.prefix = tagName.slice(0,nsp);
395
+ localName = el.localName = tagName.slice(nsp+1);
396
+ }else{
397
+ prefix = null;//important!!
398
+ localName = el.localName = tagName;
399
+ }
400
+ //no prefix element has default namespace
401
+ var ns = el.uri = currentNSMap[prefix || ''];
402
+ domBuilder.startElement(ns,localName,tagName,el);
403
+ //endPrefixMapping and startPrefixMapping have not any help for dom builder
404
+ //localNSMap = null
405
+ if(el.closed){
406
+ domBuilder.endElement(ns,localName,tagName);
407
+ if(localNSMap){
408
+ for(prefix in localNSMap){
409
+ domBuilder.endPrefixMapping(prefix)
410
+ }
411
+ }
412
+ }else{
413
+ el.currentNSMap = currentNSMap;
414
+ el.localNSMap = localNSMap;
415
+ parseStack.push(el);
416
+ }
417
+ }
418
+ function parseHtmlSpecialContent(source,elStartEnd,tagName,entityReplacer,domBuilder){
419
+ if(/^(?:script|textarea)$/i.test(tagName)){
420
+ var elEndStart = source.indexOf('</'+tagName+'>',elStartEnd);
421
+ var text = source.substring(elStartEnd+1,elEndStart);
422
+ if(/[&<]/.test(text)){
423
+ if(/^script$/i.test(tagName)){
424
+ //if(!/\]\]>/.test(text)){
425
+ //lexHandler.startCDATA();
426
+ domBuilder.characters(text,0,text.length);
427
+ //lexHandler.endCDATA();
428
+ return elEndStart;
429
+ //}
430
+ }//}else{//text area
431
+ text = text.replace(/&#?\w+;/g,entityReplacer);
432
+ domBuilder.characters(text,0,text.length);
433
+ return elEndStart;
434
+ //}
435
+
436
+ }
437
+ }
438
+ return elStartEnd+1;
439
+ }
440
+ function fixSelfClosed(source,elStartEnd,tagName,closeMap){
441
+ //if(tagName in closeMap){
442
+ var pos = closeMap[tagName];
443
+ if(pos == null){
444
+ //console.log(tagName)
445
+ pos = closeMap[tagName] = source.lastIndexOf('</'+tagName+'>')
446
+ }
447
+ return pos<elStartEnd;
448
+ //}
449
+ }
450
+ function _copy(source,target){
451
+ for(var n in source){target[n] = source[n]}
452
+ }
453
+ function parseDCC(source,start,domBuilder,errorHandler){//sure start with '<!'
454
+ var next= source.charAt(start+2)
455
+ switch(next){
456
+ case '-':
457
+ if(source.charAt(start + 3) === '-'){
458
+ var end = source.indexOf('-->',start+4);
459
+ //append comment source.substring(4,end)//<!--
460
+ if(end>start){
461
+ domBuilder.comment(source,start+4,end-start-4);
462
+ return end+3;
463
+ }else{
464
+ errorHandler.error("Unclosed comment");
465
+ return -1;
466
+ }
467
+ }else{
468
+ //error
469
+ return -1;
470
+ }
471
+ default:
472
+ if(source.substr(start+3,6) == 'CDATA['){
473
+ var end = source.indexOf(']]>',start+9);
474
+ domBuilder.startCDATA();
475
+ domBuilder.characters(source,start+9,end-start-9);
476
+ domBuilder.endCDATA()
477
+ return end+3;
478
+ }
479
+ //<!DOCTYPE
480
+ //startDTD(java.lang.String name, java.lang.String publicId, java.lang.String systemId)
481
+ var matchs = split(source,start);
482
+ var len = matchs.length;
483
+ if(len>1 && /!doctype/i.test(matchs[0][0])){
484
+ var name = matchs[1][0];
485
+ var pubid = len>3 && /^public$/i.test(matchs[2][0]) && matchs[3][0]
486
+ var sysid = len>4 && matchs[4][0];
487
+ var lastMatch = matchs[len-1]
488
+ domBuilder.startDTD(name,pubid && pubid.replace(/^(['"])(.*?)\1$/,'$2'),
489
+ sysid && sysid.replace(/^(['"])(.*?)\1$/,'$2'));
490
+ domBuilder.endDTD();
491
+
492
+ return lastMatch.index+lastMatch[0].length
493
+ }
494
+ }
495
+ return -1;
496
+ }
497
+
498
+
499
+
500
+ function parseInstruction(source,start,domBuilder){
501
+ var end = source.indexOf('?>',start);
502
+ if(end){
503
+ var match = source.substring(start,end).match(/^<\?(\S*)\s*([\s\S]*?)\s*$/);
504
+ if(match){
505
+ var len = match[0].length;
506
+ domBuilder.processingInstruction(match[1], match[2]) ;
507
+ return end+2;
508
+ }else{//error
509
+ return -1;
510
+ }
511
+ }
512
+ return -1;
513
+ }
514
+
515
+ /**
516
+ * @param source
517
+ */
518
+ function ElementAttributes(source){
519
+
520
+ }
521
+ ElementAttributes.prototype = {
522
+ setTagName:function(tagName){
523
+ if(!tagNamePattern.test(tagName)){
524
+ throw new Error('invalid tagName:'+tagName)
525
+ }
526
+ this.tagName = tagName
527
+ },
528
+ add:function(qName,value,offset){
529
+ if(!tagNamePattern.test(qName)){
530
+ throw new Error('invalid attribute:'+qName)
531
+ }
532
+ this[this.length++] = {qName:qName,value:value,offset:offset}
533
+ },
534
+ length:0,
535
+ getLocalName:function(i){return this[i].localName},
536
+ getOffset:function(i){return this[i].offset},
537
+ getQName:function(i){return this[i].qName},
538
+ getURI:function(i){return this[i].uri},
539
+ getValue:function(i){return this[i].value}
540
+ // ,getIndex:function(uri, localName)){
541
+ // if(localName){
542
+ //
543
+ // }else{
544
+ // var qName = uri
545
+ // }
546
+ // },
547
+ // getValue:function(){return this.getValue(this.getIndex.apply(this,arguments))},
548
+ // getType:function(uri,localName){}
549
+ // getType:function(i){},
550
+ }
551
+
552
+
553
+
554
+
555
+ function _set_proto_(thiz,parent){
556
+ thiz.__proto__ = parent;
557
+ return thiz;
558
+ }
559
+ if(!(_set_proto_({},_set_proto_.prototype) instanceof _set_proto_)){
560
+ _set_proto_ = function(thiz,parent){
561
+ function p(){};
562
+ p.prototype = parent;
563
+ p = new p();
564
+ for(parent in thiz){
565
+ p[parent] = thiz[parent];
566
+ }
567
+ return p;
568
+ }
569
+ }
570
+
571
+ function split(source,start){
572
+ var match;
573
+ var buf = [];
574
+ var reg = /'[^']+'|"[^"]+"|[^\s<>\/=]+=?|(\/?\s*>|<)/g;
575
+ reg.lastIndex = start;
576
+ reg.exec(source);//skip <
577
+ while(match = reg.exec(source)){
578
+ buf.push(match);
579
+ if(match[1])return buf;
580
+ }
581
+ }
582
+
583
+ if(typeof require == 'function'){
584
+ exports.XMLReader = XMLReader;
585
+ }
586
+
@@ -0,0 +1,96 @@
1
+ ## xpath
2
+ DOM 3 XPath 1.0 implemention and helper for JavaScript, with node.js support.
3
+
4
+ Originally written by Cameron McCormack ([blog](http://mcc.id.au/xpathjs)).
5
+
6
+ Additional contributions from
7
+ Yaron Naveh ([blog](http://webservices20.blogspot.com/))
8
+ goto100
9
+ Thomas Weinert
10
+ Jimmy Rishe
11
+ and [others](https://github.com/goto100/xpath/graphs/contributors)
12
+
13
+ ## Install
14
+ Install with [npm](http://github.com/isaacs/npm):
15
+
16
+ npm install xpath
17
+
18
+ xpath is xml engine agnostic but I recommend to use [xmldom](https://github.com/jindw/xmldom):
19
+
20
+ npm install xmldom
21
+
22
+
23
+ ## Your first xpath:
24
+ `````javascript
25
+ var xpath = require('xpath')
26
+ , dom = require('xmldom').DOMParser
27
+
28
+ var xml = "<book><title>Harry Potter</title></book>"
29
+ var doc = new dom().parseFromString(xml)
30
+ var nodes = xpath.select("//title", doc)
31
+
32
+ console.log(nodes[0].localName + ": " + nodes[0].firstChild.data)
33
+ console.log("node: " + nodes[0].toString())
34
+ `````
35
+
36
+
37
+ title: Harry Potter
38
+ Node: <title>Harry Potter</title>
39
+
40
+ ## Get text values directly
41
+ `````javascript
42
+ var xml = "<book><title>Harry Potter</title></book>"
43
+ var doc = new dom().parseFromString(xml)
44
+ var title = xpath.select("//title/text()", doc).toString()
45
+
46
+ console.log(title)
47
+ `````
48
+
49
+
50
+ Harry Potter
51
+
52
+ ## Namespaces
53
+ `````javascript
54
+ var xml = "<book><title xmlns='myns'>Harry Potter</title></book>"
55
+ var doc = new dom().parseFromString(xml)
56
+ var node = xpath.select("//*[local-name(.)='title' and namespace-uri(.)='myns']", doc)[0]
57
+
58
+ console.log(node.namespaceURI)
59
+ `````
60
+
61
+
62
+ myns
63
+
64
+ ## Namespaces with easy mappings
65
+ `````javascript
66
+ var xml = "<book xmlns:bookml='http://example.com/book'><bookml:title>Harry Potter</bookml:title></book>"
67
+ var select = xpath.useNamespaces({"bookml": "http://example.com/book"});
68
+
69
+ console.log(select('//bookml:title/text()', doc)[0].nodeValue);
70
+ `````
71
+
72
+
73
+ Harry Potter
74
+
75
+ ## Default namespace with mapping
76
+ `````javascript
77
+ var xml = "<book xmlns='http://example.com/book'><title>Harry Potter</title></book>"
78
+ var select = xpath.useNamespaces({"bookml": "http://example.com/book"});
79
+
80
+ console.log(select('//bookml:title/text()', doc)[0].nodeValue);
81
+ `````
82
+
83
+
84
+ Harry Potter
85
+
86
+ ## Attributes
87
+ `````javascript
88
+ var xml = "<book author='J. K. Rowling'><title>Harry Potter</title></book>"
89
+ var doc = new dom().parseFromString(xml)
90
+ var author = xpath.select1("/book/@author", doc).value
91
+
92
+ console.log(author)
93
+ `````
94
+
95
+
96
+ J. K. Rowling