File Coverage

LibXML.xs
Criterion Covered Total %
statement 3251 3908 83.1
branch 2025 4242 47.7
condition n/a
subroutine n/a
pod n/a
total 5276 8150 64.7


line stmt bran cond sub pod time code
1             /* $Id$
2             *
3             * This is free software, you may use it and distribute it under the same terms as
4             * Perl itself.
5             *
6             * Copyright 2001-2003 AxKit.com Ltd., 2002-2006 Christian Glahn, 2006-2009 Petr Pajas
7             */
8              
9             #ifdef __cplusplus
10             extern "C" {
11             #endif
12              
13             #if defined(_MSC_VER)
14             #define _CRT_SECURE_NO_DEPRECATE 1
15             #define _CRT_NONSTDC_NO_DEPRECATE 1
16             #endif
17              
18             /* perl stuff */
19             #include "EXTERN.h"
20             #include "perl.h"
21             #include "XSUB.h"
22             #define NEED_newRV_noinc_GLOBAL
23             #define NEED_sv_2pv_flags
24             #include "ppport.h"
25             #include "Av_CharPtrPtr.h" /* XS_*_charPtrPtr() */
26              
27             #include
28              
29             #ifndef WIN32
30             #include
31             #endif
32              
33             /* libxml2 configuration properties */
34             #include
35              
36             #define DEBUG_C14N
37              
38             /* libxml2 stuff */
39             #include
40             #include
41             #include
42             #include
43             #include
44             #include
45             #include
46             #include
47             #include
48             #include
49             #include
50             #include
51             /* #include */
52             #include
53             #include
54             #include
55              
56             #ifdef LIBXML_PATTERN_ENABLED
57             #include
58             #endif
59              
60             #ifdef LIBXML_REGEXP_ENABLED
61             #include
62             #endif
63              
64             #if LIBXML_VERSION >= 20510
65             #define HAVE_SCHEMAS
66             #include
67             #include
68             #endif
69              
70             #if LIBXML_VERSION >= 20621
71             #define WITH_SERRORS
72             #ifdef LIBXML_READER_ENABLED
73             #define HAVE_READER_SUPPORT
74             #include
75             #endif
76             #endif
77              
78             #ifdef LIBXML_CATALOG_ENABLED
79             #include
80             #endif
81              
82             #ifdef HAVE_READER_SUPPORT
83              
84             typedef enum {
85             XML_TEXTREADER_NONE = -1,
86             XML_TEXTREADER_START= 0,
87             XML_TEXTREADER_ELEMENT= 1,
88             XML_TEXTREADER_END= 2,
89             XML_TEXTREADER_EMPTY= 3,
90             XML_TEXTREADER_BACKTRACK= 4,
91             XML_TEXTREADER_DONE= 5,
92             XML_TEXTREADER_ERROR= 6
93             } xmlTextReaderState;
94              
95             typedef enum {
96             XML_TEXTREADER_NOT_VALIDATE = 0,
97             XML_TEXTREADER_VALIDATE_DTD = 1,
98             XML_TEXTREADER_VALIDATE_RNG = 2,
99             XML_TEXTREADER_VALIDATE_XSD = 4
100             } xmlTextReaderValidate;
101              
102             #endif /* HAVE_READER_SUPPORT */
103              
104             /* GDOME support
105             * libgdome installs only the core functions to the system.
106             * this is not enough for XML::LibXML <-> XML::GDOME conversion.
107             * therefore there is the need to ship as well the GDOME core headers.
108             */
109             #ifdef XML_LIBXML_GDOME_SUPPORT
110              
111             #include
112             #include
113              
114             #endif
115              
116              
117             #if LIBXML_VERSION < 20621
118             /* HTML_PARSE_RECOVER was added in libxml2 2.6.21 */
119             # define HTML_PARSE_RECOVER XML_PARSE_RECOVER
120             #endif
121              
122              
123             /* XML::LibXML stuff */
124             #include "perl-libxml-mm.h"
125             #include "perl-libxml-sax.h"
126              
127             #include "dom.h"
128             #include "xpath.h"
129             #include "xpathcontext.h"
130              
131             #ifdef __cplusplus
132             }
133             #endif
134              
135              
136             #define TEST_PERL_FLAG(flag) \
137             SvTRUE(get_sv(flag, FALSE)) ? 1 : 0
138              
139             #ifdef HAVE_READER_SUPPORT
140             #define LIBXML_READER_TEST_ELEMENT(reader,name,nsURI) \
141             (xmlTextReaderNodeType(reader) == XML_READER_TYPE_ELEMENT) && \
142             ((!nsURI && !name) \
143             || \
144             (!nsURI && xmlStrcmp((const xmlChar*)name, xmlTextReaderConstName(reader) ) == 0 ) \
145             || \
146             (nsURI && xmlStrcmp((const xmlChar*)nsURI, xmlTextReaderConstNamespaceUri(reader))==0 \
147             && \
148             (!name || xmlStrcmp((const xmlChar*)name, xmlTextReaderConstLocalName(reader)) == 0)))
149             #endif
150              
151             /* this should keep the default */
152             static xmlExternalEntityLoader LibXML_old_ext_ent_loader = NULL;
153              
154             /* global external entity loader */
155             SV *EXTERNAL_ENTITY_LOADER_FUNC = (SV *)NULL;
156              
157             SV* PROXY_NODE_REGISTRY_MUTEX = NULL;
158              
159             /* ****************************************************************
160             * Error handler
161             * **************************************************************** */
162              
163             #ifdef WITH_SERRORS
164              
165             #define INIT_READER_ERROR_HANDLER(reader)
166              
167             #define PREINIT_SAVED_ERROR SV* saved_error = sv_2mortal(newSV(0));
168              
169             #define INIT_ERROR_HANDLER \
170             xmlSetGenericErrorFunc((void *)saved_error, \
171             (xmlGenericErrorFunc) LibXML_flat_handler); \
172             xmlSetStructuredErrorFunc((void *)saved_error, \
173             (xmlStructuredErrorFunc)LibXML_struct_error_handler)
174              
175             #define REPORT_ERROR(recover) LibXML_report_error_ctx(saved_error, recover)
176              
177             #define CLEANUP_ERROR_HANDLER xmlSetGenericErrorFunc(NULL,NULL); \
178             xmlSetStructuredErrorFunc(NULL,NULL)
179              
180             #else /* WITH_SERRORS */
181              
182             #define INIT_READER_ERROR_HANDLER(reader) \
183             if (reader) \
184             xmlTextReaderSetErrorHandler(reader, LibXML_reader_error_handler, \
185             sv_2mortal(newSVpv("",0)));
186              
187             #define PREINIT_SAVED_ERROR SV* saved_error = sv_2mortal(newSVpv("",0));
188              
189             #define INIT_ERROR_HANDLER \
190             xmlSetGenericErrorFunc((void *) saved_error, \
191             (xmlGenericErrorFunc) LibXML_error_handler_ctx)
192              
193             #define REPORT_ERROR(recover) LibXML_report_error_ctx(saved_error, recover)
194              
195             #define CLEANUP_ERROR_HANDLER xmlSetGenericErrorFunc(NULL,NULL);
196              
197              
198             #endif /* WITH_SERRORS */
199              
200             #ifdef WITH_SERRORS
201             void
202 2581           LibXML_struct_error_callback(SV * saved_error, SV * libErr )
203             {
204              
205             dTHX;
206 2581           dSP;
207              
208 2581 50         if ( saved_error == NULL ) {
209 0           warn( "have no save_error\n" );
210             }
211              
212 2581           ENTER;
213 2581           SAVETMPS;
214 2581 50         PUSHMARK(SP);
215              
216 2581 50         XPUSHs(sv_2mortal(libErr));
217 2581 50         if ( saved_error != NULL && SvOK(saved_error) ) {
    100          
    50          
    50          
218 2419 50         XPUSHs(saved_error);
219             }
220 2581           PUTBACK;
221              
222 2581 50         if ( saved_error != NULL ) {
223 2581           call_pv( "XML::LibXML::Error::_callback_error", G_SCALAR | G_EVAL );
224             } else {
225 0           call_pv( "XML::LibXML::Error::_instant_error_callback", G_SCALAR );
226             }
227 2581           SPAGAIN;
228              
229 2581 50         if ( SvTRUE(ERRSV) ) {
    50          
    50          
    50          
    0          
    0          
    50          
    50          
    0          
    0          
    0          
    0          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    0          
    0          
    50          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
230 0           (void) POPs;
231 0           croak_obj;
232             } else {
233 2581           sv_setsv(saved_error, POPs);
234             }
235              
236 2581           PUTBACK;
237 2581 50         FREETMPS;
238 2581           LEAVE;
239 2581           }
240              
241             void
242 2578           LibXML_struct_error_handler(SV * saved_error, xmlErrorPtr error )
243             {
244 2578           const char * CLASS = "XML::LibXML::LibError";
245             SV* libErr;
246              
247 2578           libErr = NEWSV(0,0);
248 2578           sv_setref_pv( libErr, CLASS, (void*)error );
249 2578           LibXML_struct_error_callback( saved_error, libErr);
250 2578           }
251              
252              
253             void
254 3           LibXML_flat_handler(SV * saved_error, const char * msg, ...)
255             {
256             SV* sv;
257             va_list args;
258              
259 3           sv = newSVpv("",0);
260 3           va_start(args, msg);
261 3           sv_vcatpvf(sv, msg, &args);
262 3           va_end(args);
263             xs_warn("flat error\n");
264 3           LibXML_struct_error_callback( saved_error, sv);
265 3           }
266              
267             #endif /* WITH_SERRORS */
268              
269              
270             /* If threads-support is working correctly in libxml2 then
271             * this method will be called with the correct thread-context */
272             void
273 0           LibXML_error_handler_ctx(void * ctxt, const char * msg, ...)
274             {
275             va_list args;
276 0           SV * saved_error = (SV *) ctxt;
277              
278             /* If saved_error is null we croak with the error */
279 0 0         if( NULL == saved_error ) {
280 0           SV * sv = sv_2mortal(newSV(0));
281 0           va_start(args, msg);
282             /* vfprintf(stderr, msg, args); */
283 0           sv_vsetpvfn(sv, msg, strlen(msg), &args, NULL, 0, NULL);
284 0           va_end(args);
285 0 0         croak("%s", SvPV_nolen(sv));
286             /* Otherwise, save the error */
287             } else {
288 0           va_start(args, msg);
289             /* vfprintf(stderr, msg, args); */
290 0           sv_vcatpvfn(saved_error, msg, strlen(msg), &args, NULL, 0, NULL);
291 0           va_end(args);
292             }
293 0           }
294              
295             static void
296 0           LibXML_validity_error_ctx(void * ctxt, const char *msg, ...)
297             {
298             va_list args;
299 0           SV * saved_error = (SV *) ctxt;
300              
301             /* If saved_error is null we croak with the error */
302 0 0         if( NULL == saved_error ) {
303 0           SV * sv = sv_2mortal(newSV(0));
304 0           va_start(args, msg);
305 0           sv_vsetpvfn(sv, msg, strlen(msg), &args, NULL, 0, NULL);
306 0           va_end(args);
307 0 0         croak("%s", SvPV_nolen(sv));
308             /* Otherwise, save the error */
309             } else {
310 0           va_start(args, msg);
311 0           sv_vcatpvfn(saved_error, msg, strlen(msg), &args, NULL, 0, NULL);
312 0           va_end(args);
313             }
314 0           }
315              
316             static void
317 0           LibXML_validity_warning_ctx(void * ctxt, const char *msg, ...)
318             {
319             va_list args;
320 0           SV * saved_error = (SV *) ctxt;
321             STRLEN len;
322              
323             /* If saved_error is null we croak with the error */
324 0 0         if( NULL == saved_error ) {
325 0           SV * sv = sv_2mortal(newSV(0));
326 0           va_start(args, msg);
327 0           sv_vsetpvfn(sv, msg, strlen(msg), &args, NULL, 0, NULL);
328 0           va_end(args);
329 0 0         croak("LibXML_validity_warning_ctx internal error: context was null (%s)", SvPV_nolen(sv));
330             /* Otherwise, give the warning */
331             } else {
332 0           va_start(args, msg);
333 0           sv_vcatpvfn(saved_error, msg, strlen(msg), &args, NULL, 0, NULL);
334 0           va_end(args);
335 0 0         warn("validation error: %s", SvPV(saved_error, len));
336             }
337 0           }
338              
339             static int
340 399           LibXML_will_die_ctx(SV * saved_error, int recover)
341             {
342             #ifdef WITH_SERRORS
343 399 50         if( saved_error!=NULL && SvOK(saved_error) ) {
    100          
    50          
    50          
344 85 50         if ( recover == 0 ) {
345 85           return 1;
346             }
347             }
348             #else
349             if( 0 < SvCUR( saved_error ) ) {
350             if ( recover == 0 ) {
351             return 1;
352             }
353             }
354             #endif
355 314           return 0;
356             }
357              
358              
359             static void
360 1617           LibXML_report_error_ctx(SV * saved_error, int recover)
361             {
362             #ifdef WITH_SERRORS
363 1617 50         if( saved_error!=NULL && SvOK( saved_error ) ) {
    100          
    50          
    50          
364 158 100         if (!recover || recover==1) {
    100          
365             dTHX;
366 154           dSP;
367              
368 154           ENTER;
369 154           SAVETMPS;
370 154 50         PUSHMARK(SP);
371 154 50         EXTEND(SP, 1);
372 154           PUSHs(saved_error);
373 154           PUTBACK;
374 154 100         if (recover==1) {
375 3           call_pv( "XML::LibXML::Error::_report_warning", G_SCALAR | G_DISCARD);
376             } else {
377 151           call_pv( "XML::LibXML::Error::_report_error", G_SCALAR | G_DISCARD);
378             }
379 3           SPAGAIN;
380              
381 3           PUTBACK;
382 3 50         FREETMPS;
383 3           LEAVE;
384             }
385             }
386             #else
387             if( 0 < SvCUR( saved_error ) ) {
388             if( recover ) {
389             if ( recover == 1 ) {
390             warn("%s", SvPV_nolen(saved_error));
391             } /* else recover silently */
392             } else {
393             croak("%s", SvPV_nolen(saved_error));
394             }
395             }
396             #endif
397 1466           }
398              
399             #ifdef HAVE_READER_SUPPORT
400              
401             #ifndef WITH_SERRORS
402             static void
403             LibXML_reader_error_handler(void * ctxt,
404             const char * msg,
405             xmlParserSeverities severity,
406             xmlTextReaderLocatorPtr locator)
407             {
408             int line = xmlTextReaderLocatorLineNumber(locator);
409             xmlChar * filename = xmlTextReaderLocatorBaseURI(locator);
410             SV * msg_sv = sv_2mortal(C2Sv((xmlChar*) msg,NULL));
411             SV * error = sv_2mortal(newSVpv("", 0));
412              
413             switch (severity) {
414             case XML_PARSER_SEVERITY_VALIDITY_WARNING:
415             sv_catpv(error, "Validity WARNING");
416             break;
417             case XML_PARSER_SEVERITY_WARNING:
418             sv_catpv(error, "Reader WARNING");
419             break;
420             case XML_PARSER_SEVERITY_VALIDITY_ERROR:
421             sv_catpv(error, "Validity ERROR");
422             break;
423             case XML_PARSER_SEVERITY_ERROR:
424             sv_catpv(error, "Reader ERROR");
425             break;
426             }
427             if (filename) {
428             sv_catpvf(error, " in %s", filename);
429             xmlFree(filename);
430             }
431             if (line >= 0) {
432             sv_catpvf(error, " at line %d", line);
433             }
434             sv_catpvf(error, ": %s", SvPV_nolen(msg_sv));
435             if (severity == XML_PARSER_SEVERITY_VALIDITY_WARNING ||
436             severity == XML_PARSER_SEVERITY_WARNING ) {
437             warn("%s", SvPV_nolen(error));
438             } else {
439             SV * error_sv = (SV*) ctxt;
440             if (error_sv) {
441             sv_catpvf(error_sv, "%s ", SvPV_nolen(error));
442             } else {
443             croak("%s",SvPV_nolen(error));
444             }
445             }
446             }
447             #endif /* !defined WITH_SERRORS */
448              
449             SV *
450 0           LibXML_get_reader_error_data(xmlTextReaderPtr reader)
451             {
452 0           SV * saved_error = NULL;
453 0           xmlTextReaderErrorFunc f = NULL;
454 0           xmlTextReaderGetErrorHandler(reader, &f, (void **) &saved_error);
455 0           return saved_error;
456             }
457              
458             #ifndef WITH_SERRORS
459             static void
460             LibXML_report_reader_error(xmlTextReaderPtr reader)
461             {
462             SV * saved_error = NULL;
463             xmlTextReaderErrorFunc f = NULL;
464             xmlTextReaderGetErrorHandler(reader, &f, (void **) &saved_error);
465             if ( saved_error && SvOK( saved_error) && 0 < SvCUR( saved_error ) ) {
466             croak("%s", SvPV_nolen(saved_error));
467             }
468             }
469             #endif /* !defined WITH_SERRORS */
470              
471             #endif /* HAVE_READER_SUPPORT */
472              
473             static int
474 902           LibXML_get_recover(HV * real_obj)
475             {
476 902           SV** item = hv_fetch( real_obj, "XML_LIBXML_RECOVER", 18, 0 );
477 902 100         return ( item != NULL && SvTRUE(*item) ) ? SvIV(*item) : 0;
    50          
    50          
    0          
    100          
    50          
    50          
    50          
    0          
    0          
    0          
    0          
    0          
    50          
    50          
    50          
    0          
    0          
    50          
    0          
    50          
478             }
479              
480             static SV *
481 413           LibXML_NodeToSv(HV * real_obj, xmlNodePtr real_doc)
482             {
483 413           SV** item = hv_fetch( real_obj, "XML_LIBXML_GDOME", 16, 0 );
484              
485 413 100         if ( item != NULL && SvTRUE(*item) ) {
    50          
    50          
    0          
    50          
    50          
    50          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
486 0           return PmmNodeToGdomeSv(real_doc);
487             }
488             else {
489 413           return PmmNodeToSv(real_doc, NULL);
490             }
491             }
492              
493             /* ****************************************************************
494             * IO callbacks
495             * **************************************************************** */
496              
497             int
498 35           LibXML_read_perl (SV * ioref, char * buffer, int len)
499             {
500             dTHX;
501 35           dSP;
502              
503             int cnt;
504             SV * read_results;
505             IV read_results_iv;
506             STRLEN read_length;
507             char * chars;
508 35           SV * tbuff = NEWSV(0,len);
509 35           SV * tsize = newSViv(len);
510              
511 35           ENTER;
512 35           SAVETMPS;
513              
514 35 50         PUSHMARK(SP);
515 35 50         EXTEND(SP, 3);
516 35           PUSHs(ioref);
517 35           PUSHs(sv_2mortal(tbuff));
518 35           PUSHs(sv_2mortal(tsize));
519 35           PUTBACK;
520              
521 35 100         if (sv_isobject(ioref)) {
522 11           cnt = call_method("read", G_SCALAR | G_EVAL);
523             }
524             else {
525 24           cnt = call_pv("XML::LibXML::__read", G_SCALAR | G_EVAL);
526             }
527              
528 35           SPAGAIN;
529              
530 35 50         if (cnt != 1) {
531 0           croak("read method call failed");
532             }
533              
534 35 50         if (SvTRUE(ERRSV)) {
    50          
    50          
    50          
    0          
    50          
    50          
    0          
    0          
    0          
    0          
    50          
    50          
    50          
    50          
    50          
    100          
    50          
    50          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    100          
535 1           (void) POPs;
536 1           croak_obj;
537             }
538              
539 34           read_results = POPs;
540              
541 34 50         if (!SvOK(read_results)) {
    0          
    0          
542 0           croak("read error");
543             }
544              
545 34 50         read_results_iv = SvIV(read_results);
546              
547 34 50         chars = SvPV(tbuff, read_length);
548              
549             /*
550             * If the file handle uses an encoding layer, the length parameter is
551             * interpreted as character count, not as byte count. So it's possible
552             * that more than len bytes are read which would overflow the buffer.
553             * Check for this condition also by comparing the return value.
554             */
555 34 100         if (read_results_iv != read_length || read_length > len) {
    50          
556 1           croak("Read more bytes than requested. Do you use an encoding-related"
557             " PerlIO layer?");
558             }
559 33           strncpy(buffer, chars, read_length);
560              
561 33           PUTBACK;
562 33 50         FREETMPS;
563 33           LEAVE;
564              
565 33           return read_length;
566             }
567              
568             /* used only by Reader */
569             int
570 1           LibXML_close_perl (SV * ioref)
571             {
572 1           SvREFCNT_dec(ioref);
573 1           return 0;
574             }
575              
576             int
577 116           LibXML_input_match(char const * filename)
578             {
579             int results;
580             int count;
581             SV * res;
582              
583 116           results = 0;
584              
585             {
586             dTHX;
587 116           dSP;
588              
589 116           ENTER;
590 116           SAVETMPS;
591              
592 116 50         PUSHMARK(SP);
593 116 50         EXTEND(SP, 1);
594 116           PUSHs(sv_2mortal(newSVpv((char*)filename, 0)));
595 116           PUTBACK;
596              
597 116           count = call_pv("XML::LibXML::InputCallback::_callback_match",
598             G_SCALAR | G_EVAL);
599              
600 116           SPAGAIN;
601              
602 116 50         if (count != 1) {
603 0           croak("match callback must return a single value");
604             }
605              
606 116 50         if (SvTRUE(ERRSV)) {
    50          
    50          
    50          
    0          
    50          
    50          
    0          
    0          
    0          
    0          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    50          
607 0           (void) POPs;
608 0           croak_obj;
609             }
610              
611 116           res = POPs;
612              
613 116 50         if (SvTRUE(res)) {
    50          
    50          
    0          
    0          
    50          
    0          
    0          
    0          
    0          
    50          
    50          
    100          
    50          
    0          
    100          
614 25           results = 1;
615             }
616              
617 116           PUTBACK;
618 116 50         FREETMPS;
619 116           LEAVE;
620             }
621 116           return results;
622             }
623              
624             void *
625 25           LibXML_input_open(char const * filename)
626             {
627             SV * results;
628             int count;
629              
630             dTHX;
631 25           dSP;
632              
633 25           ENTER;
634 25           SAVETMPS;
635              
636 25 50         PUSHMARK(SP);
637 25 50         EXTEND(SP, 1);
638 25           PUSHs(sv_2mortal(newSVpv((char*)filename, 0)));
639 25           PUTBACK;
640              
641 25           count = call_pv("XML::LibXML::InputCallback::_callback_open",
642             G_SCALAR | G_EVAL);
643              
644 25           SPAGAIN;
645              
646 25 50         if (count != 1) {
647 0           croak("open callback must return a single value");
648             }
649              
650 25 50         if (SvTRUE(ERRSV)) {
    50          
    50          
    50          
    0          
    50          
    50          
    0          
    0          
    0          
    0          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    50          
651 0           (void) POPs;
652 0           croak_obj;
653             }
654              
655 25           results = POPs;
656              
657 25           (void)SvREFCNT_inc(results);
658              
659 25           PUTBACK;
660 25 50         FREETMPS;
661 25           LEAVE;
662              
663 25           return (void *)results;
664             }
665              
666             int
667 74           LibXML_input_read(void * context, char * buffer, int len)
668             {
669             STRLEN res_len;
670             const char * output;
671             SV * ctxt;
672             SV * output_sv;
673              
674 74           res_len = 0;
675 74           ctxt = (SV *)context;
676              
677             {
678             int count;
679              
680             dTHX;
681 74           dSP;
682              
683 74           ENTER;
684 74           SAVETMPS;
685              
686 74 50         PUSHMARK(SP);
687 74 50         EXTEND(SP, 2);
688 74           PUSHs(ctxt);
689 74           PUSHs(sv_2mortal(newSViv(len)));
690 74           PUTBACK;
691              
692 74           count = call_pv("XML::LibXML::InputCallback::_callback_read",
693             G_SCALAR | G_EVAL);
694              
695 74           SPAGAIN;
696              
697 74 50         if (count != 1) {
698 0           croak("read callback must return a single value");
699             }
700              
701 74 50         if (SvTRUE(ERRSV)) {
    50          
    50          
    50          
    0          
    50          
    50          
    0          
    0          
    0          
    0          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    50          
702 0           (void) POPs;
703 0           croak_obj;
704             }
705              
706             /*
707             * Handle undef()s gracefully, to avoid using POPpx which warns upon $^W
708             * being set. See t/49callbacks_returning_undef.t and:
709             * https://rt.cpan.org/Ticket/Display.html?id=70321
710             * */
711              
712 74           output_sv = POPs;
713 74 50         output = SvOK(output_sv) ? SvPV_nolen(output_sv) : NULL;
    0          
    0          
    50          
714              
715 74 50         if (output != NULL) {
716 74           res_len = strlen(output);
717 74 100         if (res_len) {
718 49           strncpy(buffer, output, res_len);
719             }
720             else {
721 25           buffer[0] = 0;
722             }
723             }
724              
725 74           PUTBACK;
726 74 50         FREETMPS;
727 74           LEAVE;
728             }
729 74           return res_len;
730             }
731              
732             void
733 25           LibXML_input_close(void * context)
734             {
735             SV * ctxt;
736              
737 25           ctxt = (SV *)context;
738              
739             {
740             dTHX;
741 25           dSP;
742              
743 25           ENTER;
744 25           SAVETMPS;
745              
746 25 50         PUSHMARK(SP);
747 25 50         EXTEND(SP, 1);
748 25           PUSHs(ctxt);
749 25           PUTBACK;
750              
751 25           call_pv("XML::LibXML::InputCallback::_callback_close",
752             G_SCALAR | G_EVAL | G_DISCARD);
753              
754 25           SvREFCNT_dec(ctxt);
755              
756 25 50         if (SvTRUE(ERRSV)) {
    50          
    50          
    50          
    0          
    50          
    50          
    0          
    0          
    0          
    0          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    50          
757 0           croak_obj;
758             }
759              
760 25 50         FREETMPS;
761 25           LEAVE;
762             }
763 25           }
764              
765             int
766 1           LibXML_output_write_handler(void * ioref, char * buffer, int len)
767             {
768 1 50         if ( buffer != NULL && len > 0) {
    50          
769             dTHX;
770 1           dSP;
771              
772 1           SV * tbuff = newSVpv(buffer,len);
773 1           SV * tsize = newSViv(len);
774              
775              
776 1           ENTER;
777 1           SAVETMPS;
778              
779 1 50         PUSHMARK(SP);
780 1 50         EXTEND(SP, 3);
781 1           PUSHs((SV*)ioref);
782 1           PUSHs(sv_2mortal(tbuff));
783 1           PUSHs(sv_2mortal(tsize));
784 1           PUTBACK;
785              
786 1           call_pv("XML::LibXML::__write", G_SCALAR | G_EVAL | G_DISCARD );
787              
788 1 50         if (SvTRUE(ERRSV)) {
    50          
    50          
    50          
    0          
    50          
    50          
    0          
    0          
    0          
    0          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    50          
789 0           croak_obj;
790             }
791              
792 1 50         FREETMPS;
793 1           LEAVE;
794             }
795 1           return len;
796             }
797              
798             int
799 1           LibXML_output_close_handler( void * handler )
800             {
801 1           return 1;
802             }
803              
804             xmlParserInputPtr
805 6           LibXML_load_external_entity(
806             const char * URL,
807             const char * ID,
808             xmlParserCtxtPtr ctxt)
809             {
810             SV ** func;
811             int count;
812             SV * results;
813             STRLEN results_len;
814             const char * results_pv;
815             xmlParserInputBufferPtr input_buf;
816              
817 6 50         if (ctxt->_private == NULL && EXTERNAL_ENTITY_LOADER_FUNC == NULL)
    0          
818             {
819 0           return xmlNewInputFromFile(ctxt, URL);
820             }
821              
822 6 50         if (URL == NULL) {
823 0           URL = "";
824             }
825 6 100         if (ID == NULL) {
826 3           ID = "";
827             }
828              
829             /* fetch entity loader function */
830 6 100         if(EXTERNAL_ENTITY_LOADER_FUNC != NULL)
831             {
832 2           func = &EXTERNAL_ENTITY_LOADER_FUNC;
833             }
834             else
835             {
836             SV * self;
837             HV * real_obj;
838              
839 4           self = (SV *)ctxt->_private;
840 4           real_obj = (HV *)SvRV(self);
841 4           func = hv_fetch(real_obj, "ext_ent_handler", 15, 0);
842             }
843              
844 6 50         if (func != NULL && SvTRUE(*func)) {
    50          
    50          
    0          
    50          
    0          
    0          
    50          
    0          
    0          
    0          
    0          
    0          
    50          
    0          
    0          
    0          
    0          
    0          
    50          
845             dTHX;
846 6           dSP;
847              
848 6           ENTER;
849 6           SAVETMPS;
850              
851 6 50         PUSHMARK(SP) ;
852 6 50         XPUSHs(sv_2mortal(newSVpv((char*)URL, 0)));
853 6 50         XPUSHs(sv_2mortal(newSVpv((char*)ID, 0)));
854 6           PUTBACK;
855              
856 6           count = call_sv(*func, G_SCALAR | G_EVAL);
857              
858 6           SPAGAIN;
859              
860 6 50         if (count == 0) {
861 0           croak("external entity handler did not return a value");
862             }
863              
864 6 50         if (SvTRUE(ERRSV)) {
    50          
    50          
    50          
    0          
    50          
    50          
    0          
    0          
    0          
    0          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    50          
865 0           (void) POPs;
866 0           croak_obj;
867             }
868              
869 6           results = POPs;
870              
871 6 50         results_pv = SvPV(results, results_len);
872 6           input_buf = xmlParserInputBufferCreateMem(
873             results_pv,
874             results_len,
875             XML_CHAR_ENCODING_NONE
876             );
877              
878 6           PUTBACK;
879 6 50         FREETMPS;
880 6           LEAVE;
881              
882 6           return xmlNewIOInputStream(ctxt, input_buf, XML_CHAR_ENCODING_NONE);
883             }
884             else {
885 0 0         if (URL == NULL) {
886 0           return NULL;
887             }
888 6           return xmlNewInputFromFile(ctxt, URL);
889             }
890             }
891              
892             /* ****************************************************************
893             * Helper functions
894             * **************************************************************** */
895              
896             HV*
897 1005           LibXML_init_parser( SV * self, xmlParserCtxtPtr ctxt ) {
898             /* we fetch all switches and callbacks from the hash */
899 1005           HV* real_obj = NULL;
900 1005           SV** item = NULL;
901 1005           int parserOptions = XML_PARSE_NODICT;
902              
903             /* A NOTE ABOUT xmlInitParser(); */
904             /* xmlInitParser() should be used only at startup and*/
905             /* not for initializing a single parser. libxml2's */
906             /* documentation is quite clear about this. If */
907             /* something fails it is a problem elsewhere. Simply */
908             /* resetting the entire module will lead to unwanted */
909             /* results in server environments, such as if */
910             /* mod_perl is used together with php's xml module. */
911             /* calling xmlInitParser() here is definitely wrong! */
912             /* xmlInitParser(); */
913              
914             #ifndef WITH_SERRORS
915             xmlGetWarningsDefaultValue = 0;
916             #endif
917 1005 50         if ( self != NULL ) {
918             /* first fetch the values from the hash */
919 1005           real_obj = (HV *)SvRV(self);
920              
921 1005           item = hv_fetch( real_obj, "XML_LIBXML_PARSER_OPTIONS", 25, 0 );
922 1005 50         if (item != NULL && SvOK(*item)) parserOptions = sv_2iv(*item);
    50          
    0          
    0          
923              
924             /* compatibility with old implementation:
925             absence of XML_PARSE_DTDLOAD (load_ext_dtd) implies absence of
926             all DTD related flags
927             */
928 1005 100         if ((parserOptions & XML_PARSE_DTDLOAD) == 0) {
929 877           parserOptions &= ~(XML_PARSE_DTDVALID | XML_PARSE_DTDATTR | XML_PARSE_NOENT );
930             }
931 1005 100         if (ctxt) xmlCtxtUseOptions(ctxt, parserOptions ); /* Note: sets ctxt->linenumbers = 1 */
932              
933             /*
934             * Without this if/else conditional, NOBLANKS has no effect.
935             *
936             * For more information, see:
937             *
938             * https://rt.cpan.org/Ticket/Display.html?id=76696
939             *
940             * */
941 1005 100         if (parserOptions & XML_PARSE_NOBLANKS) {
942 61           xmlKeepBlanksDefault(0);
943             }
944             else {
945 944           xmlKeepBlanksDefault(1);
946             }
947              
948 1005           item = hv_fetch( real_obj, "XML_LIBXML_LINENUMBERS", 22, 0 );
949 1005 100         if ( item != NULL && SvTRUE(*item) ) {
    50          
    50          
    0          
    100          
    50          
    50          
    50          
    0          
    0          
    0          
    0          
    0          
    50          
    50          
    100          
    50          
    0          
    100          
    0          
950 2 50         if (ctxt) ctxt->linenumbers = 1;
951             }
952             else {
953 1003 100         if (ctxt) ctxt->linenumbers = 0;
954             }
955              
956 1005 100         if(EXTERNAL_ENTITY_LOADER_FUNC == NULL)
957             {
958 1004           item = hv_fetch(real_obj, "ext_ent_handler", 15, 0);
959 1004 100         if (item != NULL && SvTRUE(*item)) {
    50          
    50          
    0          
    100          
    50          
    50          
    50          
    0          
    0          
    0          
    0          
    0          
    50          
    0          
    0          
    0          
    0          
    0          
    50          
960 3           LibXML_old_ext_ent_loader = xmlGetExternalEntityLoader();
961 3           xmlSetExternalEntityLoader( (xmlExternalEntityLoader)LibXML_load_external_entity );
962             }
963             else
964             {
965 1001 100         if (parserOptions & XML_PARSE_NONET)
966             {
967 1           LibXML_old_ext_ent_loader = xmlGetExternalEntityLoader();
968 1           xmlSetExternalEntityLoader( xmlNoNetExternalEntityLoader );
969             }
970             /* LibXML_old_ext_ent_loader = NULL; */
971             }
972             }
973             }
974              
975 1005           return real_obj;
976             }
977              
978             void
979 1003           LibXML_cleanup_parser() {
980             #ifndef WITH_SERRORS
981             xmlGetWarningsDefaultValue = 0;
982             #endif
983 1003 100         if (EXTERNAL_ENTITY_LOADER_FUNC == NULL && LibXML_old_ext_ent_loader != NULL)
    100          
984             {
985 4           xmlSetExternalEntityLoader( (xmlExternalEntityLoader)LibXML_old_ext_ent_loader );
986             }
987 1003           }
988              
989             int
990 210           LibXML_test_node_name( xmlChar * name )
991             {
992 210           xmlChar * cur = name;
993 210           int tc = 0;
994 210           int len = 0;
995              
996 210 50         if ( cur == NULL || *cur == 0 ) {
    50          
997             /* warn("name is empty" ); */
998 0           return(0);
999             }
1000              
1001 210           tc = domParseChar( cur, &len );
1002              
1003 210 50         if ( !( IS_LETTER( tc ) || (tc == '_') || (tc == ':')) ) {
    100          
    100          
    100          
    100          
    100          
    50          
    50          
    0          
    50          
    100          
    50          
    0          
    0          
    0          
    0          
    0          
    50          
    50          
1004             /* warn( "is not a letter\n" ); */
1005 26           return(0);
1006             }
1007              
1008 184           tc = 0;
1009 184           cur += len;
1010              
1011 866 100         while (*cur != 0 ) {
1012 682           tc = domParseChar( cur, &len );
1013              
1014 682 50         if (!(IS_LETTER(tc) || IS_DIGIT(tc) || (tc == '_') ||
    100          
    100          
    100          
    100          
    100          
    50          
    100          
    50          
    50          
    100          
    50          
    0          
    0          
    0          
    0          
    0          
    50          
    100          
    100          
    100          
    50          
    100          
    0          
1015 55 50         (tc == '-') || (tc == ':') || (tc == '.') ||
    0          
1016 0 0         IS_COMBINING(tc) || IS_EXTENDER(tc)) ) {
1017             /* warn( "is not a letter\n" ); */
1018 0           return(0);
1019             }
1020 682           tc = 0;
1021 682           cur += len;
1022             }
1023              
1024             /* warn("name is ok"); */
1025 210           return(1);
1026             }
1027              
1028             /* Assumes that the node has a proxy. */
1029             static void
1030 35           LibXML_reparent_removed_node(xmlNodePtr node) {
1031             /*
1032             * Attribute nodes can't be added to document fragments. Adding
1033             * DTD nodes would cause a memory leak.
1034             */
1035 35 100         if (node->type != XML_ATTRIBUTE_NODE
1036 33 100         && node->type != XML_DTD_NODE) {
1037 28           ProxyNodePtr docfrag = PmmNewFragment(node->doc);
1038 28           xmlAddChild(PmmNODE(docfrag), node);
1039 28           PmmFixOwner(PmmPROXYNODE(node), docfrag);
1040             }
1041 35           }
1042              
1043             static void
1044 12           LibXML_set_int_subset(xmlDocPtr doc, xmlNodePtr dtd) {
1045 12           xmlNodePtr old_dtd = (xmlNodePtr)doc->intSubset;
1046 12 50         if (old_dtd == dtd) {
1047 0           return;
1048             }
1049              
1050 12 50         if (old_dtd != NULL) {
1051 12           xmlUnlinkNode(old_dtd);
1052              
1053 12 100         if (PmmPROXYNODE(old_dtd) == NULL) {
1054 6           xmlFreeDtd((xmlDtdPtr)old_dtd);
1055             }
1056             }
1057              
1058 12           doc->intSubset = (xmlDtdPtr)dtd;
1059             }
1060              
1061             /* ****************************************************************
1062             * XPathContext helper functions
1063             * **************************************************************** */
1064              
1065             /* Temporary node pool: *
1066             * Stores pnode in context node-pool hash table in order to preserve *
1067             * at least one reference. *
1068             * If pnode is NULL, only return current value for hashkey */
1069             static SV*
1070 6045           LibXML_XPathContext_pool ( xmlXPathContextPtr ctxt, void * hashkey, SV * pnode ) {
1071             SV ** value;
1072             SV * key;
1073             STRLEN len;
1074             char * strkey;
1075             dTHX;
1076              
1077 6045 100         if (XPathContextDATA(ctxt)->pool == NULL) {
1078 20 50         if (pnode == NULL) {
1079 0           return &PL_sv_undef;
1080             } else {
1081             xs_warn("initializing node pool");
1082 20           XPathContextDATA(ctxt)->pool = newHV();
1083             }
1084             }
1085              
1086 6045           key = newSViv(PTR2IV(hashkey));
1087 6045 50         strkey = SvPV(key, len);
1088 6045 50         if (pnode != NULL && !hv_exists(XPathContextDATA(ctxt)->pool,strkey,len)) {
    100          
1089 6043           value = hv_store(XPathContextDATA(ctxt)->pool,strkey,len, SvREFCNT_inc(pnode),0);
1090             } else {
1091 2           value = hv_fetch(XPathContextDATA(ctxt)->pool,strkey,len, 0);
1092             }
1093 6045           SvREFCNT_dec(key);
1094              
1095 6045 50         if (value == NULL) {
1096 0           return &PL_sv_undef;
1097             } else {
1098 6045           return *value;
1099             }
1100             }
1101              
1102             /* convert perl result structures to LibXML structures */
1103             static xmlXPathObjectPtr
1104 52           LibXML_perldata_to_LibXMLdata(xmlXPathParserContextPtr ctxt,
1105             SV* perl_result) {
1106             dTHX;
1107              
1108 52 50         if (!SvOK(perl_result)) {
    0          
    0          
1109 0           return (xmlXPathObjectPtr)xmlXPathNewCString("");
1110             }
1111 52 100         if (SvROK(perl_result) &&
    100          
1112 40           SvTYPE(SvRV(perl_result)) == SVt_PVAV) {
1113             /* consider any array ref to be a nodelist */
1114             int i;
1115             int length;
1116             SV ** pnode;
1117             AV * array_result;
1118             xmlXPathObjectPtr ret;
1119              
1120 27           ret = (xmlXPathObjectPtr) xmlXPathNewNodeSet(INT2PTR(xmlNodePtr,NULL));
1121 27           array_result = (AV*)SvRV(perl_result);
1122 27           length = av_len(array_result);
1123 9083 100         for( i = 0; i <= length ; i++ ) {
1124 9056           pnode = av_fetch(array_result,i,0);
1125 18112 50         if (pnode != NULL && sv_isobject(*pnode) &&
1126 9056           sv_derived_from(*pnode,"XML::LibXML::Node")) {
1127 9056           xmlXPathNodeSetAdd(ret->nodesetval,
1128 9056           INT2PTR(xmlNodePtr,PmmSvNode(*pnode)));
1129 15099 100         if(ctxt) {
1130 6043           LibXML_XPathContext_pool(ctxt->context,
1131 6043           PmmSvNode(*pnode), *pnode);
1132             }
1133             } else {
1134 0           warn("XPathContext: ignoring non-node member of a nodelist");
1135             }
1136             }
1137 27           return ret;
1138 25 100         } else if (sv_isobject(perl_result) &&
    50          
1139 13           (SvTYPE(SvRV(perl_result)) == SVt_PVMG))
1140             {
1141 13 100         if (sv_derived_from(perl_result, "XML::LibXML::Node")) {
1142             xmlNodePtr tmp_node;
1143             xmlXPathObjectPtr ret;
1144              
1145 11           ret = INT2PTR(xmlXPathObjectPtr,xmlXPathNewNodeSet(NULL));
1146 11           tmp_node = INT2PTR(xmlNodePtr,PmmSvNode(perl_result));
1147 11           xmlXPathNodeSetAdd(ret->nodesetval,tmp_node);
1148 11 100         if(ctxt) {
1149 2           LibXML_XPathContext_pool(ctxt->context, PmmSvNode(perl_result),
1150             perl_result);
1151             }
1152              
1153 11           return ret;
1154             }
1155 2 50         else if (sv_isa(perl_result, "XML::LibXML::Boolean")) {
1156 0           return (xmlXPathObjectPtr)
1157 0 0         xmlXPathNewBoolean(SvIV(SvRV(perl_result)));
1158             }
1159 2 100         else if (sv_isa(perl_result, "XML::LibXML::Literal")) {
1160 1           return (xmlXPathObjectPtr)
1161 1 50         xmlXPathNewCString(SvPV_nolen(SvRV(perl_result)));
1162             }
1163 1 50         else if (sv_isa(perl_result, "XML::LibXML::Number")) {
1164 1           return (xmlXPathObjectPtr)
1165 1 50         xmlXPathNewFloat(SvNV(SvRV(perl_result)));
1166             }
1167 12 100         } else if (SvNOK(perl_result) || SvIOK(perl_result)) {
    50          
1168 3 50         return (xmlXPathObjectPtr)xmlXPathNewFloat(SvNV(perl_result));
1169             } else {
1170 9           return (xmlXPathObjectPtr)
1171 9 50         xmlXPathNewCString(SvPV_nolen(perl_result));
1172             }
1173 0           return NULL;
1174             }
1175              
1176              
1177             /* save XPath context and XPathContextDATA for recursion */
1178             static xmlXPathContextPtr
1179 53           LibXML_save_context(xmlXPathContextPtr ctxt)
1180             {
1181             xmlXPathContextPtr copy;
1182 53           copy = xmlMalloc(sizeof(xmlXPathContext));
1183 53 50         if (copy) {
1184             /* backup ctxt */
1185 53           memcpy(copy, ctxt, sizeof(xmlXPathContext));
1186             /* clear namespaces so that they are not freed and overwritten
1187             by configure_namespaces */
1188 53           ctxt->namespaces = NULL;
1189             /* backup data */
1190 53           copy->user = xmlMalloc(sizeof(XPathContextData));
1191 53 50         if (XPathContextDATA(copy)) {
1192 53           memcpy(XPathContextDATA(copy), XPathContextDATA(ctxt),sizeof(XPathContextData));
1193             /* clear ctxt->pool, so that it is not used freed during re-entrance */
1194 53           XPathContextDATA(ctxt)->pool = NULL;
1195             }
1196             }
1197 53           return copy;
1198             }
1199              
1200             /* restore XPath context and XPathContextDATA from a saved copy */
1201             static void
1202 53           LibXML_restore_context(xmlXPathContextPtr ctxt, xmlXPathContextPtr copy)
1203             {
1204             dTHX;
1205             /* cleanup */
1206 53 50         if (XPathContextDATA(ctxt)) {
1207             /* cleanup newly created pool */
1208 53 50         if (XPathContextDATA(ctxt)->pool != NULL &&
    0          
1209 0 0         SvOK(XPathContextDATA(ctxt)->pool)) {
    0          
1210 0           SvREFCNT_dec((SV *)XPathContextDATA(ctxt)->pool);
1211             }
1212             }
1213 53 50         if (ctxt->namespaces) {
1214             /* free namespaces allocated during recursion */
1215 0           xmlFree( ctxt->namespaces );
1216             }
1217              
1218             /* restore context */
1219 53 50         if (copy) {
1220             /* 1st restore our data */
1221 53 50         if (XPathContextDATA(copy)) {
1222 53           memcpy(XPathContextDATA(ctxt),XPathContextDATA(copy),sizeof(XPathContextData));
1223 53           xmlFree(XPathContextDATA(copy));
1224 53           copy->user = XPathContextDATA(ctxt);
1225             }
1226             /* now copy the rest */
1227 53           memcpy(ctxt, copy, sizeof(xmlXPathContext));
1228 53           xmlFree(copy);
1229             }
1230 53           }
1231              
1232              
1233             /* ****************************************************************
1234             * Variable Lookup
1235             * **************************************************************** */
1236             /* Much of the code is borrowed from Matt Sergeant's XML::LibXSLT */
1237             static xmlXPathObjectPtr
1238 21           LibXML_generic_variable_lookup(void* varLookupData,
1239             const xmlChar *name,
1240             const xmlChar *ns_uri)
1241             {
1242             xmlXPathObjectPtr ret;
1243             xmlXPathContextPtr ctxt;
1244             xmlXPathContextPtr copy;
1245             XPathContextDataPtr data;
1246             I32 count;
1247             dTHX;
1248 21           dSP;
1249              
1250 21           ctxt = (xmlXPathContextPtr) varLookupData;
1251 21 50         if ( ctxt == NULL )
1252 0           croak("XPathContext: missing xpath context");
1253 21           data = XPathContextDATA(ctxt);
1254 21 50         if ( data == NULL )
1255 0           croak("XPathContext: missing xpath context private data");
1256 21 50         if ( data->varLookup == NULL || !SvROK(data->varLookup) ||
    50          
    50          
1257 21           SvTYPE(SvRV(data->varLookup)) != SVt_PVCV )
1258 0           croak("XPathContext: lost variable lookup function!");
1259              
1260 21           ENTER;
1261 21           SAVETMPS;
1262 21 50         PUSHMARK(SP);
1263              
1264 21 50         XPUSHs( (data->varData != NULL) ? data->varData : &PL_sv_undef );
    100          
1265 21 50         XPUSHs(sv_2mortal(C2Sv(name,NULL)));
1266 21 50         XPUSHs(sv_2mortal(C2Sv(ns_uri,NULL)));
1267              
1268             /* save context to allow recursive usage of XPathContext */
1269 21           copy = LibXML_save_context(ctxt);
1270              
1271 21           PUTBACK ;
1272 21           count = call_sv(data->varLookup, G_SCALAR|G_EVAL);
1273 21           SPAGAIN;
1274              
1275             /* restore the xpath context */
1276 21           LibXML_restore_context(ctxt, copy);
1277              
1278 21 50         if (SvTRUE(ERRSV)) {
    50          
    50          
    50          
    0          
    50          
    50          
    0          
    0          
    0          
    0          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    50          
1279 0           (void) POPs;
1280 0           croak_obj;
1281             }
1282 21 50         if (count != 1) croak("XPathContext: variable lookup function returned none or more than one argument!");
1283              
1284 21           ret = LibXML_perldata_to_LibXMLdata(NULL, POPs);
1285              
1286 21           PUTBACK;
1287 21 50         FREETMPS;
1288 21           LEAVE;
1289 21           return ret;
1290             }
1291              
1292             /* ****************************************************************
1293             * Generic Extension Function
1294             * **************************************************************** */
1295             /* Much of the code is borrowed from Matt Sergeant's XML::LibXSLT */
1296             static void
1297 32           LibXML_generic_extension_function(xmlXPathParserContextPtr ctxt, int nargs)
1298             {
1299             xmlXPathObjectPtr obj,ret;
1300 32           xmlNodeSetPtr nodelist = NULL;
1301             int count;
1302             SV * perl_dispatch;
1303             int i;
1304             STRLEN len;
1305 32           ProxyNodePtr owner = NULL;
1306             SV *key;
1307             char *strkey;
1308             const char *function, *uri;
1309             SV **perl_function;
1310             dTHX;
1311 32           dSP;
1312             SV * data;
1313             xmlXPathContextPtr copy;
1314              
1315             /* warn("entered LibXML_generic_extension_function for %s\n",ctxt->context->function); */
1316 32           data = (SV *) ctxt->context->funcLookupData;
1317 32 50         if (ctxt->context->funcLookupData == NULL || !SvROK(data) ||
    50          
    50          
1318 32           SvTYPE(SvRV(data)) != SVt_PVHV) {
1319 0           croak("XPathContext: lost function lookup data structure!");
1320             }
1321              
1322 32           function = (char*) ctxt->context->function;
1323 32           uri = (char*) ctxt->context->functionURI;
1324              
1325 32           key = newSVpvn("",0);
1326 32 100         if (uri && *uri) {
    50          
1327 8           sv_catpv(key, "{");
1328 8           sv_catpv(key, (const char*)uri);
1329 8           sv_catpv(key, "}");
1330             }
1331 32           sv_catpv(key, (const char*)function);
1332 32 50         strkey = SvPV(key, len);
1333 32           perl_function =
1334 32           hv_fetch((HV*)SvRV(data), strkey, len, 0);
1335 32 50         if ( perl_function == NULL || !SvOK(*perl_function) ||
    50          
    0          
    0          
    100          
1336 31 50         !(SvPOK(*perl_function) ||
1337 31 50         (SvROK(*perl_function) &&
1338 31           SvTYPE(SvRV(*perl_function)) == SVt_PVCV))) {
1339 0           croak("XPathContext: lost perl extension function!");
1340             }
1341 32           SvREFCNT_dec(key);
1342              
1343 32           ENTER;
1344 32           SAVETMPS;
1345 32 50         PUSHMARK(SP);
1346              
1347 32 50         XPUSHs(*perl_function);
1348              
1349             /* set up call to perl dispatcher function */
1350 55 100         for (i = 0; i < nargs; i++) {
1351 23           obj = (xmlXPathObjectPtr)valuePop(ctxt);
1352 23           switch (obj->type) {
1353             case XPATH_XSLT_TREE:
1354             case XPATH_NODESET:
1355 11           nodelist = obj->nodesetval;
1356 11 50         if ( nodelist ) {
1357 11 50         XPUSHs(sv_2mortal(newSVpv("XML::LibXML::NodeList", 0)));
1358 11 50         XPUSHs(sv_2mortal(newSViv(nodelist->nodeNr)));
1359 11 100         if ( nodelist->nodeNr > 0 ) {
1360             int j;
1361 10           const char * cls = "XML::LibXML::Node";
1362             xmlNodePtr tnode;
1363             SV * element;
1364 10           int l = nodelist->nodeNr;
1365              
1366 3034 100         for( j = 0 ; j < l; j++){
1367 3023           tnode = nodelist->nodeTab[j];
1368 3023 50         if( tnode != NULL && tnode->doc != NULL) {
    50          
1369 3023 50         owner = PmmOWNERPO(PmmNewNode(INT2PTR(xmlNodePtr,tnode->doc)));
    50          
1370             } else {
1371 0           owner = NULL;
1372             }
1373 3023 50         if (tnode->type == XML_NAMESPACE_DECL) {
1374 0           element = NEWSV(0,0);
1375 0           cls = PmmNodeTypeName( tnode );
1376 0           element = sv_setref_pv( element,
1377             (const char *)cls,
1378             (void *)xmlCopyNamespace((xmlNsPtr)tnode)
1379             );
1380             }
1381             else {
1382 3023           element = PmmNodeToSv(tnode, owner);
1383             }
1384 3023 50         XPUSHs( sv_2mortal(element) );
1385             }
1386             }
1387             } else {
1388             /* PP: We can't simply leave out an empty nodelist as Matt does! */
1389             /* PP: The number of arguments must match! */
1390 0 0         XPUSHs(sv_2mortal(newSVpv("XML::LibXML::NodeList", 0)));
1391 0 0         XPUSHs(sv_2mortal(newSViv(0)));
1392             }
1393             /* prevent libxml2 from freeing the actual nodes */
1394 11 50         if (obj->boolval) obj->boolval=0;
1395 11           break;
1396             case XPATH_BOOLEAN:
1397 0 0         XPUSHs(sv_2mortal(newSVpv("XML::LibXML::Boolean", 0)));
1398 0 0         XPUSHs(sv_2mortal(newSViv(obj->boolval)));
1399 0           break;
1400             case XPATH_NUMBER:
1401 4 50         XPUSHs(sv_2mortal(newSVpv("XML::LibXML::Number", 0)));
1402 4 50         XPUSHs(sv_2mortal(newSVnv(obj->floatval)));
1403 4           break;
1404             case XPATH_STRING:
1405 8 50         XPUSHs(sv_2mortal(newSVpv("XML::LibXML::Literal", 0)));
1406 8 50         XPUSHs(sv_2mortal(C2Sv(obj->stringval, 0)));
1407 8           break;
1408             default:
1409 0           warn("Unknown XPath return type (%d) in call to {%s}%s - assuming string", obj->type, uri, function);
1410 0 0         XPUSHs(sv_2mortal(newSVpv("XML::LibXML::Literal", 0)));
1411 0 0         XPUSHs(sv_2mortal(C2Sv(xmlXPathCastToString(obj), 0)));
1412             }
1413 23           xmlXPathFreeObject(obj);
1414             }
1415              
1416             /* save context to allow recursive usage of XPathContext */
1417 32           copy = LibXML_save_context(ctxt->context);
1418              
1419             /* call perl dispatcher */
1420 32           PUTBACK;
1421 32           perl_dispatch = sv_2mortal(newSVpv("XML::LibXML::XPathContext::_perl_dispatcher",0));
1422 32           count = call_sv(perl_dispatch, G_SCALAR|G_EVAL);
1423 32           SPAGAIN;
1424              
1425             /* restore the xpath context */
1426 32           LibXML_restore_context(ctxt->context, copy);
1427              
1428 32 50         if (SvTRUE(ERRSV)) {
    50          
    50          
    50          
    0          
    50          
    50          
    0          
    0          
    0          
    0          
    50          
    50          
    50          
    50          
    50          
    100          
    50          
    50          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    100          
1429 1           (void) POPs;
1430 1           croak_obj;
1431             }
1432              
1433 31 50         if (count != 1) croak("XPathContext: perl-dispatcher in pm file returned none or more than one argument!");
1434              
1435 31           ret = LibXML_perldata_to_LibXMLdata(ctxt, POPs);
1436              
1437 31           valuePush(ctxt, ret);
1438 31           PUTBACK;
1439 31 50         FREETMPS;
1440 31           LEAVE;
1441 31           }
1442              
1443             static void
1444 176           LibXML_configure_namespaces( xmlXPathContextPtr ctxt ) {
1445 176           xmlNodePtr node = ctxt->node;
1446              
1447 176 100         if (ctxt->namespaces != NULL) {
1448 28           xmlFree( ctxt->namespaces );
1449 28           ctxt->namespaces = NULL;
1450             }
1451 176 100         if (node != NULL) {
1452 168 100         if (node->type == XML_DOCUMENT_NODE) {
1453 132           ctxt->namespaces = xmlGetNsList( node->doc,
1454 132           xmlDocGetRootElement( node->doc ) );
1455             } else {
1456 36           ctxt->namespaces = xmlGetNsList(node->doc, node);
1457             }
1458 168           ctxt->nsNr = 0;
1459 168 100         if (ctxt->namespaces != NULL) {
1460 45           int cur=0;
1461             xmlNsPtr ns;
1462             /* we now walk through the list and
1463             drop every ns that was declared via registration */
1464 173 100         while (ctxt->namespaces[cur] != NULL) {
1465 128           ns = ctxt->namespaces[cur];
1466 233           if (ns->prefix==NULL ||
1467 105           xmlHashLookup(ctxt->nsHash, ns->prefix) != NULL) {
1468             /* drop it */
1469 35           ctxt->namespaces[cur]=NULL;
1470             } else {
1471 93 100         if (cur != ctxt->nsNr) {
1472             /* move the item to the new tail */
1473 10           ctxt->namespaces[ctxt->nsNr]=ns;
1474 10           ctxt->namespaces[cur]=NULL;
1475             }
1476 93           ctxt->nsNr++;
1477             }
1478 128           cur++;
1479             }
1480             }
1481             }
1482 176           }
1483              
1484             static void
1485 162           LibXML_configure_xpathcontext( xmlXPathContextPtr ctxt ) {
1486 162           xmlNodePtr node = PmmSvNode(XPathContextDATA(ctxt)->node);
1487              
1488 162 100         if (node != NULL) {
1489 154           ctxt->doc = node->doc;
1490             } else {
1491 8           ctxt->doc = NULL;
1492             }
1493 162           ctxt->node = node;
1494 162           LibXML_configure_namespaces(ctxt);
1495 162           }
1496              
1497             #ifdef HAVE_READER_SUPPORT
1498              
1499             static void
1500 6           LibXML_set_reader_preserve_flag( xmlTextReaderPtr reader ) {
1501             HV *hash;
1502             char key[32];
1503              
1504 6           hash = get_hv("XML::LibXML::Reader::_preserve_flag", 0);
1505 6 50         if (!hash) {
1506 0           return;
1507             }
1508              
1509 6           (void) snprintf(key, sizeof(key), "%p", reader);
1510 6           (void) hv_store(hash, key, strlen(key), newSV(0), 0);
1511             }
1512              
1513             static int
1514 20           LibXML_get_reader_preserve_flag( xmlTextReaderPtr reader ) {
1515             HV *hash;
1516             char key[32];
1517              
1518 20           hash = get_hv("XML::LibXML::Reader::_preserve_flag", 0);
1519 20 50         if (!hash) {
1520 0           return 0;
1521             }
1522              
1523 20           (void) snprintf(key, sizeof(key), "%p", reader);
1524 20 100         if ( hv_exists(hash, key, strlen(key)) ) {
1525 2           (void) hv_delete(hash, key, strlen(key), G_DISCARD);
1526 2           return 1;
1527             }
1528              
1529 20           return 0;
1530             }
1531              
1532             #endif /* HAVE_READER_SUPPORT */
1533              
1534             extern void boot_XML__LibXML__Devel(pTHX_ CV*);
1535              
1536             MODULE = XML::LibXML PACKAGE = XML::LibXML
1537              
1538             PROTOTYPES: DISABLE
1539              
1540             BOOT:
1541             /* Load Devel first, so debug_memory can
1542             be called before any allocation. */
1543              
1544             /* The ++ is a bit hacky, but boot_blahblah_Devel, being an
1545             * XSUB body, will try to pop once more the mark we have just
1546             * (implicitly) popped, this boot sector also being an XSUB body */
1547 67           PL_markstack_ptr++;
1548 67           boot_XML__LibXML__Devel(aTHX_ cv);
1549 67           LIBXML_TEST_VERSION
1550 67           xmlInitParser();
1551 67           PmmSAXInitialize(aTHX);
1552             #ifndef WITH_SERRORS
1553             xmlGetWarningsDefaultValue = 0;
1554             #endif
1555             #ifdef LIBXML_CATALOG_ENABLED
1556             /* xmlCatalogSetDebug(10); */
1557 67           xmlInitializeCatalog(); /* use catalog data */
1558             #endif
1559              
1560              
1561             void
1562             _CLONE( class )
1563             CODE:
1564             #ifdef XML_LIBXML_THREADS
1565             if( PmmUSEREGISTRY )
1566             PmmCloneProxyNodes();
1567             #endif
1568              
1569             int
1570             _leaked_nodes()
1571             CODE:
1572 1           RETVAL = 0;
1573             #ifdef XML_LIBXML_THREADS
1574             if( PmmUSEREGISTRY )
1575             RETVAL = PmmProxyNodeRegistrySize();
1576             #endif
1577             OUTPUT:
1578             RETVAL
1579              
1580             void
1581             _dump_registry()
1582             PPCODE:
1583             #ifdef XML_LIBXML_THREADS
1584             if( PmmUSEREGISTRY )
1585             PmmDumpRegistry(PmmREGISTRY);
1586             #endif
1587              
1588             const char *
1589             LIBXML_DOTTED_VERSION()
1590             CODE:
1591 1           RETVAL = LIBXML_DOTTED_VERSION;
1592             OUTPUT:
1593             RETVAL
1594              
1595              
1596             int
1597             LIBXML_VERSION()
1598             CODE:
1599 83           RETVAL = LIBXML_VERSION;
1600             OUTPUT:
1601             RETVAL
1602              
1603             int
1604             HAVE_STRUCT_ERRORS()
1605             CODE:
1606             #ifdef WITH_SERRORS
1607 2           RETVAL = 1;
1608             #else
1609             RETVAL = 0;
1610             #endif
1611             OUTPUT:
1612             RETVAL
1613              
1614             int
1615             HAVE_SCHEMAS()
1616             CODE:
1617             #ifdef HAVE_SCHEMAS
1618 1           RETVAL = 1;
1619             # if LIBXML_VERSION == 20904
1620             /* exists but broken https://github.com/shlomif/libxml2-2.9.4-reader-schema-regression */
1621             RETVAL = 0;
1622             # endif
1623             #else
1624             RETVAL = 0;
1625             #endif
1626             OUTPUT:
1627             RETVAL
1628              
1629             int
1630             HAVE_READER()
1631             CODE:
1632             #ifdef HAVE_READER_SUPPORT
1633 2           RETVAL = 1;
1634             #else
1635             RETVAL = 0;
1636             #endif
1637             OUTPUT:
1638             RETVAL
1639              
1640             int
1641             HAVE_THREAD_SUPPORT()
1642             CODE:
1643             #ifdef XML_LIBXML_THREADS
1644             RETVAL = (PmmUSEREGISTRY ? 1 : 0);
1645             #else
1646 0           RETVAL = 0;
1647             #endif
1648             OUTPUT:
1649             RETVAL
1650              
1651              
1652             const char *
1653             LIBXML_RUNTIME_VERSION()
1654             CODE:
1655 71           RETVAL = xmlParserVersion;
1656             OUTPUT:
1657             RETVAL
1658              
1659             void
1660             END()
1661             CODE:
1662 67           xmlCleanupParser();
1663              
1664             int
1665             INIT_THREAD_SUPPORT()
1666             CODE:
1667             #ifdef XML_LIBXML_THREADS
1668             SV *threads = get_sv("threads::threads", 0); /* no create */
1669             if( threads && SvOK(threads) && SvTRUE(threads) ) {
1670             PROXY_NODE_REGISTRY_MUTEX = get_sv("XML::LibXML::__PROXY_NODE_REGISTRY_MUTEX",0);
1671             RETVAL = 1;
1672             } else {
1673             croak("XML::LibXML ':threads_shared' can only be used after 'use threads'");
1674             }
1675             #else
1676 0           RETVAL = 0;
1677             #endif
1678             OUTPUT:
1679             RETVAL
1680              
1681             void
1682             DISABLE_THREAD_SUPPORT()
1683             CODE:
1684             #ifdef XML_LIBXML_THREADS
1685             PROXY_NODE_REGISTRY_MUTEX = NULL;
1686             #else
1687 0           croak("XML::LibXML compiled without threads!");
1688             #endif
1689              
1690             SV*
1691             _parse_string(self, string, dir = &PL_sv_undef)
1692             SV * self
1693             SV * string
1694             SV * dir
1695             PREINIT:
1696 323           char * directory = NULL;
1697             STRLEN len;
1698             const char * ptr;
1699             HV * real_obj;
1700             int well_formed;
1701             int valid;
1702             int validate;
1703             xmlDocPtr real_doc;
1704 323           int recover = 0;
1705 323           PREINIT_SAVED_ERROR
1706             INIT:
1707 323 100         if (SvPOK(dir)) {
1708 1 50         directory = SvPV(dir, len);
1709 1 50         if (len <= 0) {
1710 0           directory = NULL;
1711             }
1712             }
1713             /* If string is a reference to a string - dereference it.
1714             * See: https://rt.cpan.org/Ticket/Display.html?id=64051 (broke it)
1715             * https://rt.cpan.org/Ticket/Display.html?id=77864 (fixed it) */
1716 323 100         if (SvROK(string) && !SvOBJECT(SvRV(string))) {
    100          
1717 2           string = SvRV(string);
1718             }
1719 323 100         ptr = SvPV_const(string, len);
1720 323 50         if (len <= 0) {
1721 0           croak("Empty string\n");
1722             XSRETURN_UNDEF;
1723             }
1724             CODE:
1725 323           RETVAL = &PL_sv_undef;
1726 323           INIT_ERROR_HANDLER;
1727             {
1728 323           xmlParserCtxtPtr ctxt = xmlCreateMemoryParserCtxt(ptr, len);
1729 323 50         if (ctxt == NULL) {
1730 0           CLEANUP_ERROR_HANDLER;
1731 0           REPORT_ERROR(1);
1732 0           croak("Could not create memory parser context!\n");
1733             }
1734             xs_warn( "context created\n");
1735 323           real_obj = LibXML_init_parser(self, ctxt);
1736 323           recover = LibXML_get_recover(real_obj);
1737              
1738              
1739 323 100         if ( directory != NULL ) {
1740 1           ctxt->directory = directory;
1741             }
1742 323           ctxt->_private = (void*)self;
1743              
1744             /* make libxml2-2.6 display line number on error */
1745 323 50         if ( ctxt->input != NULL ) {
1746 323 100         if (directory != NULL) {
1747 1           ctxt->input->filename = (char *) xmlStrdup((const xmlChar *) directory);
1748             } else {
1749 322           ctxt->input->filename = (char *) xmlStrdup((const xmlChar *) "");
1750             }
1751             }
1752              
1753             xs_warn( "context initialized\n" );
1754              
1755 323           xmlParseDocument(ctxt);
1756             xs_warn( "document parsed \n");
1757              
1758 323           ctxt->directory = NULL;
1759 323           well_formed = ctxt->wellFormed;
1760 323           valid = ctxt->valid;
1761 323           validate = ctxt->validate;
1762 323           real_doc = ctxt->myDoc;
1763 323           ctxt->myDoc = NULL;
1764 323           xmlFreeParserCtxt(ctxt);
1765             }
1766 323 50         if ( real_doc != NULL ) {
1767 323 50         if (real_doc->URL != NULL) { /* free "" assigned above */
1768 323           xmlFree((char*) real_doc->URL);
1769 323           real_doc->URL = NULL;
1770             }
1771              
1772 323 100         if ( directory == NULL ) {
1773 322           SV * newURI = sv_2mortal(newSVpvf("unknown-%p", (void*)real_doc));
1774 322 50         real_doc->URL = xmlStrdup((const xmlChar*)SvPV_nolen(newURI));
1775             } else {
1776 1           real_doc->URL = xmlStrdup((const xmlChar*)directory);
1777             }
1778 323 100         if ( ! LibXML_will_die_ctx(saved_error, recover) &&
    100          
1779 244 50         (recover || ( well_formed &&
    50          
1780             ( !validate
1781 0 0         || ( valid || ( real_doc->intSubset == NULL
    0          
1782 0 0         && real_doc->extSubset == NULL )))))) {
1783 245           RETVAL = LibXML_NodeToSv( real_obj, INT2PTR(xmlNodePtr,real_doc) );
1784             } else {
1785 78           xmlFreeDoc(real_doc);
1786 78           real_doc=NULL;
1787             }
1788             }
1789              
1790 323           LibXML_cleanup_parser();
1791 323           CLEANUP_ERROR_HANDLER;
1792 323           REPORT_ERROR(recover);
1793             OUTPUT:
1794             RETVAL
1795              
1796             int
1797             _parse_sax_string(self, string)
1798             SV * self
1799             SV * string
1800             PREINIT:
1801             STRLEN len;
1802             char * ptr;
1803             HV * real_obj;
1804 37           int recover = 0;
1805 37           PREINIT_SAVED_ERROR
1806             INIT:
1807 37 50         ptr = SvPV(string, len);
1808 37 50         if (len <= 0) {
1809 0           croak("Empty string\n");
1810             XSRETURN_UNDEF;
1811             }
1812             CODE:
1813 37           RETVAL = 0;
1814 37           INIT_ERROR_HANDLER;
1815              
1816             {
1817 37           xmlParserCtxtPtr ctxt = xmlCreateMemoryParserCtxt((const char*)ptr, len);
1818 37 50         if (ctxt == NULL) {
1819 0           CLEANUP_ERROR_HANDLER;
1820 0 0         REPORT_ERROR(recover ? recover : 1);
1821 0           croak("Could not create memory parser context!\n");
1822             }
1823             xs_warn( "context created\n");
1824 37           real_obj = LibXML_init_parser(self, ctxt);
1825 37           recover = LibXML_get_recover(real_obj);
1826              
1827 37           PmmSAXInitContext( ctxt, self, saved_error );
1828             xs_warn( "context initialized \n");
1829             {
1830 37           RETVAL = xmlParseDocument(ctxt);
1831             xs_warn( "document parsed \n");
1832             }
1833              
1834 36           PmmSAXCloseContext(ctxt);
1835 36           xmlFreeParserCtxt(ctxt);
1836             }
1837              
1838 36           LibXML_cleanup_parser();
1839 36           CLEANUP_ERROR_HANDLER;
1840 36           REPORT_ERROR(recover);
1841             OUTPUT:
1842             RETVAL
1843              
1844             SV*
1845             _parse_fh(self, fh, dir = &PL_sv_undef)
1846             SV * self
1847             SV * fh
1848             SV * dir
1849             PREINIT:
1850             STRLEN len;
1851 9           char * directory = NULL;
1852             HV * real_obj;
1853             int well_formed;
1854             int valid;
1855             int validate;
1856             xmlDocPtr real_doc;
1857 9           int recover = 0;
1858 9           PREINIT_SAVED_ERROR
1859             INIT:
1860 9 50         if (SvPOK(dir)) {
1861 0 0         directory = SvPV(dir, len);
1862 0 0         if (len <= 0) {
1863 0           directory = NULL;
1864             }
1865             }
1866             CODE:
1867 9           RETVAL = &PL_sv_undef;
1868 9           INIT_ERROR_HANDLER;
1869              
1870             {
1871             int read_length;
1872             char buffer[1024];
1873             xmlParserCtxtPtr ctxt;
1874              
1875 9           read_length = LibXML_read_perl(fh, buffer, 4);
1876 8 50         if (read_length <= 0) {
1877 0           CLEANUP_ERROR_HANDLER;
1878 0           croak( "Empty Stream\n" );
1879             }
1880              
1881 8           ctxt = xmlCreatePushParserCtxt(NULL, NULL, buffer, read_length, NULL);
1882 8 50         if (ctxt == NULL) {
1883 0           CLEANUP_ERROR_HANDLER;
1884 0           REPORT_ERROR(1);
1885 0           croak("Could not create xml push parser context!\n");
1886             }
1887             xs_warn( "context created\n");
1888 8           real_obj = LibXML_init_parser(self, ctxt);
1889 8           recover = LibXML_get_recover(real_obj);
1890             #if LIBXML_VERSION > 20600
1891             /* dictionaries not support yet */
1892 8           ctxt->dictNames = 0;
1893             #endif
1894 8 50         if ( directory != NULL ) {
1895 0           ctxt->directory = directory;
1896             }
1897 8           ctxt->_private = (void*)self;
1898             xs_warn( "context initialized \n");
1899             {
1900             int ret;
1901 14 100         while ((read_length = LibXML_read_perl(fh, buffer, 1024))) {
1902 7           ret = xmlParseChunk(ctxt, buffer, read_length, 0);
1903 7 100         if ( ret != 0 ) {
1904 1           break;
1905             }
1906             }
1907 7           ret = xmlParseChunk(ctxt, buffer, 0, 1);
1908             xs_warn( "document parsed \n");
1909             }
1910              
1911 7           ctxt->directory = NULL;
1912 7           well_formed = ctxt->wellFormed;
1913 7           valid = ctxt->valid;
1914 7           validate = ctxt->validate;
1915 7           real_doc = ctxt->myDoc;
1916 7           ctxt->myDoc = NULL;
1917 7           xmlFreeParserCtxt(ctxt);
1918             }
1919              
1920 7 50         if ( real_doc != NULL ) {
1921              
1922 7 50         if ( directory == NULL ) {
1923 7           SV * newURI = sv_2mortal(newSVpvf("unknown-%p", (void*)real_doc));
1924 7 50         real_doc->URL = xmlStrdup((const xmlChar*)SvPV_nolen(newURI));
1925             } else {
1926 0           real_doc->URL = xmlStrdup((const xmlChar*)directory);
1927             }
1928              
1929 7 100         if ( ! LibXML_will_die_ctx(saved_error, recover) &&
    50          
1930 6 50         (recover || ( well_formed &&
    50          
1931             ( !validate
1932 0 0         || ( valid || ( real_doc->intSubset == NULL
    0          
1933 0 0         && real_doc->extSubset == NULL )))))) {
1934 6           RETVAL = LibXML_NodeToSv( real_obj, INT2PTR(xmlNodePtr,real_doc) );
1935             } else {
1936 1           xmlFreeDoc(real_doc);
1937 1           real_doc=NULL;
1938             }
1939             }
1940              
1941 7           LibXML_cleanup_parser();
1942 7           CLEANUP_ERROR_HANDLER;
1943 7           REPORT_ERROR(recover);
1944             OUTPUT:
1945             RETVAL
1946              
1947             void
1948             _parse_sax_fh(self, fh, dir = &PL_sv_undef)
1949             SV * self
1950             SV * fh
1951             SV * dir
1952             PREINIT:
1953             STRLEN len;
1954 0           char * directory = NULL;
1955             HV * real_obj;
1956 0           int recover = 0;
1957 0           PREINIT_SAVED_ERROR
1958             INIT:
1959 0 0         if (SvPOK(dir)) {
1960 0 0         directory = SvPV(dir, len);
1961 0 0         if (len <= 0) {
1962 0           directory = NULL;
1963             }
1964             }
1965             CODE:
1966 0           INIT_ERROR_HANDLER;
1967             {
1968             int read_length;
1969             char buffer[1024];
1970             xmlSAXHandlerPtr sax;
1971             xmlParserCtxtPtr ctxt;
1972              
1973 0           read_length = LibXML_read_perl(fh, buffer, 4);
1974 0 0         if (read_length <= 0) {
1975 0           CLEANUP_ERROR_HANDLER;
1976 0           croak( "Empty Stream\n" );
1977             }
1978              
1979 0           sax = PSaxGetHandler();
1980 0           ctxt = xmlCreatePushParserCtxt(sax, NULL, buffer, read_length, NULL);
1981 0 0         if (ctxt == NULL) {
1982 0           CLEANUP_ERROR_HANDLER;
1983 0 0         REPORT_ERROR(recover ? recover : 1);
1984 0           croak("Could not create xml push parser context!\n");
1985             }
1986             xs_warn( "context created\n");
1987 0           real_obj = LibXML_init_parser(self, ctxt);
1988 0           recover = LibXML_get_recover(real_obj);
1989              
1990 0 0         if ( directory != NULL ) {
1991 0           ctxt->directory = directory;
1992             }
1993 0           PmmSAXInitContext( ctxt, self, saved_error );
1994             xs_warn( "context initialized \n");
1995              
1996             {
1997             int ret;
1998 0 0         while ((read_length = LibXML_read_perl(fh, buffer, 1024))) {
1999 0           ret = xmlParseChunk(ctxt, buffer, read_length, 0);
2000 0 0         if ( ret != 0 ) {
2001 0           break;
2002             }
2003             }
2004 0           ret = xmlParseChunk(ctxt, buffer, 0, 1);
2005             xs_warn( "document parsed \n");
2006             }
2007              
2008 0           ctxt->directory = NULL;
2009 0           xmlFree(ctxt->sax);
2010 0           ctxt->sax = NULL;
2011 0           xmlFree(sax);
2012 0           PmmSAXCloseContext(ctxt);
2013 0           xmlFreeParserCtxt(ctxt);
2014             }
2015 0           CLEANUP_ERROR_HANDLER;
2016 0           LibXML_cleanup_parser();
2017 0           REPORT_ERROR(recover);
2018              
2019             SV*
2020             _parse_file(self, filename_sv)
2021             SV * self
2022             SV * filename_sv
2023             PREINIT:
2024             STRLEN len;
2025             char * filename;
2026             HV * real_obj;
2027             int well_formed;
2028             int valid;
2029             int validate;
2030             xmlDocPtr real_doc;
2031 67           int recover = 0;
2032 67           PREINIT_SAVED_ERROR
2033             INIT:
2034 67 50         filename = SvPV(filename_sv, len);
2035 67 50         if (len <= 0) {
2036 0           croak("Empty filename\n");
2037             XSRETURN_UNDEF;
2038             }
2039             CODE:
2040 67           RETVAL = &PL_sv_undef;
2041 67           INIT_ERROR_HANDLER;
2042              
2043             {
2044 67           xmlParserCtxtPtr ctxt = xmlCreateFileParserCtxt(filename);
2045 67 100         if (ctxt == NULL) {
2046 1           CLEANUP_ERROR_HANDLER;
2047 1           REPORT_ERROR(1);
2048 1           croak("Could not create file parser context for file \"%s\": %s\n",
2049 1           filename, strerror(errno));
2050             }
2051             xs_warn( "context created\n");
2052 66           real_obj = LibXML_init_parser(self, ctxt);
2053 66           recover = LibXML_get_recover(real_obj);
2054              
2055 66           ctxt->_private = (void*)self;
2056              
2057             xs_warn( "context initialized\n" );
2058 66           xmlParseDocument(ctxt);
2059             xs_warn( "document parsed \n");
2060              
2061 66           well_formed = ctxt->wellFormed;
2062 66           valid = ctxt->valid;
2063 66           validate = ctxt->validate;
2064 66           real_doc = ctxt->myDoc;
2065 66           ctxt->myDoc = NULL;
2066 66           xmlFreeParserCtxt(ctxt);
2067             }
2068              
2069 66 50         if ( real_doc != NULL ) {
2070 66 100         if ( ! LibXML_will_die_ctx(saved_error, recover) &&
    50          
2071 60 50         (recover || ( well_formed &&
    50          
2072             ( !validate
2073 0 0         || ( valid || ( real_doc->intSubset == NULL
    0          
2074 0 0         && real_doc->extSubset == NULL )))))) {
2075 60           RETVAL = LibXML_NodeToSv( real_obj, INT2PTR(xmlNodePtr,real_doc) );
2076             } else {
2077 6           xmlFreeDoc(real_doc);
2078 6           real_doc=NULL;
2079             }
2080             }
2081              
2082 66           LibXML_cleanup_parser();
2083 66           CLEANUP_ERROR_HANDLER;
2084 66           REPORT_ERROR(recover);
2085             OUTPUT:
2086             RETVAL
2087              
2088             void
2089             _parse_sax_file(self, filename_sv)
2090             SV * self
2091             SV * filename_sv
2092             PREINIT:
2093             STRLEN len;
2094             char * filename;
2095             HV * real_obj;
2096 1           int recover = 0;
2097 1           PREINIT_SAVED_ERROR
2098             INIT:
2099 1 50         filename = SvPV(filename_sv, len);
2100 1 50         if (len <= 0) {
2101 0           croak("Empty filename\n");
2102             XSRETURN_UNDEF;
2103             }
2104             CODE:
2105 1           INIT_ERROR_HANDLER;
2106              
2107             {
2108 1           xmlParserCtxtPtr ctxt = xmlCreateFileParserCtxt(filename);
2109 1 50         if (ctxt == NULL) {
2110 0           CLEANUP_ERROR_HANDLER;
2111 0 0         REPORT_ERROR(recover ? recover : 1);
2112 0           croak("Could not create file parser context for file \"%s\": %s\n",
2113 0           filename, strerror(errno));
2114             }
2115             xs_warn( "context created\n");
2116 1           real_obj = LibXML_init_parser(self, ctxt);
2117 1           recover = LibXML_get_recover(real_obj);
2118              
2119 1           ctxt->sax = PSaxGetHandler();
2120 1           PmmSAXInitContext( ctxt, self, saved_error );
2121             xs_warn( "context initialized \n");
2122              
2123             {
2124 1           xmlParseDocument(ctxt);
2125             xs_warn( "document parsed \n");
2126             }
2127              
2128 1           PmmSAXCloseContext(ctxt);
2129 1           xmlFreeParserCtxt(ctxt);
2130             }
2131              
2132 1           LibXML_cleanup_parser();
2133 1           CLEANUP_ERROR_HANDLER;
2134 1           REPORT_ERROR(recover);
2135              
2136             SV*
2137             _parse_html_string(self, string, svURL, svEncoding, options = 0)
2138             SV * self
2139             SV * string
2140             SV * svURL
2141             SV * svEncoding
2142             int options
2143             PREINIT:
2144             STRLEN len;
2145             char * ptr;
2146 18           char* URL = NULL;
2147 18           const char * encoding = NULL;
2148             HV * real_obj;
2149             htmlDocPtr real_doc;
2150 18           int recover = 0;
2151 18           PREINIT_SAVED_ERROR
2152             INIT:
2153             /* If string is a reference to a string - dereference it.
2154             * See: https://rt.cpan.org/Ticket/Display.html?id=64051 (broke it)
2155             * https://rt.cpan.org/Ticket/Display.html?id=77864 (fixed it) */
2156 18 100         if (SvROK(string) && !SvOBJECT(SvRV(string))) {
    50          
2157 1           string = SvRV(string);
2158             }
2159 18 50         ptr = SvPV(string, len);
2160 18 50         if (len <= 0) {
2161 0           croak("Empty string\n");
2162             XSRETURN_UNDEF;
2163             }
2164 18 100         if (SvOK(svURL))
    50          
    50          
2165 2 50         URL = SvPV_nolen( svURL );
2166 18 100         if (SvOK(svEncoding))
    50          
    50          
2167 6 50         encoding = SvPV_nolen( svEncoding );
2168             CODE:
2169 18           RETVAL = &PL_sv_undef;
2170 18           INIT_ERROR_HANDLER;
2171 18           real_obj = LibXML_init_parser(self,NULL);
2172 18 100         if (encoding == NULL && SvUTF8( string )) {
    100          
2173 4           encoding = "UTF-8";
2174             }
2175 18 100         if (options & HTML_PARSE_RECOVER) {
2176 14 100         recover = ((options & HTML_PARSE_NOERROR) ? 2 : 1);
2177             }
2178             #if LIBXML_VERSION >= 20627
2179 18           real_doc = htmlReadDoc((xmlChar*)ptr, URL, encoding, options);
2180             #else
2181             real_doc = htmlParseDoc((xmlChar*)ptr, encoding);
2182             if ( real_doc ) {
2183             if (real_doc->URL) xmlFree((xmlChar *)real_doc->URL);
2184             if (URL) {
2185             real_doc->URL = xmlStrdup((const xmlChar*) URL);
2186             }
2187             }
2188             #endif
2189 18 50         if ( real_doc ) {
2190 18 100         if (URL==NULL) {
2191 16           SV * newURI = sv_2mortal(newSVpvf("unknown-%p", (void*)real_doc));
2192 16 50         real_doc->URL = xmlStrdup((const xmlChar*)SvPV_nolen(newURI));
2193             }
2194             /* This HTML memory parser doesn't use a ctxt; there is no "well-formed"
2195             * distinction, and if it manages to parse the HTML, it returns non-null. */
2196 18           RETVAL = LibXML_NodeToSv( real_obj, INT2PTR(xmlNodePtr,real_doc) );
2197             }
2198              
2199 18           LibXML_cleanup_parser();
2200 18           CLEANUP_ERROR_HANDLER;
2201 18           REPORT_ERROR(recover);
2202             OUTPUT:
2203             RETVAL
2204              
2205              
2206             SV*
2207             _parse_html_file(self, filename_sv, svURL, svEncoding, options = 0)
2208             SV * self
2209             SV * filename_sv
2210             SV * svURL
2211             SV * svEncoding
2212             int options
2213             PREINIT:
2214             STRLEN len;
2215             char * filename;
2216 6           char * URL = NULL;
2217 6           char * encoding = NULL;
2218             HV * real_obj;
2219             htmlDocPtr real_doc;
2220 6           int recover = 0;
2221 6           PREINIT_SAVED_ERROR
2222             INIT:
2223 6 50         filename = SvPV(filename_sv, len);
2224 6 50         if (len <= 0) {
2225 0           croak("Empty filename\n");
2226             XSRETURN_UNDEF;
2227             }
2228 6 100         if (SvOK(svURL))
    50          
    50          
2229 1 50         URL = SvPV_nolen( svURL );
2230 6 100         if (SvOK(svEncoding))
    50          
    50          
2231 2 50         encoding = SvPV_nolen( svEncoding );
2232             CODE:
2233 6           RETVAL = &PL_sv_undef;
2234 6           INIT_ERROR_HANDLER;
2235 6           real_obj = LibXML_init_parser(self,NULL);
2236 6 100         if (options & HTML_PARSE_RECOVER) {
2237 3 50         recover = ((options & HTML_PARSE_NOERROR) ? 2 : 1);
2238             }
2239             #if LIBXML_VERSION >= 20627
2240 6           real_doc = htmlReadFile((const char *)filename,
2241             encoding,
2242             options);
2243             #else
2244             real_doc = htmlParseFile((const char *)filename, encoding);
2245             #endif
2246 6 50         if ( real_doc != NULL ) {
2247              
2248             /* This HTML file parser doesn't use a ctxt; there is no "well-formed"
2249             * distinction, and if it manages to parse the HTML, it returns non-null. */
2250 6 100         if (URL) {
2251 1 50         if (real_doc->URL) xmlFree((xmlChar*) real_doc->URL);
2252 1           real_doc->URL = xmlStrdup((const xmlChar*) URL);
2253             }
2254 6           RETVAL = LibXML_NodeToSv( real_obj, INT2PTR(xmlNodePtr,real_doc) );
2255              
2256             }
2257 6           CLEANUP_ERROR_HANDLER;
2258 6           LibXML_cleanup_parser();
2259 6           REPORT_ERROR(recover);
2260             OUTPUT:
2261             RETVAL
2262              
2263             SV*
2264             _parse_html_fh(self, fh, svURL, svEncoding, options = 0)
2265             SV * self
2266             SV * fh
2267             SV * svURL
2268             SV * svEncoding
2269             int options
2270             PREINIT:
2271             HV * real_obj;
2272             htmlDocPtr real_doc;
2273 4           int recover = 0;
2274 4           char * URL = NULL;
2275 4           PREINIT_SAVED_ERROR
2276             #if LIBXML_VERSION >= 20627
2277 4           char * encoding = NULL;
2278             #else
2279             xmlCharEncoding enc = XML_CHAR_ENCODING_NONE;
2280             #endif
2281             INIT:
2282 4 100         if (SvOK(svURL))
    50          
    50          
2283 1 50         URL = SvPV_nolen( svURL );
2284             #if LIBXML_VERSION >= 20627
2285 4 100         if (SvOK(svEncoding))
    50          
    50          
2286 2 50         encoding = SvPV_nolen( svEncoding );
2287             #else
2288             if (SvOK(svEncoding))
2289             enc = xmlParseCharEncoding(SvPV_nolen( svEncoding ));
2290             #endif
2291             CODE:
2292 4           RETVAL = &PL_sv_undef;
2293 4           INIT_ERROR_HANDLER;
2294 4           real_obj = LibXML_init_parser(self,NULL);
2295 4 100         if (options & HTML_PARSE_RECOVER) {
2296 3 50         recover = ((options & HTML_PARSE_NOERROR) ? 2 : 1);
2297             }
2298             #if LIBXML_VERSION >= 20627
2299              
2300 4           real_doc = htmlReadIO((xmlInputReadCallback) LibXML_read_perl,
2301             NULL,
2302             (void *) fh,
2303             URL,
2304             encoding,
2305             options);
2306             #else /* LIBXML_VERSION >= 20627 */
2307             {
2308             int read_length;
2309             int well_formed;
2310             char buffer[1024];
2311             htmlParserCtxtPtr ctxt;
2312              
2313             read_length = LibXML_read_perl(fh, buffer, 4);
2314             if (read_length <= 0) {
2315             CLEANUP_ERROR_HANDLER;
2316             croak( "Empty Stream\n" );
2317             }
2318             ctxt = htmlCreatePushParserCtxt(NULL, NULL, buffer, read_length,
2319             URL, enc);
2320             if (ctxt == NULL) {
2321             CLEANUP_ERROR_HANDLER;
2322             REPORT_ERROR(recover ? recover : 1);
2323             croak("Could not create html push parser context!\n");
2324             }
2325             ctxt->_private = (void*)self;
2326             {
2327             int ret;
2328             while ((read_length = LibXML_read_perl(fh, buffer, 1024))) {
2329             ret = htmlParseChunk(ctxt, buffer, read_length, 0);
2330             if ( ret != 0 ) {
2331             break;
2332             }
2333             }
2334             ret = htmlParseChunk(ctxt, buffer, 0, 1);
2335             }
2336             well_formed = ctxt->wellFormed;
2337             real_doc = ctxt->myDoc;
2338             ctxt->myDoc = NULL;
2339             htmlFreeParserCtxt(ctxt);
2340             }
2341             #endif /* LIBXML_VERSION >= 20627 */
2342 4 50         if ( real_doc != NULL ) {
2343 4 100         if (real_doc->URL) xmlFree((xmlChar*) real_doc->URL);
2344 4 100         if (URL) {
2345 1           real_doc->URL = xmlStrdup((const xmlChar*) URL);
2346             } else {
2347 3           SV * newURI = sv_2mortal(newSVpvf("unknown-%p", (void*)real_doc));
2348 3 50         real_doc->URL = xmlStrdup((const xmlChar*)SvPV_nolen(newURI));
2349             }
2350              
2351 4           RETVAL = LibXML_NodeToSv( real_obj, INT2PTR(xmlNodePtr,real_doc) );
2352             }
2353              
2354 4           LibXML_cleanup_parser();
2355 4           CLEANUP_ERROR_HANDLER;
2356 4           REPORT_ERROR(recover);
2357             OUTPUT:
2358             RETVAL
2359              
2360             SV*
2361             _parse_xml_chunk(self, svchunk, enc = &PL_sv_undef)
2362             SV * self
2363             SV * svchunk
2364             SV * enc
2365             PREINIT:
2366             STRLEN len;
2367 43           const char * encoding = "UTF-8";
2368             HV * real_obj;
2369 43           int recover = 0;
2370             xmlChar * chunk;
2371 43           xmlNodePtr rv = NULL;
2372 43           PREINIT_SAVED_ERROR
2373             INIT:
2374 43 50         if (SvPOK(enc)) {
2375 0 0         encoding = SvPV(enc, len);
2376 0 0         if (len <= 0) {
2377 0           encoding = "UTF-8";
2378             }
2379             }
2380             CODE:
2381 43           RETVAL = &PL_sv_undef;
2382 43           INIT_ERROR_HANDLER;
2383 43           real_obj = LibXML_init_parser(self,NULL);
2384              
2385 43           chunk = Sv2C(svchunk, (const xmlChar*)encoding);
2386              
2387 43 50         if ( chunk != NULL ) {
2388 43           recover = LibXML_get_recover(real_obj);
2389              
2390 43           rv = domReadWellBalancedString( NULL, chunk, recover );
2391              
2392 43 100         if ( rv != NULL ) {
2393 35           xmlNodePtr fragment= NULL;
2394 35           xmlNodePtr rv_end = NULL;
2395              
2396             /* now we append the nodelist to a document
2397             fragment which is unbound to a Document!!!! */
2398              
2399             /* step 1: create the fragment */
2400 35           fragment = xmlNewDocFragment( NULL );
2401 35           RETVAL = LibXML_NodeToSv(real_obj, fragment);
2402              
2403             /* step 2: set the node list to the fragment */
2404 35           fragment->children = rv;
2405 35           rv_end = rv;
2406 60 100         while ( rv_end->next != NULL ) {
2407 25           rv_end->parent = fragment;
2408 25           rv_end = rv_end->next;
2409             }
2410             /* the following line is important, otherwise we'll have
2411             occasional segmentation faults
2412             */
2413 35           rv_end->parent = fragment;
2414 35           fragment->last = rv_end;
2415             }
2416              
2417             /* free the chunk we created */
2418 43           xmlFree( chunk );
2419             }
2420              
2421 43           LibXML_cleanup_parser();
2422 43           CLEANUP_ERROR_HANDLER;
2423 43           REPORT_ERROR(recover);
2424              
2425 35 50         if (rv == NULL) {
2426 0           croak("_parse_xml_chunk: chunk parsing failed\n");
2427             }
2428             OUTPUT:
2429             RETVAL
2430              
2431             void
2432             _parse_sax_xml_chunk(self, svchunk, enc = &PL_sv_undef)
2433             SV * self
2434             SV * svchunk
2435             SV * enc
2436             PREINIT:
2437             STRLEN len;
2438             char * ptr;
2439 29           const char * encoding = "UTF-8";
2440             HV * real_obj;
2441 29           int recover = 0;
2442             xmlChar * chunk;
2443 29           int retCode = -1;
2444 29           xmlNodePtr nodes = NULL;
2445 29           xmlSAXHandlerPtr handler = NULL;
2446 29           PREINIT_SAVED_ERROR
2447             INIT:
2448 29 50         if (SvPOK(enc)) {
2449 0 0         encoding = SvPV(enc, len);
2450 0 0         if (len <= 0) {
2451 0           encoding = "UTF-8";
2452             }
2453             }
2454 29 50         ptr = SvPV(svchunk, len);
2455 29 50         if (len <= 0) {
2456 0           croak("Empty string\n");
2457             }
2458             CODE:
2459 29           INIT_ERROR_HANDLER;
2460              
2461 29           chunk = Sv2C(svchunk, (const xmlChar*)encoding);
2462              
2463 29 50         if ( chunk != NULL ) {
2464 29           xmlParserCtxtPtr ctxt = xmlCreateMemoryParserCtxt((const char*)ptr, len);
2465 29 50         if (ctxt == NULL) {
2466 0           CLEANUP_ERROR_HANDLER;
2467 0 0         REPORT_ERROR(recover ? recover : 1);
2468 0           croak("Could not create memory parser context!\n");
2469             }
2470             xs_warn( "context created\n");
2471 29           real_obj = LibXML_init_parser(self,ctxt);
2472 29           recover = LibXML_get_recover(real_obj);
2473              
2474 29           PmmSAXInitContext( ctxt, self, saved_error );
2475 29           handler = PSaxGetHandler();
2476              
2477 29           retCode = xmlParseBalancedChunkMemory( NULL,
2478             handler,
2479             ctxt,
2480             0,
2481             chunk,
2482             &nodes );
2483              
2484 29           xmlFree( handler );
2485 29           PmmSAXCloseContext(ctxt);
2486 29           xmlFreeParserCtxt(ctxt);
2487              
2488             /* free the chunk we created */
2489 29           xmlFree( chunk );
2490             }
2491              
2492 29           LibXML_cleanup_parser();
2493 29           CLEANUP_ERROR_HANDLER;
2494 29           REPORT_ERROR(recover);
2495              
2496 29 50         if (retCode == -1) {
2497 0           croak("_parse_sax_xml_chunk: chunk parsing failed\n");
2498             }
2499              
2500             int
2501             _processXIncludes(self, doc, options=0)
2502             SV * self
2503             SV * doc
2504             int options
2505             PREINIT:
2506             xmlDocPtr real_doc;
2507             HV * real_obj;
2508 22           int recover = 0;
2509 22           PREINIT_SAVED_ERROR
2510             INIT:
2511 22           real_doc = (xmlDocPtr) PmmSvNode(doc);
2512 22 100         if (real_doc == NULL) {
2513 2           croak("No document to process!\n");
2514             XSRETURN_UNDEF;
2515             }
2516             CODE:
2517 20           RETVAL = 0;
2518 20           INIT_ERROR_HANDLER;
2519 20           real_obj = LibXML_init_parser(self,NULL);
2520 20           recover = LibXML_get_recover(real_obj);
2521              
2522 20           RETVAL = xmlXIncludeProcessFlags(real_doc,options);
2523              
2524 20           LibXML_cleanup_parser();
2525 20           CLEANUP_ERROR_HANDLER;
2526 20           REPORT_ERROR(recover);
2527              
2528 18 50         if ( RETVAL < 0 ) {
2529 0           croak( "unknown error during XInclude processing\n" );
2530             XSRETURN_UNDEF;
2531 18 100         } else if ( RETVAL == 0 ) {
2532 1           RETVAL = 1;
2533             }
2534             OUTPUT:
2535             RETVAL
2536              
2537             SV*
2538             _start_push(self, with_sax=0)
2539             SV * self
2540             int with_sax
2541             PREINIT:
2542             HV * real_obj;
2543 76           int recover = 0;
2544 76           xmlParserCtxtPtr ctxt = NULL;
2545 76           PREINIT_SAVED_ERROR
2546             CODE:
2547 76           RETVAL = &PL_sv_undef;
2548 76           INIT_ERROR_HANDLER;
2549              
2550             /* create empty context */
2551 76           ctxt = xmlCreatePushParserCtxt( NULL, NULL, NULL, 0, NULL );
2552 76           real_obj = LibXML_init_parser(self,ctxt);
2553 76           recover = LibXML_get_recover(real_obj);
2554 76 100         if ( with_sax == 1 ) {
2555 36           PmmSAXInitContext( ctxt, self, saved_error );
2556             }
2557              
2558 76           RETVAL = PmmContextSv( ctxt );
2559              
2560 76           LibXML_cleanup_parser();
2561 76           CLEANUP_ERROR_HANDLER;
2562 76           REPORT_ERROR(recover);
2563             OUTPUT:
2564             RETVAL
2565              
2566             int
2567             _push(self, pctxt, data)
2568             SV * self
2569             SV * pctxt
2570             SV * data
2571             PREINIT:
2572             HV * real_obj;
2573 299           int recover = 0;
2574 299           xmlParserCtxtPtr ctxt = NULL;
2575 299           STRLEN len = 0;
2576 299           char * chunk = NULL;
2577 299           PREINIT_SAVED_ERROR
2578             INIT:
2579 299           ctxt = PmmSvContext( pctxt );
2580 299 50         if ( ctxt == NULL ) {
2581 0           croak( "parser context already freed\n" );
2582 0           XSRETURN_UNDEF;
2583             }
2584 299 50         if ( data == &PL_sv_undef ) {
2585 0           XSRETURN_UNDEF;
2586             }
2587 299 50         chunk = SvPV( data, len );
2588 299 50         if ( len <= 0 ) {
2589             xs_warn( "empty string" );
2590 0           XSRETURN_UNDEF;
2591             }
2592             CODE:
2593 299           RETVAL = 0;
2594 299           INIT_ERROR_HANDLER;
2595 299           real_obj = LibXML_init_parser(self,NULL);
2596 299           recover = LibXML_get_recover(real_obj);
2597              
2598 299           xmlParseChunk(ctxt, (const char *)chunk, len, 0);
2599              
2600 299           LibXML_cleanup_parser();
2601 299           CLEANUP_ERROR_HANDLER;
2602 299           REPORT_ERROR(recover);
2603              
2604 298 100         if ( ctxt->wellFormed == 0 ) {
2605 8           croak( "XML not well-formed in xmlParseChunk\n" );
2606             XSRETURN_UNDEF;
2607             }
2608 290           RETVAL = 1;
2609             OUTPUT:
2610             RETVAL
2611              
2612             SV*
2613             _end_push(self, pctxt, restore)
2614             SV * self
2615             SV * pctxt
2616             int restore
2617             PREINIT:
2618             HV * real_obj;
2619             int well_formed;
2620 39           xmlParserCtxtPtr ctxt = NULL;
2621 39           xmlDocPtr real_doc = NULL;
2622 39           PREINIT_SAVED_ERROR
2623             INIT:
2624 39           ctxt = PmmSvContext( pctxt );
2625 39 50         if ( ctxt == NULL ) {
2626 0           croak( "parser context already freed\n" );
2627             XSRETURN_UNDEF;
2628             }
2629             CODE:
2630 39           RETVAL = &PL_sv_undef;
2631 39           INIT_ERROR_HANDLER;
2632 39           real_obj = LibXML_init_parser(self,NULL);
2633              
2634 39           xmlParseChunk(ctxt, "", 0, 1); /* finish the parse */
2635             xs_warn( "Finished with push parser\n" );
2636              
2637 39           well_formed = ctxt->wellFormed;
2638 39           real_doc = ctxt->myDoc;
2639 39           ctxt->myDoc = NULL;
2640 39           xmlFreeParserCtxt(ctxt);
2641 39 50         PmmNODE( SvPROXYNODE( pctxt ) ) = NULL;
2642              
2643 39 50         if ( real_doc != NULL ) {
2644 39 100         if ( restore || well_formed ) {
    50          
2645 39           RETVAL = LibXML_NodeToSv( real_obj, INT2PTR(xmlNodePtr,real_doc) );
2646             } else {
2647 0           xmlFreeDoc(real_doc);
2648 0           real_doc = NULL;
2649             }
2650             }
2651              
2652 39           LibXML_cleanup_parser();
2653 39           CLEANUP_ERROR_HANDLER;
2654 39           REPORT_ERROR(restore);
2655              
2656 39 50         if ( real_doc == NULL ){
2657 0           croak( "no document found!\n" );
2658             XSRETURN_UNDEF;
2659             }
2660             OUTPUT:
2661             RETVAL
2662              
2663             void
2664             _end_sax_push(self, pctxt)
2665             SV * self
2666             SV * pctxt
2667             PREINIT:
2668             HV * real_obj;
2669 36           xmlParserCtxtPtr ctxt = NULL;
2670 36           PREINIT_SAVED_ERROR
2671             INIT:
2672 36           ctxt = PmmSvContext( pctxt );
2673 36 50         if ( ctxt == NULL ) {
2674 0           croak( "parser context already freed\n" );
2675             }
2676             CODE:
2677 36           INIT_ERROR_HANDLER;
2678 36           real_obj = LibXML_init_parser(self,NULL);
2679              
2680 36           xmlParseChunk(ctxt, "", 0, 1); /* finish the parse */
2681             xs_warn( "Finished with SAX push parser\n" );
2682              
2683 36           xmlFree(ctxt->sax);
2684 36           ctxt->sax = NULL;
2685 36           PmmSAXCloseContext(ctxt);
2686 36           xmlFreeParserCtxt(ctxt);
2687 36 50         PmmNODE( SvPROXYNODE( pctxt ) ) = NULL;
2688              
2689 36           LibXML_cleanup_parser();
2690 36           CLEANUP_ERROR_HANDLER;
2691 36           REPORT_ERROR(0);
2692              
2693             SV*
2694             import_GDOME( CLASS, sv_gdome, deep=1 )
2695             SV * sv_gdome
2696             int deep
2697             PREINIT:
2698 0           xmlNodePtr node = NULL;
2699             INIT:
2700 0           RETVAL = &PL_sv_undef;
2701             #ifndef XML_LIBXML_GDOME_SUPPORT
2702 0           croak( "GDOME Support not compiled" );
2703             #endif
2704             if ( sv_gdome == NULL || sv_gdome == &PL_sv_undef ) {
2705             croak( "no XML::GDOME data found" );
2706             }
2707             #ifdef XML_LIBXML_GDOME_SUPPORT
2708             else {
2709             GdomeNode* gnode = NULL;
2710             gnode = (GdomeNode*)SvIV((SV*)SvRV( sv_gdome ));
2711             if ( gnode == NULL ) {
2712             croak( "no XML::GDOME data found (datastructure empty)" );
2713             }
2714              
2715             node = gdome_xml_n_get_xmlNode( gnode );
2716             if ( node == NULL ) {
2717             croak( "no XML::LibXML node found in GDOME object" );
2718             }
2719             }
2720             #endif
2721             CODE:
2722             if ( node->type == XML_NAMESPACE_DECL ) {
2723             const char * CLASS = "XML::LibXML::Namespace";
2724             RETVAL = NEWSV(0,0);
2725             RETVAL = sv_setref_pv( RETVAL,
2726             CLASS,
2727             (void*)xmlCopyNamespace((xmlNsPtr)node) );
2728             }
2729             else {
2730             RETVAL = PmmNodeToSv( PmmCloneNode( node, deep ), NULL );
2731             }
2732             OUTPUT:
2733             RETVAL
2734              
2735              
2736             SV*
2737             export_GDOME( CLASS, sv_libxml, deep=1 )
2738             SV * sv_libxml
2739             int deep
2740             PREINIT:
2741 0           xmlNodePtr node = NULL, retnode = NULL;
2742             INIT:
2743 0           RETVAL = &PL_sv_undef;
2744             #ifndef XML_LIBXML_GDOME_SUPPORT
2745 0           croak( "GDOME Support not configured!" );
2746             #endif
2747             if ( sv_libxml == NULL || sv_libxml == &PL_sv_undef ) {
2748             croak( "no XML::LibXML data found" );
2749             }
2750             node = PmmSvNode( sv_libxml );
2751             if ( node == NULL ) {
2752             croak( "no XML::LibXML data found (empty structure)" );
2753             }
2754             CODE:
2755             retnode = PmmCloneNode( node, deep );
2756             if ( retnode == NULL ) {
2757             croak( "Copy node failed" );
2758             }
2759              
2760             RETVAL = PmmNodeToGdomeSv( retnode );
2761             OUTPUT:
2762             RETVAL
2763              
2764              
2765             int
2766             load_catalog( self, filename )
2767             SV * filename
2768             PREINIT:
2769 1           const char * fn = (const char *) Sv2C(filename, NULL);
2770             INIT:
2771 1 50         if ( fn == NULL || xmlStrlen( (xmlChar *)fn ) == 0 ) {
    50          
2772 0           croak( "cannot load catalog" );
2773             }
2774             CODE:
2775             #ifdef LIBXML_CATALOG_ENABLED
2776 1           RETVAL = xmlLoadCatalog( fn );
2777             #else
2778             XSRETURN_UNDEF;
2779             #endif
2780             OUTPUT:
2781             RETVAL
2782              
2783              
2784              
2785             int
2786             _default_catalog( self, catalog )
2787             SV * catalog
2788             PREINIT:
2789             #ifdef LIBXML_CATALOG_ENABLED
2790 0 0         xmlCatalogPtr catal = INT2PTR(xmlCatalogPtr,SvIV(SvRV(catalog)));
2791             #endif
2792             INIT:
2793 0 0         if ( catal == NULL ) {
2794 0           croak( "empty catalog\n" );
2795             }
2796             CODE:
2797 0           warn( "this feature is not implemented" );
2798 0           RETVAL = 0;
2799             OUTPUT:
2800             RETVAL
2801              
2802             SV*
2803             _externalEntityLoader( loader )
2804             SV* loader
2805             CODE:
2806             {
2807 1           RETVAL = EXTERNAL_ENTITY_LOADER_FUNC;
2808 1 50         if(EXTERNAL_ENTITY_LOADER_FUNC == NULL)
2809             {
2810 1           EXTERNAL_ENTITY_LOADER_FUNC = newSVsv(loader);
2811             }
2812              
2813 1 50         if (LibXML_old_ext_ent_loader == NULL )
2814             {
2815 1           LibXML_old_ext_ent_loader = xmlGetExternalEntityLoader();
2816 1           xmlSetExternalEntityLoader((xmlExternalEntityLoader)LibXML_load_external_entity);
2817             }
2818             }
2819             OUTPUT:
2820             RETVAL
2821              
2822             MODULE = XML::LibXML PACKAGE = XML::LibXML::HashTable
2823              
2824             xmlHashTablePtr
2825             new(CLASS)
2826             const char * CLASS
2827             CODE:
2828 0           RETVAL = xmlHashCreate(8);
2829             OUTPUT:
2830             RETVAL
2831              
2832             void
2833             DESTROY( table )
2834             xmlHashTablePtr table
2835             CODE:
2836             xs_warn("DESTROY XMLHASHTABLE\n");
2837 0           PmmFreeHashTable(table);
2838              
2839             MODULE = XML::LibXML PACKAGE = XML::LibXML::ParserContext
2840              
2841             void
2842             DESTROY( self )
2843             SV * self
2844             CODE:
2845             xs_warn( "DROP PARSER CONTEXT!" );
2846 76 50         PmmContextREFCNT_dec( SvPROXYNODE( self ) );
2847              
2848              
2849             MODULE = XML::LibXML PACKAGE = XML::LibXML::Document
2850              
2851             SV *
2852             _toString(self, format=0)
2853             xmlDocPtr self
2854             int format
2855             PREINIT:
2856 29           xmlChar *result=NULL;
2857 29           int len=0;
2858 29           SV* internalFlag = NULL;
2859 29           int oldTagFlag = xmlSaveNoEmptyTags;
2860 29           xmlDtdPtr intSubset = NULL;
2861             /* PREINIT_SAVED_ERROR */
2862             CODE:
2863 29           RETVAL = &PL_sv_undef;
2864 29           internalFlag = get_sv("XML::LibXML::setTagCompression", 0);
2865 29 50         if( internalFlag ) {
2866 29 50         xmlSaveNoEmptyTags = SvTRUE(internalFlag);
    50          
    0          
    50          
    0          
    0          
    50          
    0          
    0          
    0          
    0          
    0          
    50          
    50          
    50          
    50          
    0          
    50          
    0          
2867             }
2868              
2869 29           internalFlag = get_sv("XML::LibXML::skipDTD", 0);
2870 29 50         if ( internalFlag && SvTRUE(internalFlag) ) {
    50          
    50          
    50          
    0          
    0          
    50          
    0          
    0          
    0          
    0          
    50          
    50          
    100          
    50          
    0          
    100          
2871 1           intSubset = xmlGetIntSubset( self );
2872 1 50         if ( intSubset )
2873 1           xmlUnlinkNode( INT2PTR(xmlNodePtr,intSubset) );
2874             }
2875              
2876             /* INIT_ERROR_HANDLER; */
2877              
2878 29 100         if ( format <= 0 ) {
2879             xs_warn( "use no formated toString!" );
2880 28           xmlDocDumpMemory(self, &result, &len);
2881             }
2882             else {
2883 1           int t_indent_var = xmlIndentTreeOutput;
2884             xs_warn( "use formated toString!" );
2885 1           xmlIndentTreeOutput = 1;
2886 1           xmlDocDumpFormatMemory( self, &result, &len, format );
2887 1           xmlIndentTreeOutput = t_indent_var;
2888             }
2889              
2890 29 100         if ( intSubset != NULL ) {
2891 1 50         if (self->children == NULL) {
2892 0           xmlAddChild(INT2PTR(xmlNodePtr,self), INT2PTR(xmlNodePtr,intSubset));
2893             }
2894             else {
2895 1           xmlAddPrevSibling(self->children, INT2PTR(xmlNodePtr,intSubset));
2896             }
2897             }
2898              
2899 29           xmlSaveNoEmptyTags = oldTagFlag;
2900              
2901             /* REPORT_ERROR(0); */
2902              
2903 29 50         if (result == NULL) {
2904             xs_warn("Failed to convert doc to string");
2905 0           XSRETURN_UNDEF;
2906             } else {
2907             /* warn("%s, %d\n",result, len); */
2908 29           RETVAL = newSVpvn( (const char *)result, len );
2909             /* C2Sv( result, self->encoding ); */
2910 29           xmlFree(result);
2911             }
2912             OUTPUT:
2913             RETVAL
2914              
2915             int
2916             toFH( self, filehandler, format=0 )
2917             xmlDocPtr self
2918             SV * filehandler
2919             int format
2920             PREINIT:
2921             xmlOutputBufferPtr buffer;
2922 1           const xmlChar * encoding = NULL;
2923 1           xmlCharEncodingHandlerPtr handler = NULL;
2924 1           SV* internalFlag = NULL;
2925 1           int oldTagFlag = xmlSaveNoEmptyTags;
2926 1           xmlDtdPtr intSubset = NULL;
2927 1           int t_indent_var = xmlIndentTreeOutput;
2928 1           PREINIT_SAVED_ERROR
2929             CODE:
2930 1           internalFlag = get_sv("XML::LibXML::setTagCompression", 0);
2931 1 50         if( internalFlag ) {
2932 1 50         xmlSaveNoEmptyTags = SvTRUE(internalFlag);
    50          
    0          
    50          
    0          
    0          
    50          
    0          
    0          
    0          
    0          
    0          
    50          
    50          
    50          
    50          
    0          
    50          
    0          
2933             }
2934              
2935 1           internalFlag = get_sv("XML::LibXML::skipDTD", 0);
2936 1 50         if ( internalFlag && SvTRUE(internalFlag) ) {
    50          
    50          
    50          
    0          
    0          
    50          
    0          
    0          
    0          
    0          
    50          
    50          
    50          
    50          
    0          
    50          
2937 0           intSubset = xmlGetIntSubset( self );
2938 0 0         if ( intSubset )
2939 0           xmlUnlinkNode( INT2PTR(xmlNodePtr,intSubset) );
2940             }
2941              
2942 1           xmlRegisterDefaultOutputCallbacks();
2943 1           encoding = (self)->encoding;
2944 1 50         if ( encoding != NULL ) {
2945 0 0         if ( xmlParseCharEncoding((const char*)encoding) != XML_CHAR_ENCODING_UTF8) {
2946 0           handler = xmlFindCharEncodingHandler((const char*)encoding);
2947             }
2948              
2949             }
2950             else {
2951             xs_warn("no encoding?");
2952             }
2953              
2954 1           buffer = xmlOutputBufferCreateIO( (xmlOutputWriteCallback) &LibXML_output_write_handler,
2955             (xmlOutputCloseCallback)&LibXML_output_close_handler,
2956             filehandler,
2957             handler );
2958              
2959 1 50         if ( format <= 0 ) {
2960 1           format = 0;
2961 1           xmlIndentTreeOutput = 0;
2962             }
2963             else {
2964 0           xmlIndentTreeOutput = 1;
2965             }
2966              
2967 1           INIT_ERROR_HANDLER;
2968              
2969 1           RETVAL = xmlSaveFormatFileTo( buffer,
2970             self,
2971             (const char *) encoding,
2972             format);
2973              
2974 1 50         if ( intSubset != NULL ) {
2975 0 0         if (self->children == NULL) {
2976 0           xmlAddChild(INT2PTR(xmlNodePtr,self), INT2PTR(xmlNodePtr,intSubset));
2977             }
2978             else {
2979 0           xmlAddPrevSibling(self->children, INT2PTR(xmlNodePtr,intSubset));
2980             }
2981             }
2982              
2983 1           xmlIndentTreeOutput = t_indent_var;
2984 1           xmlSaveNoEmptyTags = oldTagFlag;
2985 1           CLEANUP_ERROR_HANDLER;
2986 1           REPORT_ERROR(0);
2987             OUTPUT:
2988             RETVAL
2989              
2990             int
2991             toFile( self, filename, format=0 )
2992             xmlDocPtr self
2993             char * filename
2994             int format
2995             PREINIT:
2996 1           SV* internalFlag = NULL;
2997 1           int oldTagFlag = xmlSaveNoEmptyTags;
2998 1           PREINIT_SAVED_ERROR
2999             CODE:
3000 1           internalFlag = get_sv("XML::LibXML::setTagCompression", 0);
3001 1 50         if( internalFlag ) {
3002 1 50         xmlSaveNoEmptyTags = SvTRUE(internalFlag);
    50          
    0          
    50          
    0          
    0          
    50          
    0          
    0          
    0          
    0          
    0          
    50          
    50          
    50          
    50          
    0          
    50          
    0          
3003             }
3004              
3005 1           INIT_ERROR_HANDLER;
3006              
3007 1 50         if ( format <= 0 ) {
3008             xs_warn( "use no formated toFile!" );
3009 1           RETVAL = xmlSaveFile( filename, self );
3010             }
3011             else {
3012 0           int t_indent_var = xmlIndentTreeOutput;
3013 0           xmlIndentTreeOutput = 1;
3014 0           RETVAL =xmlSaveFormatFile( filename,
3015             self,
3016             format);
3017 0           xmlIndentTreeOutput = t_indent_var;
3018             }
3019              
3020 1           xmlSaveNoEmptyTags = oldTagFlag;
3021 1           CLEANUP_ERROR_HANDLER;
3022 1           REPORT_ERROR(0);
3023              
3024 1 50         if ( RETVAL > 0 )
3025 1           RETVAL = 1;
3026             else
3027 0           XSRETURN_UNDEF;
3028             OUTPUT:
3029             RETVAL
3030              
3031             SV *
3032             toStringHTML(self)
3033             xmlDocPtr self
3034             ALIAS:
3035             XML::LibXML::Document::serialize_html = 1
3036             PREINIT:
3037 4           xmlChar *result=NULL;
3038 4           int len = 0;
3039 4           PREINIT_SAVED_ERROR
3040             CODE:
3041             PERL_UNUSED_VAR(ix);
3042             xs_warn( "use no formated toString!" );
3043 4           INIT_ERROR_HANDLER;
3044 4           htmlDocDumpMemory(self, &result, &len);
3045 4           CLEANUP_ERROR_HANDLER;
3046 4           REPORT_ERROR(0);
3047              
3048 4 50         if (result == NULL) {
3049 0           XSRETURN_UNDEF;
3050             } else {
3051             /* warn("%s, %d\n",result, len); */
3052 4           RETVAL = newSVpvn((char *)result, (STRLEN)len);
3053 4           xmlFree(result);
3054             }
3055             OUTPUT:
3056             RETVAL
3057              
3058              
3059             const char *
3060             URI( self )
3061             xmlDocPtr self
3062             ALIAS:
3063             XML::LibXML::Document::documentURI = 1
3064             CODE:
3065             PERL_UNUSED_VAR(ix);
3066 11           RETVAL = (const char*)xmlStrdup(self->URL );
3067             OUTPUT:
3068             RETVAL
3069              
3070             void
3071             setURI( self, new_URI )
3072             xmlDocPtr self
3073             char * new_URI
3074             CODE:
3075 2 50         if (new_URI) {
3076 2           xmlFree((xmlChar*)self->URL );
3077 2           self->URL = xmlStrdup((const xmlChar*)new_URI);
3078             }
3079              
3080             SV*
3081             createDocument( CLASS, version="1.0", encoding=NULL )
3082             char * version
3083             char * encoding
3084             ALIAS:
3085             XML::LibXML::Document::new = 1
3086             PREINIT:
3087 121           xmlDocPtr doc=NULL;
3088             CODE:
3089             PERL_UNUSED_VAR(ix);
3090 121           doc = xmlNewDoc((const xmlChar*)version);
3091 121 100         if (encoding && *encoding != 0) {
    50          
3092 6           doc->encoding = (const xmlChar*)xmlStrdup((const xmlChar*)encoding);
3093             }
3094 121           RETVAL = PmmNodeToSv(INT2PTR(xmlNodePtr,doc),NULL);
3095             OUTPUT:
3096             RETVAL
3097              
3098             SV*
3099             createInternalSubset( self, Pname, extID, sysID )
3100             xmlDocPtr self
3101             SV * Pname
3102             SV * extID
3103             SV * sysID
3104             PREINIT:
3105 1           xmlDtdPtr dtd = NULL;
3106 1           xmlChar * name = NULL;
3107 1           xmlChar * externalID = NULL;
3108 1           xmlChar * systemID = NULL;
3109             CODE:
3110 1           name = Sv2C( Pname, NULL );
3111 1 50         if ( name == NULL ) {
3112 0           XSRETURN_UNDEF;
3113             }
3114              
3115 1           externalID = Sv2C(extID, NULL);
3116 1           systemID = Sv2C(sysID, NULL);
3117              
3118 1           dtd = xmlCreateIntSubset( self, name, externalID, systemID );
3119 1           xmlFree(externalID);
3120 1           xmlFree(systemID);
3121 1           xmlFree(name);
3122 1 50         if ( dtd ) {
3123 1           RETVAL = PmmNodeToSv( INT2PTR(xmlNodePtr,dtd), PmmPROXYNODE(self) );
3124             }
3125             else {
3126 0           XSRETURN_UNDEF;
3127             }
3128             OUTPUT:
3129             RETVAL
3130              
3131             SV*
3132             createExternalSubset( self, Pname, extID, sysID )
3133             xmlDocPtr self
3134             SV * Pname
3135             SV * extID
3136             SV * sysID
3137             PREINIT:
3138 1           xmlDtdPtr dtd = NULL;
3139 1           xmlChar * name = NULL;
3140 1           xmlChar * externalID = NULL;
3141 1           xmlChar * systemID = NULL;
3142             CODE:
3143 1           name = Sv2C( Pname, NULL );
3144 1 50         if ( name == NULL ) {
3145 0           XSRETURN_UNDEF;
3146             }
3147              
3148 1           externalID = Sv2C(extID, NULL);
3149 1           systemID = Sv2C(sysID, NULL);
3150              
3151 1           dtd = xmlNewDtd( self, name, externalID, systemID );
3152              
3153 1           xmlFree(externalID);
3154 1           xmlFree(systemID);
3155 1           xmlFree(name);
3156 1 50         if ( dtd ) {
3157 1           RETVAL = PmmNodeToSv( (xmlNodePtr)dtd, PmmPROXYNODE(self) );
3158             }
3159             else {
3160 0           XSRETURN_UNDEF;
3161             }
3162             OUTPUT:
3163             RETVAL
3164              
3165             SV*
3166             createDTD( self, Pname, extID, sysID )
3167             xmlDocPtr self
3168             SV * Pname
3169             SV * extID
3170             SV * sysID
3171             PREINIT:
3172 1           xmlDtdPtr dtd = NULL;
3173 1           xmlChar * name = NULL;
3174 1           xmlChar * externalID = NULL;
3175 1           xmlChar * systemID = NULL;
3176             CODE:
3177 1           name = Sv2C( Pname, NULL );
3178 1 50         if ( name == NULL ) {
3179 0           XSRETURN_UNDEF;
3180             }
3181              
3182 1           externalID = Sv2C(extID, NULL);
3183 1           systemID = Sv2C(sysID, NULL);
3184              
3185 1           dtd = xmlNewDtd( NULL, name, externalID, systemID );
3186 1           dtd->doc = self;
3187              
3188 1           xmlFree(externalID);
3189 1           xmlFree(systemID);
3190 1           xmlFree(name);
3191 1 50         if ( dtd ) {
3192 1           RETVAL = PmmNodeToSv( (xmlNodePtr)dtd, PmmPROXYNODE(self) );
3193             }
3194             else {
3195 0           XSRETURN_UNDEF;
3196             }
3197             OUTPUT:
3198             RETVAL
3199              
3200             SV*
3201             createDocumentFragment( self )
3202             xmlDocPtr self
3203             CODE:
3204 3           RETVAL = PmmNodeToSv(xmlNewDocFragment(self), PmmPROXYNODE(self));
3205             OUTPUT:
3206             RETVAL
3207              
3208             SV*
3209             createElement( self, name )
3210             xmlDocPtr self
3211             SV* name
3212             PREINIT:
3213             xmlNodePtr newNode;
3214 69           xmlChar * elname = NULL;
3215 69           ProxyNodePtr docfrag = NULL;
3216             CODE:
3217 69           elname = nodeSv2C( name , (xmlNodePtr) self);
3218 69 100         if ( !LibXML_test_node_name( elname ) ) {
3219 5           xmlFree( elname );
3220 5           croak( "bad name" );
3221             }
3222              
3223 64           newNode = xmlNewNode(NULL , elname);
3224 64           xmlFree(elname);
3225 64 50         if ( newNode != NULL ) {
3226 64           docfrag = PmmNewFragment( self );
3227 64           newNode->doc = self;
3228 64           xmlAddChild(PmmNODE(docfrag), newNode);
3229 64           RETVAL = PmmNodeToSv(newNode,docfrag);
3230             }
3231             else {
3232             xs_warn( "no node created!" );
3233 0           XSRETURN_UNDEF;
3234             }
3235             OUTPUT:
3236             RETVAL
3237              
3238             SV*
3239             createRawElement( self, name )
3240             xmlDocPtr self
3241             SV* name
3242             PREINIT:
3243             xmlNodePtr newNode;
3244 63           xmlChar * elname = NULL;
3245 63           ProxyNodePtr docfrag = NULL;
3246             CODE:
3247 63           elname = nodeSv2C( name , (xmlNodePtr) self);
3248 63 50         if ( !elname || xmlStrlen(elname) <= 0 ) {
    50          
3249 0           xmlFree( elname );
3250 0           croak( "bad name" );
3251             }
3252              
3253 63           newNode = xmlNewDocNode(self,NULL , elname, NULL);
3254 63           xmlFree(elname);
3255 63 50         if ( newNode != NULL ) {
3256 63           docfrag = PmmNewFragment( self );
3257 63           xmlAddChild(PmmNODE(docfrag), newNode);
3258 63           RETVAL = PmmNodeToSv(newNode,docfrag);
3259             }
3260             else {
3261             xs_warn( "no node created!" );
3262 0           XSRETURN_UNDEF;
3263             }
3264             OUTPUT:
3265             RETVAL
3266              
3267             SV*
3268             createElementNS( self, nsURI, name )
3269             xmlDocPtr self
3270             SV * nsURI
3271             SV * name
3272             PREINIT:
3273 19           xmlChar * ename = NULL;
3274 19           xmlChar * prefix = NULL;
3275 19           xmlChar * localname = NULL;
3276 19           xmlChar * eURI = NULL;
3277 19           xmlNsPtr ns = NULL;
3278 19           ProxyNodePtr docfrag = NULL;
3279 19           xmlNodePtr newNode = NULL;
3280             CODE:
3281 19           ename = nodeSv2C( name , (xmlNodePtr) self );
3282 19 50         if ( !LibXML_test_node_name( ename ) ) {
3283 0           xmlFree( ename );
3284 0           croak( "bad name" );
3285             }
3286              
3287 19           eURI = Sv2C( nsURI , NULL );
3288              
3289 19 50         if ( eURI != NULL && xmlStrlen(eURI)!=0 ){
    50          
3290 19           localname = xmlSplitQName2(ename, &prefix);
3291 19 100         if ( localname == NULL ) {
3292 11           localname = xmlStrdup( ename );
3293             }
3294              
3295 19           ns = xmlNewNs( NULL, eURI, prefix );
3296 19           newNode = xmlNewDocNode( self, ns, localname, NULL );
3297 19           newNode->nsDef = ns;
3298              
3299 19           xmlFree(localname);
3300             }
3301             else {
3302             xs_warn( " ordinary element " );
3303             /* ordinary element */
3304 0           localname = ename;
3305              
3306 0           newNode = xmlNewDocNode( self, NULL , localname, NULL );
3307             }
3308              
3309 19           docfrag = PmmNewFragment( self );
3310 19           xmlAddChild(PmmNODE(docfrag), newNode);
3311 19           RETVAL = PmmNodeToSv(newNode, docfrag);
3312              
3313 19 100         if ( prefix != NULL ) {
3314 8           xmlFree(prefix);
3315             }
3316 19 50         if ( eURI != NULL ) {
3317 19           xmlFree(eURI);
3318             }
3319 19           xmlFree(ename);
3320             OUTPUT:
3321             RETVAL
3322              
3323             SV*
3324             createRawElementNS( self, nsURI, name )
3325             xmlDocPtr self
3326             SV * nsURI
3327             SV * name
3328             PREINIT:
3329 8           xmlChar * ename = NULL;
3330 8           xmlChar * prefix = NULL;
3331 8           xmlChar * localname = NULL;
3332 8           xmlChar * eURI = NULL;
3333 8           xmlNsPtr ns = NULL;
3334 8           ProxyNodePtr docfrag = NULL;
3335 8           xmlNodePtr newNode = NULL;
3336             CODE:
3337 8           ename = nodeSv2C( name , (xmlNodePtr) self );
3338 8 50         if ( !LibXML_test_node_name( ename ) ) {
3339 0           xmlFree( ename );
3340 0           croak( "bad name" );
3341             }
3342              
3343 8           eURI = Sv2C( nsURI , NULL );
3344              
3345 8 50         if ( eURI != NULL && xmlStrlen(eURI)!=0 ){
    50          
3346 8           localname = xmlSplitQName2(ename, &prefix);
3347 8 100         if ( localname == NULL ) {
3348 1           localname = xmlStrdup( ename );
3349             }
3350              
3351 8           newNode = xmlNewDocNode( self,NULL , localname, NULL );
3352              
3353 8           ns = xmlSearchNsByHref( self, newNode, eURI );
3354 8 50         if ( ns == NULL ) {
3355             /* create a new NS if the NS does not already exists */
3356 8           ns = xmlNewNs(newNode, eURI , prefix );
3357             }
3358              
3359 8 50         if ( ns == NULL ) {
3360 0           xmlFreeNode( newNode );
3361 0           xmlFree(eURI);
3362 0           xmlFree(localname);
3363 0 0         if ( prefix != NULL ) {
3364 0           xmlFree(prefix);
3365             }
3366 0           xmlFree(ename);
3367 0           XSRETURN_UNDEF;
3368             }
3369              
3370 8           xmlFree(localname);
3371             }
3372             else {
3373             xs_warn( " ordinary element " );
3374             /* ordinary element */
3375 0           localname = ename;
3376              
3377 0           newNode = xmlNewDocNode( self, NULL , localname, NULL );
3378             }
3379              
3380 8           xmlSetNs(newNode, ns);
3381 8           docfrag = PmmNewFragment( self );
3382 8           xmlAddChild(PmmNODE(docfrag), newNode);
3383 8           RETVAL = PmmNodeToSv(newNode, docfrag);
3384              
3385 8 100         if ( prefix != NULL ) {
3386 7           xmlFree(prefix);
3387             }
3388 8 50         if ( eURI != NULL ) {
3389 8           xmlFree(eURI);
3390             }
3391 8           xmlFree(ename);
3392             OUTPUT:
3393             RETVAL
3394              
3395             SV *
3396             createTextNode( self, content )
3397             xmlDocPtr self
3398             SV * content
3399             PREINIT:
3400             xmlNodePtr newNode;
3401 17           xmlChar * elname = NULL;
3402 17           ProxyNodePtr docfrag = NULL;
3403             CODE:
3404 17           elname = nodeSv2C( content , (xmlNodePtr) self );
3405 17 50         if ( elname != NULL || xmlStrlen(elname) > 0 ) {
    0          
3406 17           newNode = xmlNewDocText( self, elname );
3407 17           xmlFree(elname);
3408 34 50         if ( newNode != NULL ) {
3409 17           docfrag = PmmNewFragment( self );
3410 17           newNode->doc = self;
3411 17           xmlAddChild(PmmNODE(docfrag), newNode);
3412 17           RETVAL = PmmNodeToSv(newNode,docfrag);
3413             }
3414             else {
3415             xs_warn( "no node created!" );
3416 0           XSRETURN_UNDEF;
3417             }
3418             }
3419             else {
3420 0           XSRETURN_UNDEF;
3421             }
3422             OUTPUT:
3423             RETVAL
3424              
3425             SV *
3426             createComment( self , content )
3427             xmlDocPtr self
3428             SV * content
3429             PREINIT:
3430             xmlNodePtr newNode;
3431 6           xmlChar * elname = NULL;
3432 6           ProxyNodePtr docfrag = NULL;
3433             CODE:
3434 6           elname = nodeSv2C( content , (xmlNodePtr) self );
3435 6 50         if ( elname != NULL || xmlStrlen(elname) > 0 ) {
    0          
3436 6           newNode = xmlNewDocComment( self, elname );
3437 6           xmlFree(elname);
3438 12 50         if ( newNode != NULL ) {
3439 6           docfrag = PmmNewFragment( self );
3440 6           newNode->doc = self;
3441 6           xmlAddChild(PmmNODE(docfrag), newNode);
3442             xs_warn( newNode->name );
3443 6           RETVAL = PmmNodeToSv(newNode,docfrag);
3444             }
3445             else {
3446             xs_warn( "no node created!" );
3447 0           XSRETURN_UNDEF;
3448             }
3449             }
3450             else {
3451 0           XSRETURN_UNDEF;
3452             }
3453             OUTPUT:
3454             RETVAL
3455              
3456             SV *
3457             createCDATASection( self, content )
3458             xmlDocPtr self
3459             SV * content
3460             PREINIT:
3461             xmlNodePtr newNode;
3462 6           xmlChar * elname = NULL;
3463 6           ProxyNodePtr docfrag = NULL;
3464             CODE:
3465 6           elname = nodeSv2C( content , (xmlNodePtr)self );
3466 6 50         if ( elname != NULL || xmlStrlen(elname) > 0 ) {
    0          
3467 6           newNode = xmlNewCDataBlock( self, elname, xmlStrlen(elname) );
3468 6           xmlFree(elname);
3469 12 50         if ( newNode != NULL ) {
3470 6           docfrag = PmmNewFragment( self );
3471 6           newNode->doc = self;
3472 6           xmlAddChild(PmmNODE(docfrag), newNode);
3473             xs_warn( "[CDATA section]" );
3474 6           RETVAL = PmmNodeToSv(newNode,docfrag);
3475             }
3476             else {
3477             xs_warn( "no node created!" );
3478 0           XSRETURN_UNDEF;
3479             }
3480             }
3481             else {
3482 0           XSRETURN_UNDEF;
3483             }
3484             OUTPUT:
3485             RETVAL
3486              
3487             SV*
3488             createEntityReference( self , pname )
3489             xmlDocPtr self
3490             SV * pname
3491             PREINIT:
3492             xmlNodePtr newNode;
3493 2           xmlChar * name = Sv2C( pname, NULL );
3494 2           ProxyNodePtr docfrag = NULL;
3495             CODE:
3496 2 50         if ( name == NULL ) {
3497 0           XSRETURN_UNDEF;
3498             }
3499 2           newNode = xmlNewReference( self, name );
3500 2           xmlFree(name);
3501 2 50         if ( newNode == NULL ) {
3502 0           XSRETURN_UNDEF;
3503             }
3504 2           docfrag = PmmNewFragment( self );
3505 2           xmlAddChild(PmmNODE(docfrag), newNode);
3506 2           RETVAL = PmmNodeToSv( newNode, docfrag );
3507             OUTPUT:
3508             RETVAL
3509              
3510             SV*
3511             createAttribute( self, pname, pvalue=&PL_sv_undef )
3512             xmlDocPtr self
3513             SV * pname
3514             SV * pvalue
3515             PREINIT:
3516 11           xmlChar * name = NULL;
3517 11           xmlChar * value = NULL;
3518 11           xmlAttrPtr newAttr = NULL;
3519 11           xmlChar * buffer = NULL;
3520             CODE:
3521 11           name = nodeSv2C( pname , (xmlNodePtr) self );
3522 11 100         if ( !LibXML_test_node_name( name ) ) {
3523 5           xmlFree(name);
3524 5           XSRETURN_UNDEF;
3525             }
3526              
3527 6           value = nodeSv2C( pvalue , (xmlNodePtr) self );
3528             /* unlike xmlSetProp, xmlNewDocProp does not encode entities in value */
3529 6           buffer = xmlEncodeEntitiesReentrant(self, value);
3530 6           newAttr = xmlNewDocProp( self, name, buffer );
3531 6           RETVAL = PmmNodeToSv((xmlNodePtr)newAttr, PmmPROXYNODE(self));
3532              
3533 6           xmlFree(name);
3534 6           xmlFree(buffer);
3535 6 50         if ( value ) {
3536 6           xmlFree(value);
3537             }
3538             OUTPUT:
3539             RETVAL
3540              
3541             SV*
3542             createAttributeNS( self, URI, pname, pvalue=&PL_sv_undef )
3543             xmlDocPtr self
3544             SV * URI
3545             SV * pname
3546             SV * pvalue
3547             PREINIT:
3548 16           xmlChar * name = NULL;
3549 16           xmlChar * value = NULL;
3550 16           xmlChar * prefix = NULL;
3551 16           const xmlChar * pchar = NULL;
3552 16           xmlChar * localname = NULL;
3553 16           xmlChar * nsURI = NULL;
3554 16           xmlAttrPtr newAttr = NULL;
3555 16           xmlNsPtr ns = NULL;
3556             CODE:
3557 16           name = nodeSv2C( pname , (xmlNodePtr) self );
3558 16 100         if ( !LibXML_test_node_name( name ) ) {
3559 5           xmlFree(name);
3560 5           XSRETURN_UNDEF;
3561             }
3562              
3563 11           nsURI = Sv2C( URI , NULL );
3564 11           value = nodeSv2C( pvalue, (xmlNodePtr) self );
3565              
3566 19 100         if ( nsURI != NULL && xmlStrlen(nsURI) > 0 ) {
    50          
3567 9           xmlNodePtr root = xmlDocGetRootElement(self );
3568 9 100         if ( root ) {
3569 8           pchar = xmlStrchr(name, ':');
3570 8 50         if ( pchar != NULL ) {
3571 8           localname = xmlSplitQName2(name, &prefix);
3572             }
3573             else {
3574 0           localname = xmlStrdup( name );
3575             }
3576 8           ns = xmlSearchNsByHref( self, root, nsURI );
3577 8 100         if ( ns == NULL ) {
3578             /* create a new NS if the NS does not already exists */
3579 5           ns = xmlNewNs(root, nsURI , prefix );
3580             }
3581              
3582 8 50         if ( ns == NULL ) {
3583 0           xmlFree(nsURI);
3584 0           xmlFree(localname);
3585 0 0         if ( prefix ) {
3586 0           xmlFree(prefix);
3587             }
3588 0           xmlFree(name);
3589 0 0         if ( value ) {
3590 0           xmlFree(value);
3591             }
3592 0           XSRETURN_UNDEF;
3593             }
3594              
3595 8           newAttr = xmlNewDocProp( self, localname, value );
3596 8           xmlSetNs((xmlNodePtr)newAttr, ns);
3597              
3598 8           RETVAL = PmmNodeToSv((xmlNodePtr)newAttr, PmmPROXYNODE(self) );
3599              
3600 8           xmlFree(nsURI);
3601 8           xmlFree(name);
3602 8 50         if ( prefix ) {
3603 8           xmlFree(prefix);
3604             }
3605 8           xmlFree(localname);
3606 8 50         if ( value ) {
3607 8           xmlFree(value);
3608             }
3609             }
3610             else {
3611 1           croak( "can't create a new namespace on an attribute!" );
3612             xmlFree(name);
3613             if ( value ) {
3614             xmlFree(value);
3615             }
3616             XSRETURN_UNDEF;
3617             }
3618             }
3619             else {
3620             xmlChar *buffer;
3621             /* unlike xmlSetProp, xmlNewDocProp does not encode entities in value */
3622 2           buffer = xmlEncodeEntitiesReentrant(self, value);
3623 2           newAttr = xmlNewDocProp( self, name, buffer );
3624 2           RETVAL = PmmNodeToSv((xmlNodePtr)newAttr,PmmPROXYNODE(self));
3625 2           xmlFree(name);
3626 2           xmlFree(buffer);
3627 2 50         if ( value ) {
3628 2           xmlFree(value);
3629             }
3630             }
3631             OUTPUT:
3632             RETVAL
3633              
3634             SV*
3635             createProcessingInstruction(self, name, value=&PL_sv_undef)
3636             xmlDocPtr self
3637             SV * name
3638             SV * value
3639             ALIAS:
3640             createPI = 1
3641             PREINIT:
3642 4           xmlChar * n = NULL;
3643 4           xmlChar * v = NULL;
3644 4           xmlNodePtr newNode = NULL;
3645 4           ProxyNodePtr docfrag = NULL;
3646             CODE:
3647             PERL_UNUSED_VAR(ix);
3648 4           n = nodeSv2C(name, (xmlNodePtr)self);
3649 4 50         if ( !n ) {
3650 0           XSRETURN_UNDEF;
3651             }
3652 4           v = nodeSv2C(value, (xmlNodePtr)self);
3653 4           newNode = xmlNewPI(n,v);
3654 4           xmlFree(v);
3655 4           xmlFree(n);
3656 4 50         if ( newNode != NULL ) {
3657 4           docfrag = PmmNewFragment( self );
3658 4           newNode->doc = self;
3659 4           xmlAddChild(PmmNODE(docfrag), newNode);
3660 4           RETVAL = PmmNodeToSv(newNode,docfrag);
3661             } else {
3662             xs_warn( "no node created!" );
3663 0           XSRETURN_UNDEF;
3664             }
3665             OUTPUT:
3666             RETVAL
3667              
3668             void
3669             _setDocumentElement( self , proxy )
3670             xmlDocPtr self
3671             SV * proxy
3672             PREINIT:
3673             xmlNodePtr elem, oelem;
3674             INIT:
3675 96           elem = PmmSvNode(proxy);
3676 96 50         if ( elem == NULL ) {
3677 0           XSRETURN_UNDEF;
3678             }
3679             CODE:
3680             /* please correct me if i am wrong: the document element HAS to be
3681             * an ELEMENT NODE
3682             */
3683 96 50         if ( elem->type == XML_ELEMENT_NODE ) {
3684 96 100         if ( self != elem->doc ) {
3685 2           domImportNode( self, elem, 1, 1 );
3686             }
3687              
3688 96           oelem = xmlDocGetRootElement( self );
3689 96 50         if ( oelem == NULL || oelem->_private == NULL ) {
    0          
3690 96           xmlDocSetRootElement( self, elem );
3691             }
3692             else {
3693 0           ProxyNodePtr docfrag = PmmNewFragment( self );
3694 0           xmlReplaceNode( oelem, elem );
3695 0           xmlAddChild( PmmNODE(docfrag), oelem );
3696 0           PmmFixOwner( ((ProxyNodePtr)oelem->_private), docfrag);
3697             }
3698              
3699 96 50         if ( elem->_private != NULL ) {
3700 96 50         PmmFixOwner( SvPROXYNODE(proxy), PmmPROXYNODE(self));
3701             }
3702             } else {
3703 0           croak("setDocumentElement: ELEMENT node required");
3704             }
3705              
3706             SV *
3707             documentElement( self )
3708             xmlDocPtr self
3709             ALIAS:
3710             XML::LibXML::Document::getDocumentElement = 1
3711             PREINIT:
3712             xmlNodePtr elem;
3713             CODE:
3714             PERL_UNUSED_VAR(ix);
3715 253           elem = xmlDocGetRootElement( self );
3716 253 100         if ( elem ) {
3717 158           RETVAL = PmmNodeToSv(elem, PmmPROXYNODE(self));
3718             }
3719             else {
3720 95           XSRETURN_UNDEF;
3721             }
3722             OUTPUT:
3723             RETVAL
3724              
3725             SV *
3726             externalSubset( self )
3727             xmlDocPtr self
3728             PREINIT:
3729             xmlDtdPtr dtd;
3730             CODE:
3731 10 100         if ( self->extSubset == NULL ) {
3732 8           XSRETURN_UNDEF;
3733             }
3734              
3735 2           dtd = self->extSubset;
3736 2           RETVAL = PmmNodeToSv((xmlNodePtr)dtd, PmmPROXYNODE(self));
3737             OUTPUT:
3738             RETVAL
3739              
3740             SV *
3741             internalSubset( self )
3742             xmlDocPtr self
3743             PREINIT:
3744             xmlDtdPtr dtd;
3745             CODE:
3746 41 100         if ( self->intSubset == NULL ) {
3747 5           XSRETURN_UNDEF;
3748             }
3749              
3750 36           dtd = self->intSubset;
3751 36           RETVAL = PmmNodeToSv(INT2PTR(xmlNodePtr,dtd), PmmPROXYNODE(self));
3752             OUTPUT:
3753             RETVAL
3754              
3755             void
3756             setExternalSubset( self, extdtd )
3757             xmlDocPtr self
3758             SV * extdtd
3759             PREINIT:
3760 2           xmlDtdPtr dtd = NULL;
3761 2           xmlDtdPtr olddtd = NULL;
3762             INIT:
3763 2           dtd = (xmlDtdPtr)PmmSvNode(extdtd);
3764 2 50         if ( dtd == NULL ) {
3765 0           croak( "lost DTD node" );
3766             }
3767             CODE:
3768 2 50         if ( dtd && dtd != self->extSubset ) {
    50          
3769 2 50         if ( dtd->doc == NULL ) {
3770 0           xmlSetTreeDoc( (xmlNodePtr) dtd, self );
3771 2 50         } else if ( dtd->doc != self ) {
3772 0           domImportNode( self, (xmlNodePtr) dtd,1,1);
3773             }
3774              
3775 2 100         if ( dtd == self->intSubset ) {
3776 1           xmlUnlinkNode( (xmlNodePtr)dtd );
3777 1           self->intSubset = NULL;
3778             }
3779              
3780 2           olddtd = self->extSubset;
3781 2 50         if ( olddtd && olddtd->_private == NULL ) {
    0          
3782 0           xmlFreeDtd( olddtd );
3783             }
3784 2           self->extSubset = dtd;
3785             }
3786              
3787             void
3788             setInternalSubset( self, extdtd )
3789             xmlDocPtr self
3790             SV * extdtd
3791             PREINIT:
3792 2           xmlDtdPtr dtd = NULL;
3793 2           xmlDtdPtr olddtd = NULL;
3794             INIT:
3795 2           dtd = (xmlDtdPtr)PmmSvNode(extdtd);
3796 2 50         if ( dtd == NULL ) {
3797 0           croak( "lost DTD node" );
3798             }
3799             CODE:
3800 2 50         if ( dtd && dtd != self->intSubset ) {
    50          
3801 2 50         if ( dtd->doc != self ) {
3802 0           croak( "can't import DTDs" );
3803             domImportNode( self, (xmlNodePtr) dtd,1,1);
3804             }
3805              
3806 2 100         if ( dtd == self->extSubset ) {
3807 1           self->extSubset = NULL;
3808             }
3809              
3810 2           olddtd = xmlGetIntSubset( self );
3811 2 100         if( olddtd ) {
3812 1           xmlReplaceNode( (xmlNodePtr)olddtd, (xmlNodePtr) dtd );
3813 1 50         if ( olddtd->_private == NULL ) {
3814 1           xmlFreeDtd( olddtd );
3815             }
3816             }
3817             else {
3818 1 50         if (self->children == NULL)
3819 1           xmlAddChild((xmlNodePtr) self, (xmlNodePtr) dtd);
3820             else
3821 0           xmlAddPrevSibling(self->children, (xmlNodePtr) dtd);
3822             }
3823 2           self->intSubset = dtd;
3824             }
3825              
3826             SV *
3827             removeInternalSubset( self )
3828             xmlDocPtr self
3829             PREINIT:
3830 1           xmlDtdPtr dtd = NULL;
3831             CODE:
3832 1           dtd = xmlGetIntSubset(self);
3833 1 50         if ( !dtd ) {
3834 0           XSRETURN_UNDEF;
3835             }
3836 1           xmlUnlinkNode( (xmlNodePtr)dtd );
3837 1           self->intSubset = NULL;
3838 1           RETVAL = PmmNodeToSv( (xmlNodePtr)dtd, PmmPROXYNODE(self) );
3839             OUTPUT:
3840             RETVAL
3841              
3842             SV *
3843             removeExternalSubset( self )
3844             xmlDocPtr self
3845             PREINIT:
3846 1           xmlDtdPtr dtd = NULL;
3847             CODE:
3848 1           dtd = self->extSubset;
3849 1 50         if ( !dtd ) {
3850 0           XSRETURN_UNDEF;
3851             }
3852 1           self->extSubset = NULL;
3853 1           RETVAL = PmmNodeToSv( (xmlNodePtr)dtd, PmmPROXYNODE(self) );
3854             OUTPUT:
3855             RETVAL
3856              
3857             SV *
3858             importNode( self, node, dummy=0 )
3859             xmlDocPtr self
3860             xmlNodePtr node
3861             int dummy
3862             PREINIT:
3863 4           xmlNodePtr ret = NULL;
3864 4           ProxyNodePtr docfrag = NULL;
3865             CODE:
3866 4 50         if ( node->type == XML_DOCUMENT_NODE
3867 4 50         || node->type == XML_HTML_DOCUMENT_NODE ) {
3868 0           croak( "Can't import Documents!" );
3869             XSRETURN_UNDEF;
3870             }
3871 4 50         if (node->type == XML_DTD_NODE) {
3872 0           croak("Can't import DTD nodes");
3873             }
3874              
3875 4           ret = domImportNode( self, node, 0, 1 );
3876 4 50         if ( ret ) {
3877 4           docfrag = PmmNewFragment( self );
3878 4           xmlAddChild( PmmNODE(docfrag), ret );
3879 4           RETVAL = PmmNodeToSv( ret, docfrag);
3880             }
3881             else {
3882 0           XSRETURN_UNDEF;
3883             }
3884             OUTPUT:
3885             RETVAL
3886              
3887             SV *
3888             adoptNode( self, node )
3889             xmlDocPtr self
3890             xmlNodePtr node
3891             PREINIT:
3892 6           xmlNodePtr ret = NULL;
3893 6           ProxyNodePtr docfrag = NULL;
3894             CODE:
3895 6 50         if ( node->type == XML_DOCUMENT_NODE
3896 6 50         || node->type == XML_HTML_DOCUMENT_NODE ) {
3897 0           croak( "Can't adopt Documents!" );
3898             XSRETURN_UNDEF;
3899             }
3900 6 50         if (node->type == XML_DTD_NODE) {
3901 0           croak("Can't adopt DTD nodes");
3902             }
3903              
3904 6           ret = domImportNode( self, node, 1, 1 );
3905              
3906 6 50         if ( ret ) {
3907 6           docfrag = PmmNewFragment( self );
3908 6           RETVAL = PmmNodeToSv(node, docfrag);
3909 6           xmlAddChild( PmmNODE(docfrag), ret );
3910 6 50         PmmFixOwner(SvPROXYNODE(RETVAL), docfrag);
3911             }
3912             else {
3913 0           XSRETURN_UNDEF;
3914             }
3915             OUTPUT:
3916             RETVAL
3917              
3918             char*
3919             encoding( self )
3920             xmlDocPtr self
3921             ALIAS:
3922             XML::LibXML::Document::getEncoding = 1
3923             XML::LibXML::Document::xmlEncoding = 2
3924             CODE:
3925             PERL_UNUSED_VAR(ix);
3926 23           RETVAL = (char *) self->encoding;
3927             OUTPUT:
3928             RETVAL
3929              
3930             void
3931             setEncoding( self, encoding = NULL )
3932             xmlDocPtr self
3933             char *encoding
3934             PREINIT:
3935 8           int charset = XML_CHAR_ENCODING_ERROR;
3936             CODE:
3937 8 100         if ( self->encoding != NULL ) {
3938 1           xmlFree( (xmlChar*) self->encoding );
3939             }
3940 8 100         if (encoding!=NULL && strlen(encoding)) {
    50          
3941 7           self->encoding = xmlStrdup( (const xmlChar *)encoding );
3942 7           charset = (int)xmlParseCharEncoding( (const char*)self->encoding );
3943 7 50         if ( charset <= 0 ) {
3944 0           charset = XML_CHAR_ENCODING_ERROR;
3945             }
3946             } else {
3947 1           self->encoding=NULL;
3948 1           charset = XML_CHAR_ENCODING_UTF8;
3949             }
3950 8           SetPmmNodeEncoding(self, charset);
3951              
3952              
3953             int
3954             standalone( self )
3955             xmlDocPtr self
3956             ALIAS:
3957             XML::LibXML::Document::xmlStandalone = 1
3958             CODE:
3959             PERL_UNUSED_VAR(ix);
3960 3           RETVAL = self->standalone;
3961             OUTPUT:
3962             RETVAL
3963              
3964             void
3965             setStandalone( self, value = 0 )
3966             xmlDocPtr self
3967             int value
3968             CODE:
3969 1 50         if ( value > 0 ) {
3970 1           self->standalone = 1;
3971             }
3972 0 0         else if ( value < 0 ) {
3973 0           self->standalone = -1;
3974             }
3975             else {
3976 0           self->standalone = 0;
3977             }
3978              
3979             char*
3980             version( self )
3981             xmlDocPtr self
3982             ALIAS:
3983             XML::LibXML::Document::getVersion = 1
3984             XML::LibXML::Document::xmlVersion = 2
3985             CODE:
3986             PERL_UNUSED_VAR(ix);
3987 15           RETVAL = (char *) self->version;
3988             OUTPUT:
3989             RETVAL
3990              
3991             void
3992             setVersion( self, version )
3993             xmlDocPtr self
3994             char *version
3995             CODE:
3996 71 50         if ( self->version != NULL ) {
3997 71           xmlFree( (xmlChar*) self->version );
3998             }
3999 71           self->version = xmlStrdup( (const xmlChar*)version );
4000              
4001             int
4002             compression( self )
4003             xmlDocPtr self
4004             CODE:
4005 1           RETVAL = xmlGetDocCompressMode(self);
4006             OUTPUT:
4007             RETVAL
4008              
4009             void
4010             setCompression( self, zLevel )
4011             xmlDocPtr self
4012             int zLevel
4013             CODE:
4014 0           xmlSetDocCompressMode(self, zLevel);
4015              
4016              
4017             int
4018             is_valid(self, ...)
4019             xmlDocPtr self
4020             PREINIT:
4021             xmlValidCtxt cvp;
4022 3           xmlDtdPtr dtd = NULL;
4023             SV * dtd_sv;
4024 3           PREINIT_SAVED_ERROR
4025             CODE:
4026 3           INIT_ERROR_HANDLER;
4027              
4028 3           cvp.userData = saved_error;
4029 3           cvp.error = (xmlValidityErrorFunc)LibXML_validity_error_ctx;
4030 3           cvp.warning = (xmlValidityWarningFunc)LibXML_validity_warning_ctx;
4031              
4032             /* we need to initialize the node stack, because perl might
4033             * already have messed it up.
4034             */
4035 3           cvp.nodeNr = 0;
4036 3           cvp.nodeTab = NULL;
4037 3           cvp.vstateNr = 0;
4038 3           cvp.vstateTab = NULL;
4039              
4040 3 50         PmmClearPSVI(self);
    50          
    50          
    100          
4041 3 50         PmmInvalidatePSVI(self);
    50          
4042 3 100         if (items > 1) {
4043 2           dtd_sv = ST(1);
4044 2 50         if ( sv_isobject(dtd_sv) && (SvTYPE(SvRV(dtd_sv)) == SVt_PVMG) ) {
    50          
4045 2           dtd = (xmlDtdPtr)PmmSvNode(dtd_sv);
4046             }
4047 2           RETVAL = xmlValidateDtd(&cvp, self, dtd);
4048             }
4049             else {
4050 1           RETVAL = xmlValidateDocument(&cvp, self);
4051             }
4052 3           CLEANUP_ERROR_HANDLER;
4053             /* REPORT_ERROR(1); */
4054             OUTPUT:
4055             RETVAL
4056              
4057             int
4058             validate(self, ...)
4059             xmlDocPtr self
4060             PREINIT:
4061             xmlValidCtxt cvp;
4062             xmlDtdPtr dtd;
4063             SV * dtd_sv;
4064 5           PREINIT_SAVED_ERROR
4065             CODE:
4066 5           INIT_ERROR_HANDLER;
4067              
4068 5           cvp.userData = saved_error;
4069 5           cvp.error = (xmlValidityErrorFunc)LibXML_validity_error_ctx;
4070 5           cvp.warning = (xmlValidityWarningFunc)LibXML_validity_warning_ctx;
4071             /* we need to initialize the node stack, because perl might
4072             * already have messed it up.
4073             */
4074 5           cvp.nodeNr = 0;
4075 5           cvp.nodeTab = NULL;
4076 5           cvp.vstateNr = 0;
4077 5           cvp.vstateTab = NULL;
4078              
4079 5 50         PmmClearPSVI(self);
    50          
    50          
    100          
4080 5 50         PmmInvalidatePSVI(self);
    50          
4081              
4082 5 100         if (items > 1) {
4083 2           dtd_sv = ST(1);
4084 2 50         if ( sv_isobject(dtd_sv) && (SvTYPE(SvRV(dtd_sv)) == SVt_PVMG) ) {
    50          
4085 2           dtd = (xmlDtdPtr)PmmSvNode(dtd_sv);
4086             }
4087             else {
4088 0           CLEANUP_ERROR_HANDLER;
4089 0           croak("is_valid: argument must be a DTD object");
4090             }
4091 2           RETVAL = xmlValidateDtd(&cvp, self , dtd);
4092             }
4093             else {
4094 3           RETVAL = xmlValidateDocument(&cvp, self);
4095             }
4096 5           CLEANUP_ERROR_HANDLER;
4097 5           REPORT_ERROR(RETVAL ? 1 : 0);
4098             OUTPUT:
4099             RETVAL
4100              
4101             SV*
4102             cloneNode( self, deep=0 )
4103             xmlDocPtr self
4104             int deep
4105             PREINIT:
4106 2           xmlDocPtr ret = NULL;
4107             CODE:
4108 2           ret = xmlCopyDoc( self, deep );
4109 2 50         if ( ret == NULL ) {
4110 0           XSRETURN_UNDEF;
4111             }
4112 2           RETVAL = PmmNodeToSv((xmlNodePtr)ret, NULL);
4113             OUTPUT:
4114             RETVAL
4115              
4116             SV*
4117             getElementById( self, id )
4118             xmlDocPtr self
4119             const char * id
4120             ALIAS:
4121             XML::LibXML::Document::getElementsById = 1
4122             PREINIT:
4123             xmlNodePtr elem;
4124             xmlAttrPtr attr;
4125             CODE:
4126             PERL_UNUSED_VAR(ix);
4127 22 50         if ( id != NULL ) {
4128 22           attr = xmlGetID(self, (xmlChar *) id);
4129 22 100         if (attr == NULL)
4130 5           elem = NULL;
4131 17 50         else if (attr->type == XML_ATTRIBUTE_NODE)
4132 17           elem = attr->parent;
4133 0 0         else if (attr->type == XML_ELEMENT_NODE)
4134 0           elem = (xmlNodePtr) attr;
4135             else
4136 0           elem = NULL;
4137 22 100         if (elem != NULL) {
4138 17           RETVAL = PmmNodeToSv(elem, PmmPROXYNODE(self));
4139             }
4140             else {
4141 5           XSRETURN_UNDEF;
4142             }
4143             }
4144             else {
4145 0           XSRETURN_UNDEF;
4146             }
4147             OUTPUT:
4148             RETVAL
4149              
4150             int
4151             indexElements ( self )
4152             xmlDocPtr self
4153             CODE:
4154             #if LIBXML_VERSION >= 20508
4155 0           RETVAL = xmlXPathOrderDocElems( self );
4156             #else
4157             RETVAL = -2;
4158             #endif
4159             OUTPUT:
4160             RETVAL
4161              
4162             MODULE = XML::LibXML PACKAGE = XML::LibXML::Node
4163              
4164             void
4165             DESTROY( node )
4166             SV * node
4167             PREINIT:
4168             int count;
4169             SV *is_shared;
4170             CODE:
4171             #ifdef XML_LIBXML_THREADS
4172             if ( (is_shared = get_sv("XML::LibXML::__threads_shared", 0)) == NULL ) {
4173             is_shared = &PL_sv_undef;
4174             }
4175             if ( SvTRUE(is_shared) ) {
4176             dSP;
4177             ENTER;
4178             SAVETMPS;
4179             PUSHMARK(SP);
4180             XPUSHs(node);
4181             PUTBACK;
4182             count = call_pv("threads::shared::is_shared", G_SCALAR);
4183             SPAGAIN;
4184             if (count != 1)
4185             croak("Couldn't checks if the variable is shared or not\n");
4186             is_shared = POPs;
4187             PUTBACK;
4188             FREETMPS;
4189             LEAVE;
4190             if (is_shared != &PL_sv_undef) {
4191             XSRETURN_UNDEF;
4192             }
4193             }
4194             if( PmmUSEREGISTRY ) {
4195             SvLOCK(PROXY_NODE_REGISTRY_MUTEX);
4196             PmmRegistryREFCNT_dec(SvPROXYNODE(node));
4197             }
4198             #endif
4199 20452 50         PmmREFCNT_dec(SvPROXYNODE(node));
4200             #ifdef XML_LIBXML_THREADS
4201             if( PmmUSEREGISTRY )
4202             SvUNLOCK(PROXY_NODE_REGISTRY_MUTEX);
4203             #endif
4204              
4205             SV*
4206             nodeName( self )
4207             xmlNodePtr self
4208             ALIAS:
4209             XML::LibXML::Node::getName = 1
4210             XML::LibXML::Element::tagName = 2
4211             PREINIT:
4212 253           xmlChar * name = NULL;
4213             CODE:
4214             PERL_UNUSED_VAR(ix);
4215 253           name = (xmlChar*)domName( self );
4216 253 50         if ( name != NULL ) {
4217 253           RETVAL = C2Sv(name,NULL);
4218 253           xmlFree( name );
4219             }
4220             else {
4221 0           XSRETURN_UNDEF;
4222             }
4223             OUTPUT:
4224             RETVAL
4225              
4226             SV*
4227             localname( self )
4228             xmlNodePtr self
4229             ALIAS:
4230             XML::LibXML::Node::getLocalName = 1
4231             XML::LibXML::Attr::name = 2
4232             XML::LibXML::Node::localName = 3
4233             CODE:
4234             PERL_UNUSED_VAR(ix);
4235 126 100         if ( self->type == XML_ELEMENT_NODE
4236 55 50         || self->type == XML_ATTRIBUTE_NODE
4237 0 0         || self->type == XML_ELEMENT_DECL
4238 0 0         || self->type == XML_ATTRIBUTE_DECL ) {
4239 126           RETVAL = C2Sv(self->name,NULL);
4240             }
4241             else {
4242 0           XSRETURN_UNDEF;
4243             }
4244             OUTPUT:
4245             RETVAL
4246              
4247             SV*
4248             prefix( self )
4249             xmlNodePtr self
4250             ALIAS:
4251             XML::LibXML::Node::getPrefix = 1
4252             CODE:
4253             PERL_UNUSED_VAR(ix);
4254 58 100         if( ( self->type == XML_ELEMENT_NODE
4255 14 50         || self->type == XML_ATTRIBUTE_NODE
4256 0 0         || self->type == XML_PI_NODE )
4257 58 100         && self->ns != NULL
4258 11 100         && self->ns->prefix != NULL ) {
4259 6           RETVAL = C2Sv(self->ns->prefix, NULL);
4260             }
4261             else {
4262 52           XSRETURN_UNDEF;
4263             }
4264             OUTPUT:
4265             RETVAL
4266              
4267             SV*
4268             namespaceURI( self )
4269             xmlNodePtr self
4270             ALIAS:
4271             getNamespaceURI = 1
4272             PREINIT:
4273             xmlChar * nsURI;
4274             CODE:
4275             PERL_UNUSED_VAR(ix);
4276 77 100         if ( ( self->type == XML_ELEMENT_NODE
4277 26 50         || self->type == XML_ATTRIBUTE_NODE
4278 0 0         || self->type == XML_PI_NODE )
4279 77 100         && self->ns != NULL
4280 25 50         && self->ns->href != NULL ) {
4281 25           nsURI = xmlStrdup(self->ns->href);
4282 25           RETVAL = C2Sv( nsURI, NULL );
4283 25           xmlFree( nsURI );
4284             }
4285             else {
4286 52           XSRETURN_UNDEF;
4287             }
4288             OUTPUT:
4289             RETVAL
4290              
4291              
4292             SV*
4293             lookupNamespaceURI( self, svprefix=&PL_sv_undef )
4294             xmlNodePtr self
4295             SV * svprefix
4296             PREINIT:
4297             xmlChar * nsURI;
4298 23           xmlChar * prefix = NULL;
4299             xmlNsPtr ns;
4300             CODE:
4301 23           prefix = nodeSv2C( svprefix , self );
4302 23 100         if ( prefix != NULL && xmlStrlen(prefix) == 0) {
    100          
4303 5           xmlFree( prefix );
4304 5           prefix = NULL;
4305             }
4306 23           ns = xmlSearchNs( self->doc, self, prefix );
4307 23 100         if ( prefix != NULL) {
4308 17           xmlFree( prefix );
4309             }
4310 23 100         if ( ns != NULL ) {
4311 16           nsURI = xmlStrdup(ns->href);
4312 16           RETVAL = C2Sv( nsURI, NULL );
4313 16           xmlFree( nsURI );
4314             }
4315             else {
4316 7           XSRETURN_UNDEF;
4317             }
4318             OUTPUT:
4319             RETVAL
4320              
4321             SV*
4322             lookupNamespacePrefix( self, svuri )
4323             xmlNodePtr self
4324             SV * svuri
4325             PREINIT:
4326             xmlChar * nsprefix;
4327 7           xmlChar * href = NULL;
4328             CODE:
4329 7           href = nodeSv2C( svuri , self );
4330 11 50         if ( href != NULL && xmlStrlen(href) > 0) {
    50          
4331 7           xmlNsPtr ns = xmlSearchNsByHref( self->doc, self, href );
4332 7           xmlFree( href );
4333 7 100         if ( ns != NULL ) {
4334 4 100         if ( ns->prefix != NULL ) {
4335 3           nsprefix = xmlStrdup( ns->prefix );
4336 3           RETVAL = C2Sv( nsprefix, NULL );
4337 3           xmlFree(nsprefix);
4338             } else {
4339 4           RETVAL = newSVpv("",0);
4340             }
4341             }
4342             else {
4343 3           XSRETURN_UNDEF;
4344             }
4345             }
4346             else {
4347 0           XSRETURN_UNDEF;
4348             }
4349             OUTPUT:
4350             RETVAL
4351              
4352              
4353             void
4354             setNodeName( self , value )
4355             xmlNodePtr self
4356             SV* value
4357             ALIAS:
4358             setName = 1
4359             PREINIT:
4360             xmlChar* string;
4361             xmlChar* localname;
4362             xmlChar* prefix;
4363             CODE:
4364             PERL_UNUSED_VAR(ix);
4365 11           string = nodeSv2C( value , self );
4366 11 100         if ( !LibXML_test_node_name( string ) ) {
4367 4           xmlFree(string);
4368 4           croak( "bad name" );
4369             }
4370 7 100         if( ( self->type == XML_ELEMENT_NODE
4371 2 50         || self->type == XML_ATTRIBUTE_NODE
4372 0 0         || self->type == XML_PI_NODE)
4373 7 100         && self->ns ){
4374 5           localname = xmlSplitQName2(string, &prefix);
4375 5 100         if ( localname == NULL ) {
4376 3           localname = xmlStrdup( string );
4377             }
4378 5           xmlNodeSetName(self, localname );
4379 5           xmlFree(localname);
4380 5           xmlFree(prefix);
4381             }
4382             else {
4383             xs_warn("node name normal\n");
4384 2           xmlNodeSetName(self, string );
4385             }
4386 7           xmlFree(string);
4387              
4388             void
4389             setRawName( self, value )
4390             xmlNodePtr self
4391             SV * value
4392             PREINIT:
4393             xmlChar* string;
4394             xmlChar* localname;
4395             xmlChar* prefix;
4396             CODE:
4397 0           string = nodeSv2C( value , self );
4398 0 0         if ( !string || xmlStrlen( string) <= 0 ) {
    0          
4399 0           xmlFree(string);
4400 0           XSRETURN_UNDEF;
4401             }
4402 0 0         if( ( self->type == XML_ELEMENT_NODE
4403 0 0         || self->type == XML_ATTRIBUTE_NODE
4404 0 0         || self->type == XML_PI_NODE)
4405 0 0         && self->ns ){
4406 0           localname = xmlSplitQName2(string, &prefix);
4407 0           xmlNodeSetName(self, localname );
4408 0           xmlFree(localname);
4409 0           xmlFree(prefix);
4410             }
4411             else {
4412 0           xmlNodeSetName(self, string );
4413             }
4414 0           xmlFree(string);
4415              
4416              
4417             SV*
4418             nodeValue( self, useDomEncoding = &PL_sv_undef )
4419             xmlNodePtr self
4420             SV * useDomEncoding
4421             ALIAS:
4422             XML::LibXML::Attr::value = 1
4423             XML::LibXML::Attr::getValue = 2
4424             XML::LibXML::Text::data = 3
4425             XML::LibXML::Node::getValue = 4
4426             XML::LibXML::Node::getData = 5
4427             PREINIT:
4428 172           xmlChar * content = NULL;
4429             CODE:
4430             PERL_UNUSED_VAR(ix);
4431 171           content = domGetNodeValue( self );
4432              
4433 171 100         if ( content != NULL ) {
4434 169 50         if ( SvTRUE(useDomEncoding) ) {
    50          
    0          
    50          
    50          
    50          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
4435 0           RETVAL = nodeC2Sv(content, self);
4436             }
4437             else {
4438 169           RETVAL = C2Sv(content, NULL);
4439             }
4440 169           xmlFree(content);
4441             }
4442             else {
4443 2           XSRETURN_UNDEF;
4444             }
4445             OUTPUT:
4446             RETVAL
4447              
4448             int
4449             nodeType( self )
4450             xmlNodePtr self
4451             ALIAS:
4452             XML::LibXML::Node::getType = 1
4453             CODE:
4454             PERL_UNUSED_VAR(ix);
4455 213           RETVAL = self->type;
4456             OUTPUT:
4457             RETVAL
4458              
4459             SV*
4460             parentNode( self )
4461             xmlNodePtr self
4462             ALIAS:
4463             XML::LibXML::Attr::ownerElement = 1
4464             XML::LibXML::Node::getParentNode = 2
4465             XML::LibXML::Attr::getOwnerElement = 3
4466             CODE:
4467             PERL_UNUSED_VAR(ix);
4468 316 50         RETVAL = PmmNodeToSv( self->parent,
4469 158 50         PmmOWNERPO( PmmPROXYNODE(self) ) );
4470             OUTPUT:
4471             RETVAL
4472              
4473             SV*
4474             nextSibling( self )
4475             xmlNodePtr self
4476             ALIAS:
4477             getNextSibling = 1
4478             CODE:
4479             PERL_UNUSED_VAR(ix);
4480 30 50         RETVAL = PmmNodeToSv( self->next,
4481 15 50         PmmOWNERPO(PmmPROXYNODE(self)) );
4482             OUTPUT:
4483             RETVAL
4484              
4485             SV*
4486             nextNonBlankSibling( self )
4487             xmlNodePtr self
4488             PREINIT:
4489             xmlNodePtr next;
4490             CODE:
4491 14           next = self->next;
4492 28 100         while (next != NULL && xmlIsBlankNode(next))
    100          
4493 14           next = next->next;
4494 28 50         RETVAL = PmmNodeToSv( next,
4495 14 50         PmmOWNERPO(PmmPROXYNODE(self)) );
4496             OUTPUT:
4497             RETVAL
4498              
4499              
4500             SV*
4501             previousSibling( self )
4502             xmlNodePtr self
4503             ALIAS:
4504             getPreviousSibling = 1
4505             CODE:
4506             PERL_UNUSED_VAR(ix);
4507 8 50         RETVAL = PmmNodeToSv( self->prev,
4508 4 50         PmmOWNERPO( PmmPROXYNODE(self) ) );
4509             OUTPUT:
4510             RETVAL
4511              
4512             SV*
4513             previousNonBlankSibling( self )
4514             xmlNodePtr self
4515             PREINIT:
4516             xmlNodePtr prev;
4517             CODE:
4518 14           prev = self->prev;
4519 30 100         while (prev != NULL && xmlIsBlankNode(prev))
    100          
4520 16           prev = prev->prev;
4521 28 50         RETVAL = PmmNodeToSv( prev,
4522 14 50         PmmOWNERPO(PmmPROXYNODE(self)) );
4523             OUTPUT:
4524             RETVAL
4525              
4526              
4527             void
4528             _childNodes( self, only_nonblank = 0 )
4529             xmlNodePtr self
4530             int only_nonblank
4531             ALIAS:
4532             XML::LibXML::Node::getChildnodes = 1
4533             PREINIT:
4534             xmlNodePtr cld;
4535             SV * element;
4536 165           int len = 0;
4537 165 50         int wantarray = GIMME_V;
4538             PPCODE:
4539             PERL_UNUSED_VAR(ix);
4540 165 50         if ( self->type != XML_ATTRIBUTE_NODE ) {
4541 165           cld = self->children;
4542             xs_warn("childnodes start");
4543 620 100         while ( cld ) {
4544 455 100         if ( !(only_nonblank && xmlIsBlankNode(cld)) ) {
    100          
4545 439 50         if( wantarray != G_SCALAR ) {
4546 439 50         element = PmmNodeToSv(cld, PmmOWNERPO(PmmPROXYNODE(self)) );
    100          
4547 439 50         XPUSHs(sv_2mortal(element));
4548             }
4549 439           len++;
4550             }
4551 455           cld = cld->next;
4552             }
4553             }
4554 165 50         if ( wantarray == G_SCALAR ) {
4555 0 0         XPUSHs(sv_2mortal(newSViv(len)) );
4556             }
4557              
4558             void
4559             _getChildrenByTagNameNS( self, namespaceURI, node_name )
4560             xmlNodePtr self
4561             SV * namespaceURI
4562             SV * node_name
4563             PREINIT:
4564             xmlChar * name;
4565             xmlChar * nsURI;
4566             xmlNodePtr cld;
4567             SV * element;
4568 12           int len = 0;
4569 12           int name_wildcard = 0;
4570 12           int ns_wildcard = 0;
4571 12 50         int wantarray = GIMME_V;
4572             PPCODE:
4573 12           name = nodeSv2C(node_name, self );
4574 12           nsURI = nodeSv2C(namespaceURI, self );
4575              
4576 12 50         if ( nsURI != NULL ) {
4577 12 50         if (xmlStrlen(nsURI) == 0 ) {
4578 0           xmlFree(nsURI);
4579 0           nsURI = NULL;
4580 12 100         } else if (xmlStrcmp( nsURI, (xmlChar *)"*" )==0) {
4581 9           ns_wildcard = 1;
4582             }
4583             }
4584 12 50         if ( name !=NULL && xmlStrcmp( name, (xmlChar *)"*" ) == 0) {
    100          
4585 6           name_wildcard = 1;
4586             }
4587 12 50         if ( self->type != XML_ATTRIBUTE_NODE ) {
4588 12           cld = self->children;
4589             xs_warn("childnodes start");
4590 48 100         while ( cld ) {
4591 60 100         if (((name_wildcard && (cld->type == XML_ELEMENT_NODE)) ||
4592 24           xmlStrcmp( name, cld->name ) == 0)
4593 24 100         && (ns_wildcard ||
    100          
4594 3 50         (cld->ns != NULL &&
4595 6 50         xmlStrcmp(nsURI,cld->ns->href) == 0 ) ||
4596 3 50         (cld->ns == NULL && nsURI == NULL))) {
4597 21 50         if( wantarray != G_SCALAR ) {
4598 21 50         element = PmmNodeToSv(cld, PmmOWNERPO(PmmPROXYNODE(self)) );
    50          
4599 21 50         XPUSHs(sv_2mortal(element));
4600             }
4601 21           len++;
4602             }
4603 36           cld = cld->next;
4604             }
4605             }
4606 12 50         if ( wantarray == G_SCALAR ) {
4607 0 0         XPUSHs(sv_2mortal(newSViv(len)) );
4608             }
4609 12           xmlFree(name);
4610 12 50         if (nsURI) xmlFree(nsURI);
4611              
4612             SV*
4613             firstChild( self )
4614             xmlNodePtr self
4615             ALIAS:
4616             getFirstChild = 1
4617             CODE:
4618             PERL_UNUSED_VAR(ix);
4619 102 50         RETVAL = PmmNodeToSv( self->children,
4620 51 100         PmmOWNERPO( PmmPROXYNODE(self) ) );
4621             OUTPUT:
4622             RETVAL
4623              
4624             SV*
4625             firstNonBlankChild( self )
4626             xmlNodePtr self
4627             PREINIT:
4628             xmlNodePtr child;
4629             CODE:
4630 2           child = self->children;
4631 4 50         while (child !=NULL && xmlIsBlankNode(child))
    100          
4632 2           child = child->next;
4633 4 50         RETVAL = PmmNodeToSv( child,
4634 2 50         PmmOWNERPO( PmmPROXYNODE(self) ) );
4635             OUTPUT:
4636             RETVAL
4637              
4638             SV*
4639             lastChild( self )
4640             xmlNodePtr self
4641             ALIAS:
4642             getLastChild = 1
4643             CODE:
4644             PERL_UNUSED_VAR(ix);
4645 56 50         RETVAL = PmmNodeToSv( self->last,
4646 28 100         PmmOWNERPO( PmmPROXYNODE(self) ) );
4647             OUTPUT:
4648             RETVAL
4649              
4650             void
4651             _attributes( self )
4652             xmlNodePtr self
4653             ALIAS:
4654             XML::LibXML::Node::getAttributes = 1
4655             PREINIT:
4656 51           xmlAttrPtr attr = NULL;
4657 51           xmlNsPtr ns = NULL;
4658             SV * element;
4659 51           int len=0;
4660 51 50         int wantarray = GIMME_V;
4661             PPCODE:
4662             PERL_UNUSED_VAR(ix);
4663 51 50         if ( self->type != XML_ATTRIBUTE_NODE
4664 51 100         && self->type != XML_DTD_NODE ) {
4665 50           attr = self->properties;
4666 83 100         while ( attr != NULL ) {
4667 33 50         if ( wantarray != G_SCALAR ) {
4668 66 50         element = PmmNodeToSv((xmlNodePtr)attr,
4669 33 50         PmmOWNERPO(PmmPROXYNODE(self)) );
4670 33 50         XPUSHs(sv_2mortal(element));
4671             }
4672 33           attr = attr->next;
4673 33           len++;
4674             }
4675 50 50         if (self->type == XML_ELEMENT_NODE) {
4676 50           ns = self->nsDef;
4677 64 100         while ( ns != NULL ) {
4678 14           const char * CLASS = "XML::LibXML::Namespace";
4679 14 50         if ( wantarray != G_SCALAR ) {
4680             /* namespace handling is kinda odd:
4681             * as soon we have a namespace isolated from its
4682             * owner, we loose the context. therefore it is
4683             * forbidden to access the NS information directly.
4684             * instead the use will receive a copy of the real
4685             * namespace, that can be destroied and is not
4686             * bound to a document.
4687             *
4688             * this avoids segfaults in the end.
4689             */
4690 14 100         if ((ns->prefix != NULL || ns->href != NULL)) {
    50          
4691 14           xmlNsPtr tns = xmlCopyNamespace(ns);
4692 14 50         if ( tns != NULL ) {
4693 14           element = sv_newmortal();
4694 14 50         XPUSHs(sv_setref_pv( element,
4695             (char *)CLASS,
4696             (void*)tns));
4697             }
4698             }
4699             }
4700 14           ns = ns->next;
4701 14           len++;
4702             }
4703             }
4704             }
4705 51 50         if( wantarray == G_SCALAR ) {
4706 0 0         XPUSHs( sv_2mortal(newSViv(len)) );
4707             }
4708              
4709             int
4710             hasChildNodes( self )
4711             xmlNodePtr self
4712             CODE:
4713 125 100         if ( self->type == XML_ATTRIBUTE_NODE ) {
4714 2           RETVAL = 0;
4715             }
4716             else {
4717 123           RETVAL = self->children ? 1 : 0 ;
4718             }
4719             OUTPUT:
4720             RETVAL
4721              
4722             int
4723             hasAttributes( self )
4724             xmlNodePtr self
4725             CODE:
4726 2 50         if ( self->type == XML_ATTRIBUTE_NODE
4727 2 100         || self->type == XML_DTD_NODE ) {
4728 1           RETVAL = 0;
4729             }
4730             else {
4731 1           RETVAL = self->properties ? 1 : 0 ;
4732             }
4733             OUTPUT:
4734             RETVAL
4735              
4736             SV*
4737             ownerDocument( self )
4738             xmlNodePtr self
4739             ALIAS:
4740             XML::LibXML::Node::getOwnerDocument = 1
4741             CODE:
4742             PERL_UNUSED_VAR(ix);
4743             xs_warn( "GET OWNERDOC\n" );
4744 19 50         if( self != NULL
4745 19 100         && self->doc != NULL ){
4746 17           RETVAL = PmmNodeToSv((xmlNodePtr)(self->doc), NULL);
4747             }
4748             else {
4749 2           XSRETURN_UNDEF;
4750             }
4751             OUTPUT:
4752             RETVAL
4753              
4754             SV*
4755             ownerNode( self )
4756             xmlNodePtr self
4757             ALIAS:
4758             XML::LibXML::Node::getOwner = 1
4759             XML::LibXML::Node::getOwnerElement = 2
4760             CODE:
4761             PERL_UNUSED_VAR(ix);
4762 0 0         RETVAL = PmmNodeToSv(PmmNODE(PmmOWNERPO(PmmPROXYNODE(self))), NULL);
    0          
4763             OUTPUT:
4764             RETVAL
4765              
4766              
4767             void
4768             normalize( self )
4769             xmlNodePtr self
4770             CODE:
4771 3           domNodeNormalize( self );
4772              
4773              
4774             SV*
4775             insertBefore( self, nNode, refNode )
4776             xmlNodePtr self
4777             xmlNodePtr nNode
4778             SV * refNode
4779             PREINIT:
4780 9           xmlNodePtr oNode=NULL, rNode;
4781             INIT:
4782 9           oNode = PmmSvNode(refNode);
4783             CODE:
4784 9           rNode = domInsertBefore( self, nNode, oNode );
4785 8 50         if ( rNode != NULL ) {
4786 16 50         RETVAL = PmmNodeToSv( rNode,
4787 8 100         PmmOWNERPO(PmmPROXYNODE(self)) );
4788 8 100         if (rNode->type == XML_DTD_NODE) {
4789 2           LibXML_set_int_subset(self->doc, rNode);
4790             }
4791 8 50         PmmFixOwner(PmmPROXYNODE(rNode), PmmOWNERPO(PmmPROXYNODE(self)));
    100          
4792             }
4793             else {
4794 0           XSRETURN_UNDEF;
4795             }
4796             OUTPUT:
4797             RETVAL
4798              
4799             SV*
4800             insertAfter( self, nNode, refNode )
4801             xmlNodePtr self
4802             xmlNodePtr nNode
4803             SV* refNode
4804             PREINIT:
4805 6           xmlNodePtr oNode = NULL, rNode;
4806             INIT:
4807 6           oNode = PmmSvNode(refNode);
4808             CODE:
4809 6           rNode = domInsertAfter( self, nNode, oNode );
4810 6 50         if ( rNode != NULL ) {
4811 12 50         RETVAL = PmmNodeToSv( rNode,
4812 6 100         PmmOWNERPO(PmmPROXYNODE(self)) );
4813 6 100         if (rNode->type == XML_DTD_NODE) {
4814 2           LibXML_set_int_subset(self->doc, rNode);
4815             }
4816 6 50         PmmFixOwner(PmmPROXYNODE(rNode), PmmOWNERPO(PmmPROXYNODE(self)));
    100          
4817             }
4818             else {
4819 0           XSRETURN_UNDEF;
4820             }
4821             OUTPUT:
4822             RETVAL
4823              
4824             SV*
4825             replaceChild( self, nNode, oNode )
4826             xmlNodePtr self
4827             xmlNodePtr nNode
4828             xmlNodePtr oNode
4829             PREINIT:
4830 5           xmlNodePtr ret = NULL;
4831             CODE:
4832             // if newNode == oldNode or self == newNode then do nothing, just return nNode.
4833 5 50         if (nNode == oNode || self == nNode ) {
    50          
4834 0           ret = nNode;
4835 0 0         RETVAL = PmmNodeToSv(ret, PmmOWNERPO(PmmPROXYNODE(ret)));
    0          
4836             }
4837             else{
4838 5 100         if ( self->type == XML_DOCUMENT_NODE ) {
4839 2           switch ( nNode->type ) {
4840             case XML_ELEMENT_NODE:
4841 0           warn("replaceChild with an element on a document node not supported yet!");
4842 0           XSRETURN_UNDEF;
4843             break;
4844             case XML_DOCUMENT_FRAG_NODE:
4845 0           warn("replaceChild with a document fragment node on a document node not supported yet!");
4846 0           XSRETURN_UNDEF;
4847             break;
4848             case XML_TEXT_NODE:
4849             case XML_CDATA_SECTION_NODE:
4850 0           warn("replaceChild with a text node not supported on a document node!");
4851 0           XSRETURN_UNDEF;
4852             break;
4853             default:
4854 2           break;
4855             }
4856             }
4857 5           ret = domReplaceChild( self, nNode, oNode );
4858 5 50         if (ret == NULL) {
4859 0           XSRETURN_UNDEF;
4860             }
4861             else {
4862 5           LibXML_reparent_removed_node(ret);
4863 5 50         RETVAL = PmmNodeToSv(ret, PmmOWNERPO(PmmPROXYNODE(ret)));
    50          
4864 5 100         if (nNode->type == XML_DTD_NODE) {
4865 2           LibXML_set_int_subset(nNode->doc, nNode);
4866             }
4867 5 50         if ( nNode->_private != NULL ) {
4868 10 50         PmmFixOwner( PmmPROXYNODE(nNode),
4869 5 100         PmmOWNERPO(PmmPROXYNODE(self)) );
4870             }
4871             }
4872             }
4873             OUTPUT:
4874             RETVAL
4875              
4876             SV*
4877             replaceNode( self,nNode )
4878             xmlNodePtr self
4879             xmlNodePtr nNode
4880             PREINIT:
4881 5           xmlNodePtr ret = NULL;
4882 5           ProxyNodePtr owner = NULL;
4883             CODE:
4884 5 50         if ( domIsParent( self, nNode ) == 1 ) {
4885 0           XSRETURN_UNDEF;
4886             }
4887 5 50         owner = PmmOWNERPO(PmmPROXYNODE(self));
    50          
4888              
4889 5 100         if ( self->type != XML_ATTRIBUTE_NODE ) {
4890 4           ret = domReplaceChild( self->parent, nNode, self);
4891             }
4892             else {
4893 1           ret = xmlReplaceNode( self, nNode );
4894             }
4895 5 50         if ( ret ) {
4896 5           LibXML_reparent_removed_node(ret);
4897 5 50         RETVAL = PmmNodeToSv(ret, PmmOWNERPO(PmmPROXYNODE(ret)));
    50          
4898 5 100         if (nNode->type == XML_DTD_NODE) {
4899 3           LibXML_set_int_subset(nNode->doc, nNode);
4900             }
4901 5 50         if ( nNode->_private != NULL ) {
4902 5           PmmFixOwner(PmmPROXYNODE(nNode), owner);
4903             }
4904             }
4905             else {
4906 0           croak( "replacement failed" );
4907             XSRETURN_UNDEF;
4908             }
4909             OUTPUT:
4910             RETVAL
4911              
4912             SV*
4913             removeChild( self, node )
4914             xmlNodePtr self
4915             xmlNodePtr node
4916             PREINIT:
4917             xmlNodePtr ret;
4918             CODE:
4919 15           ret = domRemoveChild( self, node );
4920 15 100         if (ret == NULL) {
4921 1           XSRETURN_UNDEF;
4922             }
4923             else {
4924 14           LibXML_reparent_removed_node(ret);
4925 14           RETVAL = PmmNodeToSv(ret, NULL);
4926             }
4927             OUTPUT:
4928             RETVAL
4929              
4930             void
4931             removeChildNodes( self )
4932             xmlNodePtr self
4933             PREINIT:
4934             xmlNodePtr elem, fragment;
4935             ProxyNodePtr docfrag;
4936             CODE:
4937 2           docfrag = PmmNewFragment( self->doc );
4938 2           fragment = PmmNODE( docfrag );
4939 2           elem = self->children;
4940 6 100         while ( elem ) {
4941 4           xmlNodePtr next = elem->next;
4942 4           xmlUnlinkNode( elem );
4943 4 50         if (elem->type == XML_ATTRIBUTE_NODE
4944 4 100         || elem->type == XML_DTD_NODE) {
4945 1 50         if (PmmPROXYNODE(elem) == NULL) {
4946 0           xmlFreeNode(elem);
4947             }
4948             }
4949             else {
4950             /* this following piece is the function of domAppendChild()
4951             * but in this special case we can avoid most of the logic of
4952             * that function.
4953             */
4954 3 100         if ( fragment->children != NULL ) {
4955             xs_warn("unlink node!\n");
4956 1           domAddNodeToList( elem, fragment->last, NULL );
4957             }
4958             else {
4959 2           fragment->children = elem;
4960 2           fragment->last = elem;
4961 2           elem->parent= fragment;
4962             }
4963 3           PmmFixOwnerNode( elem, docfrag );
4964             }
4965 4           elem = next;
4966             }
4967              
4968 2           self->children = self->last = NULL;
4969 2 50         if ( PmmREFCNT(docfrag) <= 0 ) {
4970             xs_warn( "have not references left" );
4971 2           PmmREFCNT_inc( docfrag );
4972 2           PmmREFCNT_dec( docfrag );
4973             }
4974              
4975             void
4976             unbindNode( self )
4977             xmlNodePtr self
4978             ALIAS:
4979             XML::LibXML::Node::unlink = 1
4980             XML::LibXML::Node::unlinkNode = 2
4981             PREINIT:
4982 10           ProxyNodePtr docfrag = NULL;
4983             CODE:
4984             PERL_UNUSED_VAR(ix);
4985 10 50         if ( self->type != XML_DOCUMENT_NODE
4986 10 50         && self->type != XML_DOCUMENT_FRAG_NODE ) {
4987 10           xmlUnlinkNode( self );
4988 10           LibXML_reparent_removed_node(self);
4989             }
4990              
4991             SV*
4992             appendChild( self, nNode )
4993             xmlNodePtr self
4994             xmlNodePtr nNode
4995             PREINIT:
4996             xmlNodePtr rNode;
4997             CODE:
4998 61 100         if (self->type == XML_DOCUMENT_NODE ) {
4999             /* NOT_SUPPORTED_ERR
5000             */
5001 3           switch ( nNode->type ) {
5002             case XML_ELEMENT_NODE:
5003 1           warn("Appending an element to a document node not supported yet!");
5004 1           XSRETURN_UNDEF;
5005             break;
5006             case XML_DOCUMENT_FRAG_NODE:
5007 0           warn("Appending a document fragment node to a document node not supported yet!");
5008 0           XSRETURN_UNDEF;
5009             break;
5010             case XML_TEXT_NODE:
5011             case XML_CDATA_SECTION_NODE:
5012 0           warn("Appending text node not supported on a document node yet!");
5013 0           XSRETURN_UNDEF;
5014             break;
5015             default:
5016 2           break;
5017             }
5018             }
5019              
5020 60           rNode = domAppendChild( self, nNode );
5021              
5022 59 50         if ( rNode == NULL ) {
5023 0           XSRETURN_UNDEF;
5024             }
5025              
5026 118 50         RETVAL = PmmNodeToSv( nNode,
5027 59 100         PmmOWNERPO(PmmPROXYNODE(self)) );
5028 59 100         if (nNode->type == XML_DTD_NODE) {
5029 1           LibXML_set_int_subset(self->doc, nNode);
5030             }
5031 59 50         PmmFixOwner( SvPROXYNODE(RETVAL), PmmPROXYNODE(self) );
5032             OUTPUT:
5033             RETVAL
5034              
5035             SV*
5036             addChild( self, nNode )
5037             xmlNodePtr self
5038             xmlNodePtr nNode
5039             PREINIT:
5040 39           xmlNodePtr retval = NULL;
5041             ProxyNodePtr proxy;
5042             CODE:
5043 39           switch ( nNode->type ) {
5044             case XML_DOCUMENT_FRAG_NODE:
5045 0           croak("Adding document fragments with addChild not supported!");
5046             XSRETURN_UNDEF;
5047             case XML_DOCUMENT_NODE :
5048             case XML_HTML_DOCUMENT_NODE :
5049             case XML_DOCB_DOCUMENT_NODE :
5050 0           croak("addChild: HIERARCHY_REQUEST_ERR\n");
5051             XSRETURN_UNDEF;
5052             case XML_NOTATION_NODE :
5053             case XML_NAMESPACE_DECL :
5054             case XML_DTD_NODE :
5055             case XML_DOCUMENT_TYPE_NODE :
5056             case XML_ENTITY_DECL :
5057             case XML_ELEMENT_DECL :
5058             case XML_ATTRIBUTE_DECL :
5059 0           croak("addChild: unsupported node type!");
5060             XSRETURN_UNDEF;
5061             default:
5062 39           break;
5063             }
5064              
5065 39           xmlUnlinkNode(nNode);
5066 39           proxy = PmmPROXYNODE(nNode);
5067 39           retval = xmlAddChild( self, nNode );
5068              
5069 39 50         if ( retval == NULL ) {
5070 0           croak( "Error: addChild failed (check node types)!\n" );
5071             }
5072              
5073 39 100         if ( retval != nNode ) {
5074             xs_warn( "node was lost during operation\n" );
5075 1           PmmNODE(proxy) = NULL;
5076             }
5077              
5078 78 50         RETVAL = PmmNodeToSv( retval,
5079 39 100         PmmOWNERPO(PmmPROXYNODE(self)) );
5080 39 100         if ( retval != self ) {
5081 38 50         PmmFixOwner( SvPROXYNODE(RETVAL), PmmPROXYNODE(self) );
5082             }
5083             OUTPUT:
5084             RETVAL
5085              
5086              
5087             SV*
5088             addSibling( self, nNode )
5089             xmlNodePtr self
5090             xmlNodePtr nNode
5091             PREINIT:
5092 6           xmlNodePtr ret = NULL;
5093 6           ProxyNodePtr owner = NULL;
5094             CODE:
5095 6 50         if ( nNode->type == XML_DOCUMENT_FRAG_NODE ) {
5096 0           croak("Adding document fragments with addSibling not yet supported!");
5097             XSRETURN_UNDEF;
5098             }
5099 6 50         owner = PmmOWNERPO(PmmPROXYNODE(self));
    50          
5100              
5101 6 100         if (self->type == XML_TEXT_NODE && nNode->type == XML_TEXT_NODE
    50          
5102 2 50         && self->name == nNode->name) {
5103             /* As a result of text merging, the added node may be freed. */
5104 1           xmlNodePtr copy = xmlCopyNode(nNode, 0);
5105 1           ret = xmlAddSibling(self, copy);
5106              
5107 1 50         if (ret) {
5108 1           RETVAL = PmmNodeToSv(ret, owner);
5109             /* Unlink original node. */
5110 1           xmlUnlinkNode(nNode);
5111 1           LibXML_reparent_removed_node(nNode);
5112             }
5113             else {
5114 0           xmlFreeNode(copy);
5115 0           XSRETURN_UNDEF;
5116             }
5117             }
5118             else {
5119 5           ret = xmlAddSibling( self, nNode );
5120              
5121 5 50         if ( ret ) {
5122 5           RETVAL = PmmNodeToSv(ret, owner);
5123 5 100         if (nNode->type == XML_DTD_NODE) {
5124 2           LibXML_set_int_subset(self->doc, nNode);
5125             }
5126 5 50         PmmFixOwner(SvPROXYNODE(RETVAL), owner);
5127             }
5128             else {
5129 0           XSRETURN_UNDEF;
5130             }
5131             }
5132             OUTPUT:
5133             RETVAL
5134              
5135             SV*
5136             cloneNode( self, deep=0 )
5137             xmlNodePtr self
5138             int deep
5139             PREINIT:
5140             xmlNodePtr ret;
5141 6           xmlDocPtr doc = NULL;
5142 6           ProxyNodePtr docfrag = NULL;
5143             CODE:
5144 6           ret = PmmCloneNode( self, deep );
5145 6 50         if ( ret == NULL ) {
5146 0           XSRETURN_UNDEF;
5147             }
5148              
5149 6 100         if ( ret->type == XML_DTD_NODE ) {
5150 1           RETVAL = PmmNodeToSv(ret, NULL);
5151             }
5152             else {
5153 5           doc = self->doc;
5154              
5155 5 50         if ( doc != NULL ) {
5156 5           xmlSetTreeDoc(ret, doc); /* setting to self, no need to clear psvi */
5157             }
5158              
5159 5           docfrag = PmmNewFragment( doc );
5160 5           xmlAddChild( PmmNODE(docfrag), ret );
5161 5           RETVAL = PmmNodeToSv(ret, docfrag);
5162             }
5163             OUTPUT:
5164             RETVAL
5165              
5166             int
5167             isSameNode( self, oNode )
5168             xmlNodePtr self
5169             xmlNodePtr oNode
5170             ALIAS:
5171             XML::LibXML::Node::isEqual = 1
5172             CODE:
5173             PERL_UNUSED_VAR(ix);
5174 152           RETVAL = ( self == oNode ) ? 1 : 0;
5175             OUTPUT:
5176             RETVAL
5177              
5178             IV
5179             unique_key( self )
5180             xmlNodePtr self
5181             CODE:
5182             /* Cast pointer to IV */
5183 50           RETVAL = PTR2IV(self);
5184             OUTPUT:
5185             RETVAL
5186              
5187             SV *
5188             baseURI( self )
5189             xmlNodePtr self
5190             PREINIT:
5191             xmlChar * uri;
5192             CODE:
5193 13           uri = xmlNodeGetBase( self->doc, self );
5194 13           RETVAL = C2Sv( uri, NULL );
5195 13           xmlFree( uri );
5196             OUTPUT:
5197             RETVAL
5198              
5199             void
5200             setBaseURI( self, URI )
5201             xmlNodePtr self
5202             SV * URI
5203             PREINIT:
5204             xmlChar * uri;
5205             CODE:
5206 7           uri = nodeSv2C( URI, self );
5207 7 50         if ( uri != NULL ) {
5208 7           xmlNodeSetBase( self, uri );
5209             }
5210              
5211             SV*
5212             toString( self, format=0, useDomEncoding = &PL_sv_undef )
5213             xmlNodePtr self
5214             SV * useDomEncoding
5215             int format
5216             ALIAS:
5217             XML::LibXML::Node::serialize = 1
5218             PREINIT:
5219             xmlBufferPtr buffer;
5220 156           const xmlChar *ret = NULL;
5221 156           SV* internalFlag = NULL;
5222 156           int oldTagFlag = xmlSaveNoEmptyTags;
5223             CODE:
5224             PERL_UNUSED_VAR(ix);
5225 156           internalFlag = get_sv("XML::LibXML::setTagCompression", 0);
5226              
5227 156 50         if ( internalFlag ) {
5228 156 50         xmlSaveNoEmptyTags = SvTRUE(internalFlag);
    50          
    0          
    50          
    0          
    0          
    50          
    0          
    0          
    0          
    0          
    0          
    50          
    50          
    100          
    50          
    0          
    100          
    0          
5229             }
5230 156           buffer = xmlBufferCreate();
5231              
5232 156 100         if ( format <= 0 ) {
5233 152           xmlNodeDump( buffer,
5234 152           self->doc,
5235             self, 0, format);
5236             }
5237             else {
5238 4           int t_indent_var = xmlIndentTreeOutput;
5239 4           xmlIndentTreeOutput = 1;
5240 4           xmlNodeDump( buffer,
5241 4           self->doc,
5242             self, 0, format);
5243 4           xmlIndentTreeOutput = t_indent_var;
5244             }
5245              
5246 156           ret = xmlBufferContent( buffer );
5247              
5248 156           xmlSaveNoEmptyTags = oldTagFlag;
5249              
5250 156 50         if ( ret != NULL ) {
5251 156 100         if ( useDomEncoding != &PL_sv_undef && SvTRUE(useDomEncoding) ) {
    50          
    50          
    0          
    50          
    0          
    0          
    50          
    0          
    0          
    0          
    0          
    0          
    50          
    50          
    50          
    0          
    0          
    50          
    0          
5252 2           RETVAL = nodeC2Sv((xmlChar*)ret, PmmNODE(PmmPROXYNODE(self))) ;
5253 2           SvUTF8_off(RETVAL);
5254             }
5255             else {
5256 154           RETVAL = C2Sv((xmlChar*)ret, NULL) ;
5257             }
5258 156           xmlBufferFree( buffer );
5259             }
5260             else {
5261 0           xmlBufferFree( buffer );
5262             xs_warn("Failed to convert node to string");
5263 0           XSRETURN_UNDEF;
5264             }
5265             OUTPUT:
5266             RETVAL
5267              
5268              
5269             SV *
5270             _toStringC14N(self, comments=0, xpath=&PL_sv_undef, exclusive=0, inc_prefix_list=NULL, xpath_context)
5271             xmlNodePtr self
5272             int comments
5273             SV * xpath
5274             int exclusive
5275             char** inc_prefix_list
5276             SV * xpath_context
5277              
5278             PREINIT:
5279 24           xmlChar *result = NULL;
5280 24           xmlChar *nodepath = NULL;
5281 24           xmlXPathContextPtr child_ctxt = NULL;
5282 24           xmlXPathObjectPtr xpath_res = NULL;
5283 24           xmlNodeSetPtr nodelist = NULL;
5284 24           xmlNodePtr refNode = NULL;
5285 24           PREINIT_SAVED_ERROR
5286             INIT:
5287             /* due to how c14n is implemented, the nodeset it receives must
5288             include child nodes; ie, child nodes aren't assumed to be rendered.
5289             so we use an xpath expression to find all of the child nodes. */
5290              
5291 24 50         if ( self->doc == NULL ) {
5292 0           croak("Node passed to toStringC14N must be part of a document");
5293             }
5294              
5295 24           refNode = self;
5296             CODE:
5297 24 50         if ( xpath != NULL && xpath != &PL_sv_undef ) {
    100          
5298 11           nodepath = Sv2C( xpath, NULL );
5299             }
5300              
5301 24 100         if ( nodepath != NULL && xmlStrlen( nodepath ) == 0 ) {
    50          
5302 0           xmlFree( nodepath );
5303 0           nodepath = NULL;
5304             }
5305              
5306 24 100         if ( nodepath == NULL
5307 13 100         && self->type != XML_DOCUMENT_NODE
5308 3 50         && self->type != XML_HTML_DOCUMENT_NODE
5309 3 50         && self->type != XML_DOCB_DOCUMENT_NODE
5310             ) {
5311 3 50         if (comments)
5312 0           nodepath = xmlStrdup( (const xmlChar *) "(. | .//node() | .//@* | .//namespace::*)" );
5313             else
5314 3           nodepath = xmlStrdup( (const xmlChar *) "(. | .//node() | .//@* | .//namespace::*)[not(self::comment())]" );
5315             }
5316              
5317 24 100         if ( nodepath != NULL ) {
5318 14 100         if ( self->type == XML_DOCUMENT_NODE
5319 4 50         || self->type == XML_HTML_DOCUMENT_NODE
5320 4 50         || self->type == XML_DOCB_DOCUMENT_NODE ) {
5321 10           refNode = xmlDocGetRootElement( self->doc );
5322             }
5323 14 100         if (SvOK(xpath_context)) {
    50          
    50          
5324 2 50         child_ctxt = INT2PTR(xmlXPathContextPtr,SvIV(SvRV(xpath_context)));
5325 2 50         if ( child_ctxt == NULL ) {
5326 0           croak("XPathContext: missing xpath context\n");
5327             }
5328             } else {
5329 12           xpath_context = NULL;
5330 12           child_ctxt = xmlXPathNewContext(self->doc);
5331             }
5332 14 50         if (!child_ctxt) {
5333 0 0         if ( nodepath != NULL ) {
5334 0           xmlFree( nodepath );
5335             }
5336 0           croak("Failed to create xpath context");
5337             }
5338              
5339 14           child_ctxt->node = self;
5340 14           LibXML_configure_namespaces(child_ctxt);
5341              
5342 14           xpath_res = xmlXPathEval(nodepath, child_ctxt);
5343 14 100         if (child_ctxt->namespaces != NULL) {
5344 13           xmlFree( child_ctxt->namespaces );
5345 13           child_ctxt->namespaces = NULL;
5346             }
5347 14 100         if (!xpath_context) xmlXPathFreeContext(child_ctxt);
5348 14 50         if ( nodepath != NULL ) {
5349 14           xmlFree( nodepath );
5350             }
5351              
5352 14 50         if (xpath_res == NULL) {
5353 0           croak("2 Failed to compile xpath expression");
5354             }
5355              
5356 14           nodelist = xpath_res->nodesetval;
5357 14 50         if ( nodelist == NULL ) {
5358 0           xmlXPathFreeObject(xpath_res);
5359 0           croak( "cannot canonize empty nodeset!" );
5360             }
5361             }
5362              
5363 24           INIT_ERROR_HANDLER;
5364              
5365 24           xmlC14NDocDumpMemory( self->doc,
5366             nodelist,
5367             exclusive, (xmlChar **) inc_prefix_list,
5368             comments,
5369             &result );
5370              
5371 24 100         if ( xpath_res ) xmlXPathFreeObject(xpath_res);
5372 24           CLEANUP_ERROR_HANDLER;
5373 24           REPORT_ERROR(0);
5374              
5375 24 50         if (result == NULL) {
5376 0           croak("Failed to convert doc to string in doc->toStringC14N");
5377             } else {
5378 24           RETVAL = C2Sv( result, NULL );
5379 24           xmlFree(result);
5380             }
5381             OUTPUT:
5382             RETVAL
5383              
5384             SV*
5385             string_value ( self, useDomEncoding = &PL_sv_undef )
5386             xmlNodePtr self
5387             SV * useDomEncoding
5388             ALIAS:
5389             to_literal = 1
5390             textContent = 2
5391             PREINIT:
5392 100           xmlChar * string = NULL;
5393             CODE:
5394             PERL_UNUSED_VAR(ix);
5395             /* we can't just return a string, because of UTF8! */
5396 100           string = xmlXPathCastNodeToString(self);
5397 100 50         if ( SvTRUE(useDomEncoding) ) {
    50          
    0          
    100          
    50          
    50          
    50          
    0          
    0          
    0          
    0          
    0          
    50          
    50          
    50          
    0          
    0          
    50          
    0          
5398 1           RETVAL = nodeC2Sv(string,
5399             self);
5400             }
5401             else {
5402 99           RETVAL = C2Sv(string,
5403             NULL);
5404             }
5405 100           xmlFree(string);
5406             OUTPUT:
5407             RETVAL
5408              
5409             double
5410             to_number ( self )
5411             xmlNodePtr self
5412             CODE:
5413 0           RETVAL = xmlXPathCastNodeToNumber(self);
5414             OUTPUT:
5415             RETVAL
5416              
5417              
5418             void
5419             _find( pnode, pxpath, to_bool )
5420             SV* pnode
5421             SV * pxpath
5422             int to_bool
5423             PREINIT:
5424 54           xmlNodePtr node = PmmSvNode(pnode);
5425 54           ProxyNodePtr owner = NULL;
5426 54           xmlXPathObjectPtr found = NULL;
5427 54           xmlNodeSetPtr nodelist = NULL;
5428 54           xmlChar * xpath = NULL;
5429 54           xmlXPathCompExprPtr comp = NULL;
5430 54           PREINIT_SAVED_ERROR
5431             INIT:
5432 54 50         if ( node == NULL ) {
5433 0           croak( "lost node" );
5434             }
5435 54 100         if (sv_isobject(pxpath) && sv_isa(pxpath,"XML::LibXML::XPathExpression")) {
    50          
5436 3 50         comp = INT2PTR(xmlXPathCompExprPtr,SvIV((SV*)SvRV( pxpath )));
5437 3 50         if (!comp) XSRETURN_UNDEF;
5438             } else {
5439 51           xpath = nodeSv2C(pxpath, node);
5440 51 50         if ( !(xpath && xmlStrlen(xpath)) ) {
    50          
5441             xs_warn( "bad xpath\n" );
5442 0 0         if ( xpath )
5443 0           xmlFree(xpath);
5444 0           croak( "empty XPath found" );
5445             XSRETURN_UNDEF;
5446             }
5447             }
5448             PPCODE:
5449 54           INIT_ERROR_HANDLER;
5450 54 100         if (comp) {
5451 3           found = domXPathCompFind( node, comp, to_bool );
5452             } else {
5453 51           found = domXPathFind( node, xpath, to_bool );
5454 51           xmlFree( xpath );
5455             }
5456 54           CLEANUP_ERROR_HANDLER;
5457 54 100         if (found) {
5458 42           REPORT_ERROR(1);
5459 42           switch (found->type) {
5460             case XPATH_NODESET:
5461             /* return as a NodeList */
5462             /* access ->nodesetval */
5463 25 50         XPUSHs(sv_2mortal(newSVpv("XML::LibXML::NodeList", 0)));
5464 25           nodelist = found->nodesetval;
5465 25 50         if ( nodelist ) {
5466 25 50         if ( nodelist->nodeNr > 0 ) {
5467             int i;
5468 25           const char * cls = "XML::LibXML::Node";
5469             xmlNodePtr tnode;
5470             SV * element;
5471 25           int l = nodelist->nodeNr;
5472              
5473 25 50         owner = PmmOWNERPO(SvPROXYNODE(pnode));
    50          
    0          
    50          
    100          
    50          
    50          
5474 65 100         for( i=0 ; i < l; i++){
5475             /* we have to create a new instance of an
5476             * objectptr. and then
5477             * place the current node into the new
5478             * object. afterwards we can
5479             * push the object to the array!
5480             */
5481 40           tnode = nodelist->nodeTab[i];
5482              
5483             /* let's be paranoid */
5484 40 50         if (tnode->type == XML_NAMESPACE_DECL) {
5485 0           xmlNsPtr newns = xmlCopyNamespace((xmlNsPtr)tnode);
5486 0 0         if ( newns != NULL ) {
5487 0           element = NEWSV(0,0);
5488 0           cls = PmmNodeTypeName( tnode );
5489 0           element = sv_setref_pv( element,
5490             (const char *)cls,
5491             (void*)newns
5492             );
5493             }
5494             else {
5495 0           continue;
5496             }
5497             }
5498             else {
5499 40           element = PmmNodeToSv(tnode, owner);
5500             }
5501              
5502 40 50         XPUSHs( sv_2mortal(element) );
5503             }
5504             }
5505 25           xmlXPathFreeNodeSet( found->nodesetval );
5506 25           found->nodesetval = NULL;
5507             }
5508 25           break;
5509             case XPATH_BOOLEAN:
5510             /* return as a Boolean */
5511             /* access ->boolval */
5512 12 50         XPUSHs(sv_2mortal(newSVpv("XML::LibXML::Boolean", 0)));
5513 12 50         XPUSHs(sv_2mortal(newSViv(found->boolval)));
5514 12           break;
5515             case XPATH_NUMBER:
5516             /* return as a Number */
5517             /* access ->floatval */
5518 2 50         XPUSHs(sv_2mortal(newSVpv("XML::LibXML::Number", 0)));
5519 2 50         XPUSHs(sv_2mortal(newSVnv(found->floatval)));
5520 2           break;
5521             case XPATH_STRING:
5522             /* access ->stringval */
5523             /* return as a Literal */
5524 3 50         XPUSHs(sv_2mortal(newSVpv("XML::LibXML::Literal", 0)));
5525 3 50         XPUSHs(sv_2mortal(C2Sv(found->stringval, NULL)));
5526 3           break;
5527             default:
5528 0           croak("Unknown XPath return type");
5529             }
5530 42           xmlXPathFreeObject(found);
5531             } else {
5532 12           REPORT_ERROR(0);
5533             }
5534              
5535             void
5536             _findnodes( pnode, perl_xpath )
5537             SV* pnode
5538             SV * perl_xpath
5539             PREINIT:
5540 95           xmlNodePtr node = PmmSvNode(pnode);
5541 95           ProxyNodePtr owner = NULL;
5542 95           xmlNodeSetPtr nodelist = NULL;
5543 95           SV * element = NULL ;
5544 95           xmlChar * xpath = NULL ;
5545 95           xmlXPathCompExprPtr comp = NULL;
5546 95           PREINIT_SAVED_ERROR
5547             INIT:
5548 95 50         if ( node == NULL ) {
5549 0 0         if ( xpath )
5550 0           xmlFree(xpath);
5551 0           croak( "lost node" );
5552             }
5553 95 100         if (sv_isobject(perl_xpath) && sv_isa(perl_xpath,"XML::LibXML::XPathExpression")) {
    50          
5554 3 50         comp = INT2PTR(xmlXPathCompExprPtr,SvIV((SV*)SvRV( perl_xpath )));
5555 3 50         if (!comp) XSRETURN_UNDEF;
5556             } else {
5557 92           xpath = nodeSv2C(perl_xpath, node);
5558 92 50         if ( !(xpath && xmlStrlen(xpath)) ) {
    50          
5559             xs_warn( "bad xpath\n" );
5560 0 0         if ( xpath )
5561 0           xmlFree(xpath);
5562 0           croak( "empty XPath found" );
5563             XSRETURN_UNDEF;
5564             }
5565             }
5566             PPCODE:
5567 95           INIT_ERROR_HANDLER;
5568 95 100         if (comp) {
5569 3           nodelist = domXPathCompSelect( node, comp );
5570             } else {
5571 92           nodelist = domXPathSelect( node, xpath );
5572 92           xmlFree(xpath);
5573             }
5574 95           CLEANUP_ERROR_HANDLER;
5575              
5576 95 100         if ( nodelist ) {
5577 87           REPORT_ERROR(1);
5578 87 100         if ( nodelist->nodeNr > 0 ) {
5579             int i;
5580 81           int len = nodelist->nodeNr;
5581 81           const char * cls = "XML::LibXML::Node";
5582             xmlNodePtr tnode;
5583 81 50         owner = PmmOWNERPO(SvPROXYNODE(pnode));
    50          
    0          
    50          
    100          
    50          
    50          
5584              
5585 6280 100         for(i=0 ; i < len; i++){
5586             /* we have to create a new instance of an objectptr.
5587             * and then place the current node into the new object.
5588             * afterwards we can push the object to the array!
5589             */
5590 6199           element = NULL;
5591 6199           tnode = nodelist->nodeTab[i];
5592 6199 100         if (tnode->type == XML_NAMESPACE_DECL) {
5593 3           xmlNsPtr newns = xmlCopyNamespace((xmlNsPtr)tnode);
5594 3 100         if ( newns != NULL ) {
5595 2           element = NEWSV(0,0);
5596 2           cls = PmmNodeTypeName( tnode );
5597 2           element = sv_setref_pv( element,
5598             (const char *)cls,
5599             newns
5600             );
5601             }
5602             else {
5603 3           continue;
5604             }
5605             }
5606             else {
5607 6196           element = PmmNodeToSv(tnode, owner);
5608             }
5609              
5610 6198 100         XPUSHs( sv_2mortal(element) );
5611             }
5612             }
5613 87           xmlXPathFreeNodeSet( nodelist );
5614             } else {
5615 8           REPORT_ERROR(0);
5616             }
5617              
5618             void
5619             getNamespaces( pnode )
5620             SV * pnode
5621             ALIAS:
5622             namespaces = 1
5623             PREINIT:
5624             xmlNodePtr node;
5625 37           xmlNsPtr ns = NULL;
5626 37           xmlNsPtr newns = NULL;
5627 37           SV* element = &PL_sv_undef;
5628 37           const char * class = "XML::LibXML::Namespace";
5629             INIT:
5630             PERL_UNUSED_VAR(ix);
5631 37           node = PmmSvNode(pnode);
5632 37 50         if ( node == NULL ) {
5633 0           croak( "lost node" );
5634             }
5635             PPCODE:
5636 37 50         if (node->type == XML_ELEMENT_NODE) {
5637 37           ns = node->nsDef;
5638 42 100         while ( ns != NULL ) {
5639 5 100         if (ns->prefix != NULL || ns->href != NULL) {
    50          
5640 5           newns = xmlCopyNamespace(ns);
5641 5 50         if ( newns != NULL ) {
5642 5           element = NEWSV(0,0);
5643 5           element = sv_setref_pv( element,
5644             (const char *)class,
5645             (void*)newns
5646             );
5647 5 50         XPUSHs( sv_2mortal(element) );
5648             }
5649             }
5650 5           ns = ns->next;
5651             }
5652             }
5653              
5654             SV *
5655             getNamespace( node )
5656             xmlNodePtr node
5657             ALIAS:
5658             localNamespace = 1
5659             localNS = 2
5660             PREINIT:
5661 1           xmlNsPtr ns = NULL;
5662 1           xmlNsPtr newns = NULL;
5663 1           const char * class = "XML::LibXML::Namespace";
5664             CODE:
5665             PERL_UNUSED_VAR(ix);
5666 1 50         if ( node->type == XML_ELEMENT_NODE
5667 0 0         || node->type == XML_ATTRIBUTE_NODE
5668 0 0         || node->type == XML_PI_NODE ) {
5669 1           ns = node->ns;
5670 2 50         if ( ns != NULL ) {
5671 1           newns = xmlCopyNamespace(ns);
5672 1 50         if ( newns != NULL ) {
5673 1           RETVAL = NEWSV(0,0);
5674 1           RETVAL = sv_setref_pv( RETVAL,
5675             (const char *)class,
5676             (void*)newns
5677             );
5678             } else {
5679 0           XSRETURN_UNDEF;
5680             }
5681             }
5682             else {
5683 0           XSRETURN_UNDEF;
5684             }
5685             } else {
5686 0           XSRETURN_UNDEF;
5687             }
5688             OUTPUT:
5689             RETVAL
5690              
5691              
5692             SV *
5693             nodePath( self )
5694             xmlNodePtr self
5695             PREINIT:
5696 3           xmlChar * path = NULL;
5697             CODE:
5698 3           path = xmlGetNodePath( self );
5699 3 50         if ( path == NULL ) {
5700 0           croak( "cannot calculate path for the given node" );
5701             }
5702 3           RETVAL = C2Sv( path, NULL );
5703 3           xmlFree(path);
5704             OUTPUT:
5705             RETVAL
5706              
5707             int
5708             line_number( self )
5709             xmlNodePtr self
5710             CODE:
5711 5           RETVAL = xmlGetLineNo( self );
5712             OUTPUT:
5713             RETVAL
5714              
5715             MODULE = XML::LibXML PACKAGE = XML::LibXML::Element
5716              
5717             SV*
5718             new(CLASS, name )
5719             char * name
5720             PREINIT:
5721             xmlNodePtr newNode;
5722 13           ProxyNodePtr docfrag = NULL;
5723             CODE:
5724 13           docfrag = PmmNewFragment(NULL);
5725 13           newNode = xmlNewNode( NULL, (const xmlChar*)name );
5726 13           newNode->doc = NULL;
5727 13           xmlAddChild(PmmNODE(docfrag), newNode);
5728 13           RETVAL = PmmNodeToSv(newNode, docfrag );
5729             OUTPUT:
5730             RETVAL
5731              
5732             int
5733             _setNamespace(self, namespaceURI, namespacePrefix = &PL_sv_undef, flag = 1 )
5734             SV * self
5735             SV * namespaceURI
5736             SV * namespacePrefix
5737             int flag
5738             PREINIT:
5739 33           xmlNodePtr node = PmmSvNode(self);
5740 33           xmlChar * nsURI = nodeSv2C(namespaceURI,node);
5741 33           xmlChar * nsPrefix = NULL;
5742 33           xmlNsPtr ns = NULL;
5743             INIT:
5744 33 50         if ( node == NULL ) {
5745 0           croak( "lost node" );
5746             }
5747             CODE:
5748             /* if ( !nsURI ){
5749             XSRETURN_UNDEF;
5750             } */
5751              
5752 33           nsPrefix = nodeSv2C(namespacePrefix, node);
5753 33 100         if ( xmlStrlen( nsPrefix ) == 0 ) {
5754 1           xmlFree(nsPrefix);
5755 1           nsPrefix = NULL;
5756             }
5757 33 100         if ( xmlStrlen( nsURI ) == 0 ) {
5758 1           xmlFree(nsURI);
5759 1           nsURI = NULL;
5760             }
5761 33 100         if ( nsPrefix == NULL && nsURI == NULL ) {
    50          
5762             /* special case: empty namespace */
5763 2 50         if ( (ns = xmlSearchNs(node->doc, node, NULL)) &&
    0          
5764 0 0         ( ns->href && xmlStrlen( ns->href ) != 0 ) ) {
5765             /* won't take it */
5766 0           RETVAL = 0;
5767 1 50         } else if ( flag ) {
5768             /* no namespace */
5769 1           xmlSetNs(node, NULL);
5770 1           RETVAL = 1;
5771             } else {
5772 0           RETVAL = 0;
5773             }
5774             }
5775 32 100         else if ( flag && (ns = xmlSearchNs(node->doc, node, nsPrefix)) ) {
    100          
5776             /* user just wants to set the namespace for the node */
5777             /* try to reuse an existing declaration for the prefix */
5778 2 50         if ( xmlStrEqual( ns->href, nsURI ) ) {
5779 1           RETVAL = 1;
5780             }
5781 0 0         else if ( (ns = xmlNewNs( node, nsURI, nsPrefix )) ) {
5782 0           RETVAL = 1;
5783             }
5784             else {
5785 0           RETVAL = 0;
5786             }
5787             }
5788 31 50         else if ( (ns = xmlNewNs( node, nsURI, nsPrefix )) )
5789 31           RETVAL = 1;
5790             else
5791 0           RETVAL = 0;
5792              
5793 33 100         if ( flag && ns ) {
    100          
5794 4           xmlSetNs(node, ns);
5795             }
5796 33 100         if ( nsPrefix ) xmlFree(nsPrefix);
5797 33 100         if ( nsURI ) xmlFree(nsURI);
5798             OUTPUT:
5799             RETVAL
5800              
5801             int
5802             setNamespaceDeclURI( self, svprefix, newURI )
5803             xmlNodePtr self
5804             SV * svprefix
5805             SV * newURI
5806             PREINIT:
5807 15           xmlChar * prefix = NULL;
5808 15           xmlChar * nsURI = NULL;
5809             xmlNsPtr ns;
5810             CODE:
5811 15           RETVAL = 0;
5812 15           prefix = nodeSv2C( svprefix , self );
5813 15           nsURI = nodeSv2C( newURI , self );
5814             /* null empty values */
5815 15 50         if ( prefix && xmlStrlen(prefix) == 0) {
    100          
5816 3           xmlFree( prefix );
5817 3           prefix = NULL;
5818             }
5819 15 100         if ( nsURI && xmlStrlen(nsURI) == 0) {
    50          
5820 0           xmlFree( nsURI );
5821 0           nsURI = NULL;
5822             }
5823 15           ns = self->nsDef;
5824 28 100         while ( ns ) {
5825 39 100         if ((ns->prefix || ns->href ) &&
5826 19           ( xmlStrcmp( ns->prefix, prefix ) == 0 )) {
5827 7 50         if (ns->href) xmlFree((char*)ns->href);
5828 7           ns->href = nsURI;
5829 7 100         if ( nsURI == NULL ) {
5830 3           domRemoveNsRefs( self, ns );
5831             } else
5832 4           nsURI = NULL; /* do not free it */
5833 7           RETVAL = 1;
5834 7           break;
5835             } else {
5836 13           ns = ns->next;
5837             }
5838             }
5839 15 100         if ( prefix ) xmlFree( prefix );
5840 15 100         if ( nsURI ) xmlFree( nsURI );
5841             OUTPUT:
5842             RETVAL
5843              
5844             int
5845             setNamespaceDeclPrefix( self, svprefix, newPrefix )
5846             xmlNodePtr self
5847             SV * svprefix
5848             SV * newPrefix
5849             PREINIT:
5850 6           xmlChar * prefix = NULL;
5851 6           xmlChar * nsPrefix = NULL;
5852             xmlNsPtr ns;
5853             CODE:
5854 6           RETVAL = 0;
5855 6           prefix = nodeSv2C( svprefix , self );
5856 6           nsPrefix = nodeSv2C( newPrefix , self );
5857             /* null empty values */
5858 6 50         if ( prefix != NULL && xmlStrlen(prefix) == 0) {
    100          
5859 1           xmlFree( prefix );
5860 1           prefix = NULL;
5861             }
5862 6 100         if ( nsPrefix != NULL && xmlStrlen(nsPrefix) == 0) {
    100          
5863 2           xmlFree( nsPrefix );
5864 2           nsPrefix = NULL;
5865             }
5866 6 50         if ( xmlStrcmp( prefix, nsPrefix ) == 0 ) {
5867 0           RETVAL = 1;
5868             } else {
5869             /* check that new prefix is not in scope */
5870 6           ns = xmlSearchNs( self->doc, self, nsPrefix );
5871 6 100         if ( ns != NULL ) {
5872 2 100         if (nsPrefix != NULL) xmlFree( nsPrefix );
5873 2 50         if (prefix != NULL) xmlFree( prefix );
5874 2           croak("setNamespaceDeclPrefix: prefix '%s' is in use", ns->prefix);
5875             }
5876             /* lookup the declaration */
5877 4           ns = self->nsDef;
5878 7 50         while ( ns != NULL ) {
5879 13 100         if ((ns->prefix != NULL || ns->href != NULL) &&
5880 6           xmlStrcmp( ns->prefix, prefix ) == 0 ) {
5881 4 100         if ( ns->href == NULL && nsPrefix != NULL ) {
    50          
5882             /* xmlns:foo="" - no go */
5883 0 0         if ( prefix != NULL) xmlFree(prefix);
5884 0           croak("setNamespaceDeclPrefix: cannot set non-empty prefix for empty namespace");
5885             }
5886 4 100         if ( ns->prefix != NULL )
5887 3           xmlFree( (xmlChar*)ns->prefix );
5888 4           ns->prefix = nsPrefix;
5889 4           nsPrefix = NULL; /* do not free it */
5890 4           RETVAL = 1;
5891 4           break;
5892             } else {
5893 3           ns = ns->next;
5894             }
5895             }
5896             }
5897 4 50         if ( nsPrefix != NULL ) xmlFree(nsPrefix);
5898 4 100         if ( prefix != NULL) xmlFree(prefix);
5899             OUTPUT:
5900             RETVAL
5901              
5902              
5903             SV*
5904             _getNamespaceDeclURI( self, ns_prefix )
5905             xmlNodePtr self
5906             SV * ns_prefix
5907             PREINIT:
5908             xmlChar * prefix;
5909             xmlNsPtr ns;
5910             CODE:
5911 22           prefix = nodeSv2C(ns_prefix, self );
5912 22 100         if ( prefix != NULL && xmlStrlen(prefix) == 0) {
    100          
5913 3           xmlFree( prefix );
5914 3           prefix = NULL;
5915             }
5916 22           RETVAL = &PL_sv_undef;
5917 22           ns = self->nsDef;
5918 33 100         while ( ns != NULL ) {
5919 48 100         if ( (ns->prefix != NULL || ns->href != NULL) &&
5920 24           xmlStrcmp( ns->prefix, prefix ) == 0 ) {
5921 13           RETVAL = C2Sv(ns->href, NULL);
5922 13           break;
5923             } else {
5924 11           ns = ns->next;
5925             }
5926             }
5927 22 100         if ( prefix != NULL ) {
5928 18           xmlFree( prefix );
5929             }
5930              
5931             OUTPUT:
5932             RETVAL
5933              
5934             int
5935             hasAttribute( self, attr_name )
5936             xmlNodePtr self
5937             SV * attr_name
5938             PREINIT:
5939             xmlChar * name;
5940             CODE:
5941 16           name = nodeSv2C(attr_name, self );
5942 16 50         if ( ! name ) {
5943 0           XSRETURN_UNDEF;
5944             }
5945 16 100         if ( domGetAttrNode( self, name ) ) {
5946 9           RETVAL = 1;
5947             }
5948             else {
5949 7           RETVAL = 0;
5950             }
5951 16           xmlFree(name);
5952             OUTPUT:
5953             RETVAL
5954              
5955             int
5956             hasAttributeNS( self, namespaceURI, attr_name )
5957             xmlNodePtr self
5958             SV * namespaceURI
5959             SV * attr_name
5960             PREINIT:
5961             xmlChar * name;
5962             xmlChar * nsURI;
5963             xmlNodePtr attr;
5964             CODE:
5965 16           name = nodeSv2C(attr_name, self );
5966 16           nsURI = nodeSv2C(namespaceURI, self );
5967              
5968 16 50         if ( name == NULL ) {
5969 0 0         if ( nsURI != NULL ) {
5970 0           xmlFree(nsURI);
5971             }
5972 0           XSRETURN_UNDEF;
5973             }
5974 16 100         if ( nsURI != NULL && xmlStrlen(nsURI) == 0 ){
    100          
5975 2           xmlFree(nsURI);
5976 2           nsURI = NULL;
5977             }
5978 16           attr = (xmlNodePtr) xmlHasNsProp( self, name, nsURI );
5979 16 100         if ( attr && attr->type == XML_ATTRIBUTE_NODE ) {
    100          
5980 8           RETVAL = 1;
5981             }
5982             else {
5983 8           RETVAL = 0;
5984             }
5985              
5986 16           xmlFree(name);
5987 16 100         if ( nsURI != NULL ){
5988 12           xmlFree(nsURI);
5989             }
5990             OUTPUT:
5991             RETVAL
5992              
5993             SV*
5994             _getAttribute( self, attr_name, useDomEncoding = 0 )
5995             xmlNodePtr self
5996             SV * attr_name
5997             int useDomEncoding
5998             PREINIT:
5999             xmlChar * name;
6000 46           xmlChar * prefix = NULL;
6001 46           xmlChar * localname = NULL;
6002 46           xmlChar * ret = NULL;
6003 46           xmlNsPtr ns = NULL;
6004             CODE:
6005 46           name = nodeSv2C(attr_name, self );
6006 46 50         if( !name ) {
6007 0           XSRETURN_UNDEF;
6008             }
6009              
6010 46           ret = xmlGetNoNsProp(self, name);
6011 46 100         if ( ret == NULL ) {
6012 7           localname = xmlSplitQName2(name, &prefix);
6013 7 50         if ( localname != NULL ) {
6014 7           ns = xmlSearchNs( self->doc, self, prefix );
6015 7 50         if ( ns != NULL ) {
6016 7           ret = xmlGetNsProp(self, localname, ns->href);
6017             }
6018 7 50         if ( prefix != NULL) {
6019 7           xmlFree( prefix );
6020             }
6021 7           xmlFree( localname );
6022             }
6023             }
6024 46           xmlFree(name);
6025 46 50         if ( ret ) {
6026 46 100         if ( useDomEncoding ) {
6027 9           RETVAL = nodeC2Sv(ret, self);
6028             }
6029             else {
6030 37           RETVAL = C2Sv(ret, NULL);
6031             }
6032 46           xmlFree( ret );
6033             }
6034             else {
6035 0           XSRETURN_UNDEF;
6036             }
6037              
6038             OUTPUT:
6039             RETVAL
6040              
6041             void
6042             _setAttribute( self, attr_name, attr_value )
6043             xmlNodePtr self
6044             SV * attr_name
6045             SV * attr_value
6046             PREINIT:
6047 28           xmlChar * name = NULL;
6048 28           xmlChar * value = NULL;
6049             #if LIBXML_VERSION < 20621
6050             xmlChar * prefix = NULL;
6051             xmlChar * localname = NULL;
6052             #endif
6053             CODE:
6054 28           name = nodeSv2C(attr_name, self );
6055              
6056 28 100         if ( !LibXML_test_node_name(name) ) {
6057 4           xmlFree(name);
6058 4           croak( "bad name" );
6059             }
6060 24           value = nodeSv2C(attr_value, self );
6061             #if LIBXML_VERSION >= 20621
6062             /*
6063             * For libxml2-2.6.21 and later we can use just xmlSetProp
6064             */
6065 24           xmlSetProp(self,name,value);
6066             #else
6067             /*
6068             * but xmlSetProp does not work correctly for older libxml2 versions
6069             * The following is copied from libxml2 source
6070             * with xmlSplitQName3 replaced by xmlSplitQName2 for compatibility
6071             * with older libxml2 versions
6072             */
6073             localname = xmlSplitQName2(name, &prefix);
6074             if (localname != NULL) {
6075             xmlNsPtr ns;
6076             ns = xmlSearchNs(self->doc, self, prefix);
6077             if (prefix != NULL)
6078             xmlFree(prefix);
6079             if (ns != NULL)
6080             xmlSetNsProp(self, ns, localname, value);
6081             else
6082             xmlSetNsProp(self, NULL, name, value);
6083             xmlFree(localname);
6084             } else {
6085             xmlSetNsProp(self, NULL, name, value);
6086             }
6087             #endif
6088 24           xmlFree(name);
6089 24           xmlFree(value);
6090              
6091              
6092             void
6093             removeAttribute( self, attr_name )
6094             xmlNodePtr self
6095             SV * attr_name
6096             PREINIT:
6097             xmlChar * name;
6098 4           xmlAttrPtr xattr = NULL;
6099             CODE:
6100 4           name = nodeSv2C(attr_name, self );
6101 4 50         if ( name ) {
6102 4           xattr = domGetAttrNode( self, name );
6103              
6104 4 50         if ( xattr ) {
6105 4           xmlUnlinkNode((xmlNodePtr)xattr);
6106 4 100         if ( xattr->_private ) {
6107 1           PmmFixOwner((ProxyNodePtr)xattr->_private, NULL);
6108             }
6109             else {
6110 3           xmlFreeProp(xattr);
6111             }
6112             }
6113 4           xmlFree(name);
6114             }
6115              
6116             SV*
6117             getAttributeNode( self, attr_name )
6118             xmlNodePtr self
6119             SV * attr_name
6120             PREINIT:
6121             xmlChar * name;
6122 45           xmlAttrPtr ret = NULL;
6123             CODE:
6124 45           name = nodeSv2C(attr_name, self );
6125 45 50         if ( !name ) {
6126 0           XSRETURN_UNDEF;
6127             }
6128              
6129 45           ret = domGetAttrNode( self, name );
6130 45           xmlFree(name);
6131 45 100         if ( ret ) {
6132 60 50         RETVAL = PmmNodeToSv( (xmlNodePtr)ret,
6133 30 50         PmmOWNERPO(PmmPROXYNODE(self)) );
6134             }
6135             else {
6136 15           XSRETURN_UNDEF;
6137             }
6138             OUTPUT:
6139             RETVAL
6140              
6141             SV *
6142             setAttributeNode( self, attr_node )
6143             xmlNodePtr self
6144             SV * attr_node
6145             PREINIT:
6146 1           xmlAttrPtr attr = (xmlAttrPtr)PmmSvNode( attr_node );
6147 1           xmlAttrPtr ret = NULL;
6148             INIT:
6149 1 50         if ( attr == NULL ) {
6150 0           croak( "lost attribute" );
6151             }
6152             CODE:
6153 1 50         if ( attr != NULL && attr->type != XML_ATTRIBUTE_NODE ) {
    50          
6154 0           XSRETURN_UNDEF;
6155             }
6156 1 50         if ( attr->doc != self->doc ) {
6157 0           domImportNode( self->doc, (xmlNodePtr)attr, 1, 1);
6158             }
6159 1           ret = domGetAttrNode( self, attr->name );
6160 1 50         if ( ret != NULL ) {
6161 0 0         if ( ret != attr ) {
6162 0           xmlReplaceNode( (xmlNodePtr)ret, (xmlNodePtr)attr );
6163             }
6164             else {
6165 0           XSRETURN_UNDEF;
6166             }
6167             }
6168             else {
6169 1           xmlAddChild( self, (xmlNodePtr)attr );
6170             }
6171              
6172 1 50         if ( attr->_private != NULL ) {
6173 1 50         PmmFixOwner( SvPROXYNODE(attr_node), PmmPROXYNODE(self) );
6174             }
6175              
6176 1 50         if ( ret == NULL ) {
6177 1           XSRETURN_UNDEF;
6178             }
6179              
6180 0           RETVAL = PmmNodeToSv( (xmlNodePtr)ret, NULL );
6181 0 0         PmmFixOwner( SvPROXYNODE(RETVAL), NULL );
6182             OUTPUT:
6183             RETVAL
6184              
6185             SV *
6186             _getAttributeNS( self, namespaceURI, attr_name, useDomEncoding = 0 )
6187             xmlNodePtr self
6188             SV * namespaceURI
6189             SV * attr_name
6190             int useDomEncoding
6191             PREINIT:
6192             xmlChar * name;
6193             xmlChar * nsURI;
6194 22           xmlChar * ret = NULL;
6195             CODE:
6196 22           name = nodeSv2C( attr_name, self );
6197 22           nsURI = nodeSv2C( namespaceURI, self );
6198 22 50         if ( !name ) {
6199 0           xmlFree(nsURI);
6200 0           XSRETURN_UNDEF;
6201             }
6202 22 100         if ( nsURI && xmlStrlen(nsURI) ) {
    100          
6203 20           ret = xmlGetNsProp( self, name, nsURI );
6204             }
6205             else {
6206 2           ret = xmlGetProp( self, name );
6207             }
6208              
6209 22           xmlFree( name );
6210 22 100         if ( nsURI ) {
6211 21           xmlFree( nsURI );
6212             }
6213 22 50         if ( ret ) {
6214 22 50         if (useDomEncoding) {
6215 0           RETVAL = nodeC2Sv( ret, self );
6216             } else {
6217 22           RETVAL = C2Sv( ret, NULL );
6218             }
6219 22           xmlFree( ret );
6220             }
6221             else {
6222 0           XSRETURN_UNDEF;
6223             }
6224             OUTPUT:
6225             RETVAL
6226              
6227             void
6228             _setAttributeNS( self, namespaceURI, attr_name, attr_value )
6229             xmlNodePtr self
6230             SV * namespaceURI
6231             SV * attr_name
6232             SV * attr_value
6233             PREINIT:
6234             xmlChar * nsURI;
6235 48           xmlChar * name = NULL;
6236 48           xmlChar * value = NULL;
6237 48           xmlNsPtr ns = NULL;
6238 48           xmlChar * localname = NULL;
6239 48           xmlChar * prefix = NULL;
6240 48           xmlNsPtr * all_ns = NULL;
6241             int i;
6242             INIT:
6243 48           name = nodeSv2C( attr_name, self );
6244              
6245 48 100         if ( !LibXML_test_node_name(name) ) {
6246 3           xmlFree(name);
6247 3           croak( "bad name" );
6248             }
6249              
6250 45           nsURI = nodeSv2C( namespaceURI, self );
6251 45           localname = xmlSplitQName2(name, &prefix);
6252 45 100         if ( localname ) {
6253 21           xmlFree( name );
6254 21           name = localname;
6255             }
6256             CODE:
6257 45           value = nodeSv2C( attr_value, self );
6258              
6259 45 100         if ( nsURI && xmlStrlen(nsURI) ) {
    100          
6260             xs_warn( "found uri" );
6261              
6262 24           ns = xmlSearchNsByHref( self->doc, self, nsURI );
6263              
6264             /*
6265             * check for any prefixed namespaces occluded by a default namespace
6266             * because xmlSearchNsByHref will return default namespaces unless
6267             * you are searching on an attribute node, which may not exist yet
6268             */
6269 24 100         if ( ns && !ns->prefix )
    100          
6270             {
6271 4           all_ns = xmlGetNsList(self->doc, self);
6272 4 50         if ( all_ns )
6273             {
6274 4           i = 0;
6275 4           ns = all_ns[i];
6276 14 100         while ( ns )
6277             {
6278 13 100         if ( ns->prefix && xmlStrEqual(ns->href, nsURI) )
    100          
6279             {
6280 3           break;
6281             }
6282 10           ns = all_ns[i++];
6283             }
6284 4           xmlFree(all_ns);
6285             }
6286             }
6287              
6288 24 100         if ( !ns ) {
6289             /* create new ns */
6290 5 50         if ( prefix && xmlStrlen( prefix ) ) {
    50          
6291 5           ns = xmlNewNs(self, nsURI , prefix);
6292             }
6293             else {
6294 0           ns = NULL;
6295             }
6296             }
6297             }
6298              
6299 45 100         if ( nsURI && xmlStrlen(nsURI) && !ns ) {
    100          
    50          
6300 0 0         if ( prefix ) xmlFree( prefix );
6301 0 0         if ( nsURI ) xmlFree( nsURI );
6302 0           xmlFree( name );
6303 0           xmlFree( value );
6304 0           croak( "bad ns attribute!" );
6305             }
6306             else {
6307             /* warn( "set attribute %s->%s", name, value ); */
6308 45           xmlSetNsProp( self, ns, name, value );
6309             }
6310              
6311 45 100         if ( prefix ) {
6312 21           xmlFree( prefix );
6313             }
6314 45 100         if ( nsURI ) {
6315 44           xmlFree( nsURI );
6316             }
6317 45           xmlFree( name );
6318 45           xmlFree( value );
6319              
6320             void
6321             removeAttributeNS( self, namespaceURI, attr_name )
6322             xmlNodePtr self
6323             SV * namespaceURI
6324             SV * attr_name
6325             PREINIT:
6326             xmlChar * nsURI;
6327 3           xmlChar * name = NULL;
6328 3           xmlAttrPtr xattr = NULL;
6329             CODE:
6330 3           nsURI = nodeSv2C( namespaceURI, self );
6331 3           name = nodeSv2C( attr_name, self );
6332 3 50         if ( ! name ) {
6333 0           xmlFree(nsURI);
6334 0           XSRETURN_UNDEF;
6335             }
6336              
6337 3 50         if ( nsURI && xmlStrlen(nsURI) ) {
    100          
6338 2           xattr = xmlHasNsProp( self, name, nsURI );
6339             }
6340             else {
6341 1           xattr = xmlHasNsProp( self, name, NULL );
6342             }
6343 3 50         if ( xattr && xattr->type == XML_ATTRIBUTE_NODE ) {
    50          
6344 3           xmlUnlinkNode((xmlNodePtr)xattr);
6345 3 100         if ( xattr->_private ) {
6346 2           PmmFixOwner((ProxyNodePtr)xattr->_private, NULL);
6347             }
6348             else {
6349 1           xmlFreeProp(xattr);
6350             }
6351             }
6352 3           xmlFree(nsURI);
6353 3           xmlFree( name );
6354              
6355              
6356             SV*
6357             getAttributeNodeNS( self,namespaceURI, attr_name )
6358             xmlNodePtr self
6359             SV * namespaceURI
6360             SV * attr_name
6361             PREINIT:
6362             xmlChar * nsURI;
6363             xmlChar * name;
6364 33           xmlAttrPtr ret = NULL;
6365             CODE:
6366 33           nsURI = nodeSv2C(namespaceURI, self );
6367 33           name = nodeSv2C(attr_name, self );
6368 33 50         if ( !name ) {
6369 0           xmlFree(nsURI);
6370 0           XSRETURN_UNDEF;
6371             }
6372 33 100         if ( nsURI && xmlStrlen(nsURI) ) {
    50          
6373 20           ret = xmlHasNsProp( self, name, nsURI );
6374             }
6375             else {
6376 13           ret = xmlHasNsProp( self, name, NULL );
6377             }
6378 33           xmlFree(name);
6379 33 100         if ( nsURI ) {
6380 20           xmlFree(nsURI);
6381             }
6382 33 100         if ( ret &&
    100          
6383 18           ret->type == XML_ATTRIBUTE_NODE /* we don't want fixed attribute decls */
6384             ) {
6385 24 50         RETVAL = PmmNodeToSv( (xmlNodePtr)ret,
6386 12 50         PmmOWNERPO(PmmPROXYNODE(self)) );
6387             }
6388             else {
6389             /* warn("no prop\n"); */
6390 21           XSRETURN_UNDEF;
6391             }
6392             OUTPUT:
6393             RETVAL
6394              
6395             SV *
6396             setAttributeNodeNS( self, attr_node )
6397             xmlNodePtr self
6398             SV * attr_node
6399             PREINIT:
6400 4           xmlAttrPtr attr = (xmlAttrPtr)PmmSvNode( attr_node );
6401 4           xmlNsPtr ns = NULL;
6402 4           xmlAttrPtr ret = NULL;
6403             INIT:
6404 4 50         if ( attr == NULL ) {
6405 0           croak( "lost attribute node" );
6406             }
6407             CODE:
6408 4 50         if ( attr->type != XML_ATTRIBUTE_NODE ) {
6409 0           XSRETURN_UNDEF;
6410             }
6411              
6412 4 100         if ( attr->doc != self->doc ) {
6413 1           domImportNode( self->doc, (xmlNodePtr)attr, 1,1);
6414             }
6415              
6416              
6417 4           ns = attr->ns;
6418 4 50         if ( ns != NULL ) {
6419 4           ret = xmlHasNsProp( self, ns->href, attr->name );
6420             }
6421             else {
6422 0           ret = xmlHasNsProp( self, NULL, attr->name );
6423             }
6424              
6425 4 50         if ( ret && ret->type == XML_ATTRIBUTE_NODE ) {
    0          
6426 0 0         if ( ret != attr ) {
6427 0           xmlReplaceNode( (xmlNodePtr)ret, (xmlNodePtr)attr );
6428             }
6429             else {
6430 0           XSRETURN_UNDEF;
6431             }
6432             }
6433             else {
6434 4           xmlAddChild( self, (xmlNodePtr)attr );
6435 4           xmlReconciliateNs(self->doc, self);
6436             }
6437 4 50         if ( attr->_private != NULL ) {
6438 4 50         PmmFixOwner( SvPROXYNODE(attr_node), PmmPROXYNODE(self) );
6439             }
6440 4 50         if ( ret != NULL && ret->type == XML_ATTRIBUTE_NODE ) {
    0          
6441 0           RETVAL = PmmNodeToSv( (xmlNodePtr)ret, NULL );
6442 0 0         PmmFixOwner( SvPROXYNODE(RETVAL), NULL );
6443             } else {
6444 4           XSRETURN_UNDEF;
6445             }
6446             OUTPUT:
6447             RETVAL
6448              
6449             SV *
6450             removeAttributeNode( self, attr_node )
6451             xmlNodePtr self
6452             SV * attr_node
6453             PREINIT:
6454 3           xmlAttrPtr attr = (xmlAttrPtr)PmmSvNode( attr_node );
6455             xmlAttrPtr ret;
6456             INIT:
6457 3 50         if ( attr == NULL ) {
6458 0           croak( "lost attribute node" );
6459             }
6460             CODE:
6461 3 50         if ( attr->type != XML_ATTRIBUTE_NODE ) {
6462 0           XSRETURN_UNDEF;
6463             }
6464 3 50         if ( attr->parent != self ) {
6465 0           XSRETURN_UNDEF;
6466             }
6467 3           ret = attr;
6468 3           xmlUnlinkNode( (xmlNodePtr)attr );
6469 3           RETVAL = PmmNodeToSv( (xmlNodePtr)ret, NULL );
6470 3 50         PmmFixOwner( SvPROXYNODE(RETVAL), NULL );
6471             OUTPUT:
6472             RETVAL
6473              
6474             void
6475             appendText( self, string )
6476             xmlNodePtr self
6477             SV * string
6478             ALIAS:
6479             appendTextNode = 1
6480             XML::LibXML::DocumentFragment::appendText = 2
6481             XML::LibXML::DocumentFragment::appendTextNode = 3
6482             PREINIT:
6483 88           xmlChar * content = NULL;
6484             INIT:
6485             PERL_UNUSED_VAR(ix);
6486 88           content = nodeSv2C( string, self );
6487 88 50         if ( content == NULL ) {
6488 0           XSRETURN_UNDEF;
6489             }
6490 88 50         if ( xmlStrlen(content) == 0 ) {
6491 0           xmlFree( content );
6492 0           XSRETURN_UNDEF;
6493             }
6494             CODE:
6495 88           xmlNodeAddContent( self, content );
6496 88           xmlFree(content);
6497              
6498              
6499             void
6500             appendTextChild( self, strname, strcontent=&PL_sv_undef, nsURI=&PL_sv_undef )
6501             xmlNodePtr self
6502             SV * strname
6503             SV * strcontent
6504             SV * nsURI
6505             PREINIT:
6506             xmlChar * name;
6507 3           xmlChar * content = NULL;
6508 3           xmlChar * encstr = NULL;
6509             INIT:
6510 3           name = nodeSv2C( strname, self );
6511 3 50         if ( xmlStrlen(name) == 0 ) {
6512 0           xmlFree(name);
6513 0           XSRETURN_UNDEF;
6514             }
6515             CODE:
6516 3           content = nodeSv2C(strcontent, self);
6517 3 100         if ( content && xmlStrlen( content ) == 0 ) {
    50          
6518 0           xmlFree(content);
6519 0           content=NULL;
6520             }
6521 3 100         else if ( content ) {
6522 2           encstr = xmlEncodeEntitiesReentrant( self->doc, content );
6523 2           xmlFree(content);
6524             }
6525              
6526 3           xmlNewChild( self, NULL, name, encstr );
6527              
6528 3 100         if ( encstr )
6529 2           xmlFree(encstr);
6530 3           xmlFree(name);
6531              
6532             SV *
6533             addNewChild( self, namespaceURI, nodename )
6534             xmlNodePtr self
6535             SV * namespaceURI
6536             SV * nodename
6537             ALIAS:
6538             XML::LibXML::DocumentFragment::addNewChild = 1
6539             PREINIT:
6540 72           xmlChar * nsURI = NULL;
6541 72           xmlChar * name = NULL;
6542 72           xmlChar * localname = NULL;
6543 72           xmlChar * prefix = NULL;
6544 72           xmlNodePtr newNode = NULL;
6545 72           xmlNodePtr prev = NULL;
6546 72           xmlNsPtr ns = NULL;
6547             CODE:
6548             PERL_UNUSED_VAR(ix);
6549 72           name = nodeSv2C(nodename, self);
6550 72 50         if ( name && xmlStrlen( name ) == 0 ) {
    50          
6551 0           xmlFree(name);
6552 0           XSRETURN_UNDEF;
6553             }
6554              
6555 72           nsURI = nodeSv2C(namespaceURI, self);
6556 72 50         if ( nsURI && xmlStrlen( nsURI ) == 0 ) {
    100          
6557 50           xmlFree(nsURI);
6558 50           nsURI=NULL;
6559             }
6560              
6561 72 100         if ( nsURI != NULL ) {
6562 22           localname = xmlSplitQName2(name, &prefix);
6563 22           ns = xmlSearchNsByHref(self->doc, self, nsURI);
6564              
6565 22 100         newNode = xmlNewDocNode(self->doc,
6566             ns,
6567             localname?localname:name,
6568             NULL);
6569 22 100         if ( ns == NULL ) {
6570 4           xmlSetNs(newNode,xmlNewNs(newNode, nsURI, prefix));
6571             }
6572              
6573 22           xmlFree(localname);
6574 22           xmlFree(prefix);
6575 22           xmlFree(nsURI);
6576             }
6577             else {
6578 50           newNode = xmlNewDocNode(self->doc,
6579             NULL,
6580             name,
6581             NULL);
6582             }
6583 72           xmlFree(name);
6584             /* add the node to the parent node */
6585 72           newNode->type = XML_ELEMENT_NODE;
6586 72           newNode->parent = self;
6587 72           newNode->doc = self->doc;
6588              
6589 72 100         if (self->children == NULL) {
6590 31           self->children = newNode;
6591 31           self->last = newNode;
6592             } else {
6593 41           prev = self->last;
6594 41           prev->next = newNode;
6595 41           newNode->prev = prev;
6596 41           self->last = newNode;
6597             }
6598 72 50         RETVAL = PmmNodeToSv(newNode, PmmOWNERPO(PmmPROXYNODE(self)) );
    100          
6599             OUTPUT:
6600             RETVAL
6601              
6602             MODULE = XML::LibXML PACKAGE = XML::LibXML::Text
6603              
6604             SV *
6605             new( CLASS, content )
6606             SV * content
6607             PREINIT:
6608             xmlChar * data;
6609             xmlNodePtr newNode;
6610 18           ProxyNodePtr docfrag = NULL;
6611             CODE:
6612 18           data = Sv2C(content, NULL);
6613 18           newNode = xmlNewText( data );
6614 18           xmlFree(data);
6615 18 50         if( newNode != NULL ) {
6616 18           docfrag = PmmNewFragment( NULL );
6617 18           xmlAddChild(PmmNODE(docfrag), newNode);
6618 18           RETVAL = PmmNodeToSv(newNode,docfrag);
6619             }
6620             else {
6621 0           XSRETURN_UNDEF;
6622             }
6623             OUTPUT:
6624             RETVAL
6625              
6626             SV *
6627             substringData( self, offset, length )
6628             xmlNodePtr self
6629             int offset
6630             int length
6631             PREINIT:
6632 4           xmlChar * data = NULL;
6633 4           xmlChar * substr = NULL;
6634             CODE:
6635 4 50         if ( offset >= 0 && length >= 0 ) {
    50          
6636 4           data = domGetNodeValue( self );
6637 8 50         if ( data != NULL ) {
6638 4           substr = xmlUTF8Strsub( data, offset, length );
6639 4           RETVAL = C2Sv( (const xmlChar*)substr, NULL );
6640 4           xmlFree( substr );
6641             }
6642             else {
6643 0           XSRETURN_UNDEF;
6644             }
6645             }
6646             else {
6647 0           XSRETURN_UNDEF;
6648             }
6649             OUTPUT:
6650             RETVAL
6651              
6652             void
6653             setData( self, value )
6654             xmlNodePtr self
6655             SV * value
6656             ALIAS:
6657             XML::LibXML::Attr::setValue = 1
6658             XML::LibXML::PI::_setData = 2
6659             PREINIT:
6660 45           xmlChar * encstr = NULL;
6661             CODE:
6662             PERL_UNUSED_VAR(ix);
6663 45           encstr = nodeSv2C(value,self);
6664 45           domSetNodeValue( self, encstr );
6665 45           xmlFree(encstr);
6666              
6667             void
6668             appendData( self, value )
6669             xmlNodePtr self
6670             SV * value
6671             PREINIT:
6672 2           xmlChar * encstring = NULL;
6673 2           int strlen = 0;
6674             CODE:
6675 2 50         encstring = Sv2C( value,
6676 4           self->doc!=NULL ? self->doc->encoding : NULL );
6677              
6678 2 50         if ( encstring != NULL ) {
6679 2           strlen = xmlStrlen( encstring );
6680 2           xmlTextConcat( self, encstring, strlen );
6681 2           xmlFree( encstring );
6682             }
6683              
6684             void
6685             insertData( self, offset, value )
6686             xmlNodePtr self
6687             int offset
6688             SV * value
6689             PREINIT:
6690 5           xmlChar * after= NULL;
6691 5           xmlChar * data = NULL;
6692 5           xmlChar * new = NULL;
6693 5           xmlChar * encstring = NULL;
6694 5           int dl = 0;
6695             CODE:
6696 5 50         if ( offset >= 0 ) {
6697 5 50         encstring = Sv2C( value,
6698 10           self->doc!=NULL ? self->doc->encoding : NULL );
6699 5 50         if ( encstring != NULL && xmlStrlen( encstring ) > 0 ) {
    100          
6700 4           data = domGetNodeValue(self);
6701 4 50         if ( data != NULL && xmlStrlen( data ) > 0 ) {
    50          
6702 4 50         if ( xmlUTF8Strlen( data ) < offset ) {
6703 0           data = xmlStrcat( data, encstring );
6704 0           domSetNodeValue( self, data );
6705             }
6706             else {
6707 4           dl = xmlUTF8Strlen( data ) - offset;
6708              
6709 4 50         if ( offset > 0 )
6710 4           new = xmlUTF8Strsub(data, 0, offset );
6711              
6712 4           after = xmlUTF8Strsub(data, offset, dl );
6713              
6714 4 50         if ( new != NULL ) {
6715 4           new = xmlStrcat(new, encstring );
6716             }
6717             else {
6718 0           new = xmlStrdup( encstring );
6719             }
6720              
6721 4 50         if ( after != NULL )
6722 4           new = xmlStrcat(new, after );
6723              
6724 4           domSetNodeValue( self, new );
6725              
6726 4           xmlFree( new );
6727 4           xmlFree( after );
6728             }
6729 4           xmlFree( data );
6730             }
6731             else {
6732 0           domSetNodeValue( self, encstring );
6733             }
6734 4           xmlFree(encstring);
6735             }
6736             }
6737              
6738             void
6739             deleteData( self, offset, length )
6740             xmlNodePtr self
6741             int offset
6742             int length
6743             PREINIT:
6744 9           xmlChar * data = NULL;
6745 9           xmlChar * after = NULL;
6746 9           xmlChar * new = NULL;
6747 9           int len = 0;
6748 9           int dl1 = 0;
6749 9           int dl2 = 0;
6750             CODE:
6751 9 100         if ( length > 0 && offset >= 0 ) {
    50          
6752 7           data = domGetNodeValue(self);
6753 7           len = xmlUTF8Strlen( data );
6754 7 50         if ( data != NULL
6755 7 50         && len > 0
6756 7 100         && len > offset ) {
6757 5           dl1 = offset + length;
6758 5 100         if ( offset > 0 )
6759 4           new = xmlUTF8Strsub( data, 0, offset );
6760              
6761 5 100         if ( len > dl1 ) {
6762 3           dl2 = len - dl1;
6763 3           after = xmlUTF8Strsub( data, dl1, dl2 );
6764 3 100         if ( new != NULL ) {
6765 2           new = xmlStrcat( new, after );
6766 2           xmlFree(after);
6767             }
6768             else {
6769 1           new = after;
6770             }
6771             }
6772              
6773 5           domSetNodeValue( self, new );
6774 5           xmlFree(new);
6775             }
6776             }
6777              
6778             void
6779             replaceData( self, offset,length, value )
6780             xmlNodePtr self
6781             int offset
6782             int length
6783             SV * value
6784             PREINIT:
6785 6           xmlChar * after= NULL;
6786 6           xmlChar * data = NULL;
6787 6           xmlChar * new = NULL;
6788 6           xmlChar * encstring = NULL;
6789 6           int len = 0;
6790 6           int dl1 = 0;
6791 6           int dl2 = 0;
6792             CODE:
6793 6 50         if ( offset >= 0 ) {
6794 6 50         encstring = Sv2C( value,
6795 12           self->doc!=NULL ? self->doc->encoding : NULL );
6796              
6797 6 50         if ( encstring != NULL && xmlStrlen( encstring ) > 0 ) {
    50          
6798 6           data = domGetNodeValue(self);
6799 6           len = xmlUTF8Strlen( data );
6800              
6801 6 50         if ( data != NULL
6802 6 50         && len > 0
6803 6 50         && len > offset ) {
6804              
6805 6           dl1 = offset + length;
6806 6 100         if ( dl1 < len ) {
6807 4           dl2 = xmlUTF8Strlen( data ) - dl1;
6808 4 50         if ( offset > 0 ) {
6809 4           new = xmlUTF8Strsub(data, 0, offset );
6810 4           new = xmlStrcat(new, encstring );
6811             }
6812             else {
6813 0           new = xmlStrdup( encstring );
6814             }
6815              
6816 4           after = xmlUTF8Strsub(data, dl1, dl2 );
6817 4           new = xmlStrcat(new, after );
6818              
6819 4           domSetNodeValue( self, new );
6820              
6821 4           xmlFree( new );
6822 4           xmlFree( after );
6823             }
6824             else {
6825             /* replace until end! */
6826 2 50         if ( offset > 0 ) {
6827 2           new = xmlUTF8Strsub(data, 0, offset );
6828 2           new = xmlStrcat(new, encstring );
6829             }
6830             else {
6831 0           new = xmlStrdup( encstring );
6832             }
6833 2           domSetNodeValue( self, new );
6834 2           xmlFree( new );
6835             }
6836 6           xmlFree( data );
6837             }
6838              
6839 6           xmlFree(encstring);
6840             }
6841             }
6842              
6843             MODULE = XML::LibXML PACKAGE = XML::LibXML::Comment
6844              
6845             SV *
6846             new( CLASS, content )
6847             SV * content
6848             PREINIT:
6849             xmlChar * encstring;
6850             xmlNodePtr newNode;
6851 7           ProxyNodePtr docfrag = NULL;
6852             CODE:
6853 7           encstring = Sv2C(content, NULL);
6854 7           newNode = xmlNewComment( encstring );
6855 7           xmlFree(encstring);
6856 7 50         if( newNode != NULL ) {
6857 7           docfrag = PmmNewFragment( NULL );
6858 7           xmlAddChild(PmmNODE(docfrag), newNode);
6859 7           RETVAL = PmmNodeToSv(newNode,docfrag);
6860             }
6861             else {
6862 0           XSRETURN_UNDEF;
6863             }
6864             OUTPUT:
6865             RETVAL
6866              
6867             MODULE = XML::LibXML PACKAGE = XML::LibXML::CDATASection
6868              
6869             SV *
6870             new( CLASS , content )
6871             SV * content
6872             PREINIT:
6873             xmlChar * encstring;
6874             xmlNodePtr newNode;
6875 7           ProxyNodePtr docfrag = NULL;
6876             CODE:
6877 7           encstring = Sv2C(content, NULL);
6878 7           newNode = xmlNewCDataBlock( NULL , encstring, xmlStrlen( encstring ) );
6879 7           xmlFree(encstring);
6880 7 50         if ( newNode != NULL ){
6881 7           docfrag = PmmNewFragment( NULL );
6882 7           xmlAddChild(PmmNODE(docfrag), newNode);
6883 7           RETVAL = PmmNodeToSv(newNode,docfrag);
6884             }
6885             else {
6886 0           XSRETURN_UNDEF;
6887             }
6888             OUTPUT:
6889             RETVAL
6890              
6891             MODULE = XML::LibXML PACKAGE = XML::LibXML::DocumentFragment
6892              
6893             SV*
6894             new( CLASS )
6895             PREINIT:
6896 29           xmlNodePtr real_doc=NULL;
6897             CODE:
6898 29           real_doc = xmlNewDocFragment( NULL );
6899 29           RETVAL = PmmNodeToSv( real_doc, NULL );
6900             OUTPUT:
6901             RETVAL
6902              
6903             MODULE = XML::LibXML PACKAGE = XML::LibXML::Attr
6904              
6905             SV*
6906             new( CLASS, pname, pvalue )
6907             SV * pname
6908             SV * pvalue
6909             PREINIT:
6910 0           xmlNodePtr attr = NULL;
6911             xmlChar * name;
6912             xmlChar * value;
6913             CODE:
6914 0           name = Sv2C(pname,NULL);
6915 0           value = Sv2C(pvalue,NULL);
6916 0 0         if ( name == NULL ) {
6917 0           XSRETURN_UNDEF;
6918             }
6919 0           attr = (xmlNodePtr)xmlNewProp( NULL, name, value );
6920 0           attr->doc = NULL;
6921 0           RETVAL = PmmNodeToSv(attr,NULL);
6922             OUTPUT:
6923             RETVAL
6924              
6925              
6926             SV*
6927             parentElement( self )
6928             ALIAS:
6929             XML::LibXML::Attr::getParentNode = 1
6930             XML::LibXML::Attr::getNextSibling = 2
6931             XML::LibXML::Attr::getPreviousSibling = 3
6932             XML::LibXML::Attr::nextSibling = 4
6933             XML::LibXML::Attr::previousSibling = 5
6934             CODE:
6935             /* override the original parentElement(), since this an attribute is
6936             * not part of the main tree
6937             */
6938              
6939             PERL_UNUSED_VAR(ix);
6940 0           XSRETURN_UNDEF;
6941             OUTPUT:
6942             RETVAL
6943              
6944             SV*
6945             serializeContent( self, useDomEncoding = &PL_sv_undef )
6946             SV * self
6947             SV * useDomEncoding
6948             PREINIT:
6949             xmlBufferPtr buffer;
6950 4           const xmlChar *ret = NULL;
6951 4           xmlAttrPtr node = (xmlAttrPtr)PmmSvNode(self);
6952             CODE:
6953 4           buffer = xmlBufferCreate();
6954 4           domAttrSerializeContent(buffer, node);
6955 4 50         if ( xmlBufferLength(buffer) > 0 ) {
6956 4           ret = xmlBufferContent( buffer );
6957             }
6958 4 50         if ( ret != NULL ) {
6959 4 50         if ( useDomEncoding != &PL_sv_undef && SvTRUE(useDomEncoding) ) {
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
6960 0           RETVAL = nodeC2Sv((xmlChar*)ret, PmmNODE(PmmPROXYNODE(node))) ;
6961             }
6962             else {
6963 4           RETVAL = C2Sv((xmlChar*)ret, NULL) ;
6964             }
6965 4           xmlBufferFree( buffer );
6966             }
6967             else {
6968 0           xmlBufferFree( buffer );
6969             xs_warn("Failed to convert attribute to string");
6970 0           XSRETURN_UNDEF;
6971             }
6972             OUTPUT:
6973             RETVAL
6974              
6975             SV*
6976             toString(self , format=0, useDomEncoding = &PL_sv_undef )
6977             SV * self
6978             SV * useDomEncoding
6979             int format
6980             ALIAS:
6981             XML::LibXML::Attr::serialize = 1
6982             PREINIT:
6983 10           xmlAttrPtr node = (xmlAttrPtr)PmmSvNode(self);
6984             xmlBufferPtr buffer;
6985 10           const xmlChar *ret = NULL;
6986             CODE:
6987             /* we add an extra method for serializing attributes since
6988             XML::LibXML::Node::toString causes segmentation fault inside
6989             libxml2
6990             */
6991             PERL_UNUSED_VAR(ix);
6992 10           buffer = xmlBufferCreate();
6993 10           xmlBufferAdd(buffer, BAD_CAST " ", 1);
6994 10 100         if ((node->ns != NULL) && (node->ns->prefix != NULL)) {
    50          
6995 2           xmlBufferAdd(buffer, node->ns->prefix, xmlStrlen(node->ns->prefix));
6996 2           xmlBufferAdd(buffer, BAD_CAST ":", 1);
6997             }
6998 10           xmlBufferAdd(buffer, node->name, xmlStrlen(node->name));
6999 10           xmlBufferAdd(buffer, BAD_CAST "=\"", 2);
7000 10           domAttrSerializeContent(buffer, node);
7001 10           xmlBufferAdd(buffer, BAD_CAST "\"", 1);
7002              
7003 10 50         if ( xmlBufferLength(buffer) > 0 ) {
7004 10           ret = xmlBufferContent( buffer );
7005             }
7006 10 50         if ( ret != NULL ) {
7007 10 50         if ( useDomEncoding != &PL_sv_undef && SvTRUE(useDomEncoding) ) {
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
7008 0           RETVAL = nodeC2Sv((xmlChar*)ret, PmmNODE(PmmPROXYNODE(node))) ;
7009             }
7010             else {
7011 10           RETVAL = C2Sv((xmlChar*)ret, NULL) ;
7012             }
7013 10           xmlBufferFree( buffer );
7014             }
7015             else {
7016 0           xmlBufferFree( buffer );
7017             xs_warn("Failed to convert attribute to string");
7018 0           XSRETURN_UNDEF;
7019             }
7020             OUTPUT:
7021             RETVAL
7022              
7023              
7024             int
7025             _setNamespace(self, namespaceURI, namespacePrefix = &PL_sv_undef )
7026             SV * self
7027             SV * namespaceURI
7028             SV * namespacePrefix
7029             PREINIT:
7030 2           xmlAttrPtr node = (xmlAttrPtr)PmmSvNode(self);
7031 2           xmlChar * nsURI = nodeSv2C(namespaceURI,(xmlNodePtr)node);
7032 2           xmlChar * nsPrefix = NULL;
7033 2           xmlNsPtr ns = NULL;
7034             INIT:
7035 2 50         if ( node == NULL ) {
7036 0           croak( "lost node" );
7037             }
7038             CODE:
7039 2 50         if ( !nsURI || xmlStrlen(nsURI)==0 ){
    100          
7040 1           xmlSetNs((xmlNodePtr)node, NULL);
7041 1           RETVAL = 1;
7042             }
7043 2 50         if ( !node->parent ) {
7044 0           XSRETURN_UNDEF;
7045             }
7046 2           nsPrefix = nodeSv2C(namespacePrefix, (xmlNodePtr)node);
7047 3           if ( (ns = xmlSearchNs(node->doc, node->parent, nsPrefix)) &&
7048 1           xmlStrEqual( ns->href, nsURI) ) {
7049             /* same uri and prefix */
7050 1           RETVAL = 1;
7051             }
7052 1 50         else if ( (ns = xmlSearchNsByHref(node->doc, node->parent, nsURI)) ) {
7053             /* set uri, but with a different prefix */
7054 0           RETVAL = 1;
7055             }
7056 1 50         else if (! RETVAL)
7057 0           RETVAL = 0;
7058              
7059 2 100         if ( ns ) {
7060 1 50         if ( ns->prefix ) {
7061 1           xmlSetNs((xmlNodePtr)node, ns);
7062             } else {
7063 0           RETVAL = 0;
7064             }
7065             }
7066 2           xmlFree(nsPrefix);
7067 2           xmlFree(nsURI);
7068             OUTPUT:
7069             RETVAL
7070              
7071             int
7072             isId( self )
7073             SV * self
7074             PREINIT:
7075 10           xmlAttrPtr attr = (xmlAttrPtr)PmmSvNode(self);
7076             xmlNodePtr elem;
7077             CODE:
7078 10 50         if ( attr == NULL ) {
7079 0           XSRETURN_UNDEF;
7080             }
7081 10           elem = attr->parent;
7082 10 50         if ( elem == NULL || elem->doc == NULL ) {
    50          
7083 0           XSRETURN_UNDEF;
7084             }
7085 10           RETVAL = xmlIsID( elem->doc, elem, attr );
7086             OUTPUT:
7087             RETVAL
7088              
7089             MODULE = XML::LibXML PACKAGE = XML::LibXML::Namespace
7090              
7091             SV*
7092             new(CLASS, namespaceURI, namespacePrefix=&PL_sv_undef)
7093             const char * CLASS
7094             SV * namespaceURI
7095             SV * namespacePrefix
7096             PREINIT:
7097 14           xmlNsPtr ns = NULL;
7098             xmlChar* nsURI;
7099             xmlChar* nsPrefix;
7100             CODE:
7101 14           RETVAL = &PL_sv_undef;
7102              
7103 14           nsURI = Sv2C(namespaceURI,NULL);
7104 14 50         if ( !nsURI ) {
7105 0           XSRETURN_UNDEF;
7106             }
7107 14           nsPrefix = Sv2C(namespacePrefix, NULL);
7108 14           ns = xmlNewNs(NULL, nsURI, nsPrefix);
7109 14 50         if ( ns ) {
7110 14           RETVAL = NEWSV(0,0);
7111 14           RETVAL = sv_setref_pv( RETVAL,
7112             CLASS,
7113             (void*)ns);
7114             }
7115 14           xmlFree(nsURI);
7116 14 100         if ( nsPrefix )
7117 9           xmlFree(nsPrefix);
7118             OUTPUT:
7119             RETVAL
7120              
7121             void
7122             DESTROY(self)
7123             SV * self
7124             PREINIT:
7125 36 50         xmlNsPtr ns = INT2PTR(xmlNsPtr,SvIV(SvRV(self)));
7126             CODE:
7127             xs_warn( "DESTROY NS" );
7128 36 50         if (ns) {
7129 36           xmlFreeNs(ns);
7130             }
7131              
7132             int
7133             nodeType(self)
7134             SV * self
7135             ALIAS:
7136             getType = 1
7137             PREINIT:
7138 3 50         xmlNsPtr ns = INT2PTR(xmlNsPtr,SvIV(SvRV(self)));
7139             CODE:
7140             PERL_UNUSED_VAR(ix);
7141 3           RETVAL = ns->type;
7142             OUTPUT:
7143             RETVAL
7144              
7145             SV*
7146             declaredURI(self)
7147             SV * self
7148             ALIAS:
7149             value = 1
7150             nodeValue = 2
7151             getData = 3
7152             getValue = 4
7153             value2 = 5
7154             href = 6
7155             PREINIT:
7156 12 50         xmlNsPtr ns = INT2PTR(xmlNsPtr,SvIV(SvRV(self)));
7157             xmlChar * href;
7158             CODE:
7159             PERL_UNUSED_VAR(ix);
7160 12           href = xmlStrdup(ns->href);
7161 12           RETVAL = C2Sv(href, NULL);
7162 12           xmlFree(href);
7163             OUTPUT:
7164             RETVAL
7165              
7166             SV*
7167             declaredPrefix(self)
7168             SV * self
7169             ALIAS:
7170             localname = 1
7171             getLocalName = 2
7172             PREINIT:
7173 20 50         xmlNsPtr ns = INT2PTR(xmlNsPtr,SvIV(SvRV(self)));
7174             xmlChar * prefix;
7175             CODE:
7176             PERL_UNUSED_VAR(ix);
7177 20           prefix = xmlStrdup(ns->prefix);
7178 20           RETVAL = C2Sv(prefix, NULL);
7179 20           xmlFree(prefix);
7180             OUTPUT:
7181             RETVAL
7182              
7183             SV*
7184             unique_key( self )
7185             SV * self
7186             PREINIT:
7187 10 50         xmlNsPtr ns = INT2PTR(xmlNsPtr,SvIV(SvRV(self)));
7188             xmlChar* key;
7189             CODE:
7190             /* Concatenate prefix and URI with vertical bar dividing*/
7191 10           key = xmlStrdup(ns->prefix);
7192 10           key = xmlStrcat(key, (const xmlChar*)"|");
7193 10           key = xmlStrcat(key, ns->href);
7194 10           RETVAL = C2Sv(key, NULL);
7195             OUTPUT:
7196             RETVAL
7197              
7198             int
7199             _isEqual(self, ref_node)
7200             SV * self
7201             SV * ref_node
7202             PREINIT:
7203 0 0         xmlNsPtr ns = INT2PTR(xmlNsPtr,SvIV(SvRV(self)));
7204 0 0         xmlNsPtr ons = INT2PTR(xmlNsPtr,SvIV(SvRV(ref_node)));
7205             CODE:
7206 0           RETVAL = 0;
7207 0 0         if ( ns == ons ) {
7208 0           RETVAL = 1;
7209             }
7210 0 0         else if ( xmlStrEqual(ns->href, ons->href)
7211 0 0         && xmlStrEqual(ns->prefix, ons->prefix) ) {
7212 0           RETVAL = 1;
7213             }
7214             OUTPUT:
7215             RETVAL
7216              
7217              
7218             MODULE = XML::LibXML PACKAGE = XML::LibXML::Dtd
7219              
7220             SV *
7221             new(CLASS, external, system)
7222             char * external
7223             char * system
7224             ALIAS:
7225             parse_uri = 1
7226             PREINIT:
7227 4           xmlDtdPtr dtd = NULL;
7228 4           PREINIT_SAVED_ERROR
7229             CODE:
7230             PERL_UNUSED_VAR(ix);
7231 4           INIT_ERROR_HANDLER;
7232 4           dtd = xmlParseDTD((const xmlChar*)external, (const xmlChar*)system);
7233 4 100         if ( dtd == NULL ) {
7234 2           CLEANUP_ERROR_HANDLER;
7235 2           REPORT_ERROR(0);
7236 1           XSRETURN_UNDEF;
7237             } else {
7238 2           xmlSetTreeDoc((xmlNodePtr)dtd, NULL);
7239 2           RETVAL = PmmNodeToSv( (xmlNodePtr) dtd, NULL );
7240 2           CLEANUP_ERROR_HANDLER;
7241 2           REPORT_ERROR(0);
7242             }
7243             OUTPUT:
7244             RETVAL
7245              
7246             SV*
7247             systemId( self )
7248             xmlDtdPtr self
7249             ALIAS:
7250             getSystemId = 1
7251             CODE:
7252             PERL_UNUSED_VAR(ix);
7253 3 100         if ( self->SystemID == NULL ) {
7254 1           XSRETURN_UNDEF;
7255             } else {
7256 2           RETVAL = C2Sv(self->SystemID,NULL);
7257             }
7258             OUTPUT:
7259             RETVAL
7260              
7261             SV*
7262             publicId( self )
7263             xmlDtdPtr self
7264             ALIAS:
7265             getPublicId = 1
7266             CODE:
7267             PERL_UNUSED_VAR(ix);
7268 3 100         if ( self->ExternalID == NULL ) {
7269 1           XSRETURN_UNDEF;
7270             } else {
7271 2           RETVAL = C2Sv(self->ExternalID,NULL);
7272             }
7273             OUTPUT:
7274             RETVAL
7275              
7276             SV *
7277             parse_string(CLASS, str, ...)
7278             char * str
7279             PREINIT:
7280             xmlDtdPtr res;
7281             SV * encoding_sv;
7282             xmlParserInputBufferPtr buffer;
7283 4           xmlCharEncoding enc = XML_CHAR_ENCODING_NONE;
7284             xmlChar * new_string;
7285 4           PREINIT_SAVED_ERROR
7286             CODE:
7287 4           INIT_ERROR_HANDLER;
7288 4 50         if (items > 2) {
7289 0           encoding_sv = ST(2);
7290 0 0         if (items > 3) {
7291 0           CLEANUP_ERROR_HANDLER;
7292 0           croak("parse_string: too many parameters");
7293             }
7294             /* warn("getting encoding...\n"); */
7295 0 0         enc = xmlParseCharEncoding(SvPV_nolen(encoding_sv));
7296 0 0         if (enc == XML_CHAR_ENCODING_ERROR) {
7297 0           CLEANUP_ERROR_HANDLER;
7298 0           REPORT_ERROR(1);
7299 0 0         croak("Parse of encoding %s failed", SvPV_nolen(encoding_sv));
7300             }
7301             }
7302 4           buffer = xmlAllocParserInputBuffer(enc);
7303             /* buffer = xmlParserInputBufferCreateMem(str, xmlStrlen(str), enc); */
7304 4 50         if ( !buffer) {
7305 0           CLEANUP_ERROR_HANDLER;
7306 0           REPORT_ERROR(1);
7307 0           croak("cannot create buffer!\n" );
7308             }
7309 4           new_string = xmlStrdup((const xmlChar*)str);
7310 4           xmlParserInputBufferPush(buffer, xmlStrlen(new_string), (const char*)new_string);
7311              
7312 4           res = xmlIOParseDTD(NULL, buffer, enc);
7313              
7314             /* NOTE: xmlIOParseDTD is documented to free its InputBuffer */
7315 4           xmlFree(new_string);
7316 4 100         if ( res && LibXML_will_die_ctx(saved_error, 0) )
    50          
7317 0           xmlFreeDtd( res );
7318 4           CLEANUP_ERROR_HANDLER;
7319 4           REPORT_ERROR(0);
7320 3 50         if (res == NULL) {
7321 0           croak("no DTD parsed!");
7322             }
7323 3           RETVAL = PmmNodeToSv((xmlNodePtr)res, NULL);
7324             OUTPUT:
7325             RETVAL
7326              
7327              
7328             #ifdef HAVE_SCHEMAS
7329              
7330             MODULE = XML::LibXML PACKAGE = XML::LibXML::RelaxNG
7331              
7332             void
7333             DESTROY( self )
7334             xmlRelaxNGPtr self
7335             CODE:
7336 6           xmlRelaxNGFree( self );
7337              
7338              
7339             xmlRelaxNGPtr
7340             parse_location( self, url, parser_options = 0, recover = FALSE )
7341             char * url
7342             int parser_options
7343             bool recover
7344             PREINIT:
7345 6           const char * CLASS = "XML::LibXML::RelaxNG";
7346 6           xmlRelaxNGParserCtxtPtr rngctxt = NULL;
7347 6           xmlExternalEntityLoader old_ext_ent_loader = NULL;
7348 6           PREINIT_SAVED_ERROR
7349             CODE:
7350 6           INIT_ERROR_HANDLER;
7351              
7352 6           rngctxt = xmlRelaxNGNewParserCtxt( url );
7353 6 50         if ( rngctxt == NULL ) {
7354 0           croak( "failed to initialize RelaxNG parser" );
7355             }
7356             #ifndef WITH_SERRORS
7357             /* Register Error callbacks */
7358             xmlRelaxNGSetParserErrors( rngctxt,
7359             (xmlRelaxNGValidityErrorFunc)LibXML_error_handler_ctx,
7360             (xmlRelaxNGValidityWarningFunc)LibXML_error_handler_ctx,
7361             saved_error );
7362             #endif
7363              
7364 6 50         if ( EXTERNAL_ENTITY_LOADER_FUNC == NULL && (parser_options & XML_PARSE_NONET) ) {
    100          
7365 1           old_ext_ent_loader = xmlGetExternalEntityLoader();
7366 1           xmlSetExternalEntityLoader( xmlNoNetExternalEntityLoader );
7367             }
7368              
7369 6           RETVAL = xmlRelaxNGParse( rngctxt );
7370              
7371 6 50         if ( EXTERNAL_ENTITY_LOADER_FUNC == NULL && (parser_options & XML_PARSE_NONET) )
    100          
7372 1           xmlSetExternalEntityLoader( (xmlExternalEntityLoader)old_ext_ent_loader );
7373              
7374 6           xmlRelaxNGFreeParserCtxt( rngctxt );
7375 6           CLEANUP_ERROR_HANDLER;
7376 6 100         REPORT_ERROR((RETVAL == NULL) ? 0 : recover);
7377             OUTPUT:
7378             RETVAL
7379              
7380              
7381             xmlRelaxNGPtr
7382             parse_buffer( self, perlstring, parser_options = 0, recover = FALSE )
7383             SV * perlstring
7384             int parser_options
7385             bool recover
7386             PREINIT:
7387 3           const char * CLASS = "XML::LibXML::RelaxNG";
7388 3           xmlRelaxNGParserCtxtPtr rngctxt = NULL;
7389 3           xmlExternalEntityLoader old_ext_ent_loader = NULL;
7390 3           char * string = NULL;
7391 3           STRLEN len = 0;
7392 3           PREINIT_SAVED_ERROR
7393             INIT:
7394 3 50         string = SvPV( perlstring, len );
7395 3 50         if ( string == NULL ) {
7396 0           croak( "cannot parse empty string" );
7397             }
7398             CODE:
7399 3           INIT_ERROR_HANDLER;
7400              
7401 3           rngctxt = xmlRelaxNGNewMemParserCtxt( string,len );
7402 3 50         if ( rngctxt == NULL ) {
7403 0           croak( "failed to initialize RelaxNG parser" );
7404             }
7405             #ifndef WITH_SERRORS
7406             /* Register Error callbacks */
7407             xmlRelaxNGSetParserErrors( rngctxt,
7408             (xmlRelaxNGValidityErrorFunc)LibXML_error_handler_ctx,
7409             (xmlRelaxNGValidityWarningFunc)LibXML_error_handler_ctx,
7410             saved_error );
7411             #endif
7412              
7413 3 50         if ( EXTERNAL_ENTITY_LOADER_FUNC == NULL && (parser_options & XML_PARSE_NONET) ) {
    100          
7414 1           old_ext_ent_loader = xmlGetExternalEntityLoader();
7415 1           xmlSetExternalEntityLoader( xmlNoNetExternalEntityLoader );
7416             }
7417              
7418 3           RETVAL = xmlRelaxNGParse( rngctxt );
7419              
7420 3 50         if ( EXTERNAL_ENTITY_LOADER_FUNC == NULL && (parser_options & XML_PARSE_NONET) )
    100          
7421 1           xmlSetExternalEntityLoader( (xmlExternalEntityLoader)old_ext_ent_loader );
7422              
7423 3           xmlRelaxNGFreeParserCtxt( rngctxt );
7424 3           CLEANUP_ERROR_HANDLER;
7425 3 100         REPORT_ERROR((RETVAL == NULL) ? 0 : recover);
7426             OUTPUT:
7427             RETVAL
7428              
7429              
7430             xmlRelaxNGPtr
7431             parse_document( self, doc, parser_options = 0, recover = FALSE )
7432             xmlDocPtr doc
7433             int parser_options
7434             bool recover
7435             PREINIT:
7436 2           const char * CLASS = "XML::LibXML::RelaxNG";
7437 2           xmlRelaxNGParserCtxtPtr rngctxt = NULL;
7438 2           xmlExternalEntityLoader old_ext_ent_loader = NULL;
7439 2           PREINIT_SAVED_ERROR
7440             CODE:
7441 2           INIT_ERROR_HANDLER;
7442              
7443 2           rngctxt = xmlRelaxNGNewDocParserCtxt( doc );
7444 2 50         if ( rngctxt == NULL ) {
7445 0           croak( "failed to initialize RelaxNG parser" );
7446             }
7447             #ifndef WITH_SERRORS
7448             /* Register Error callbacks */
7449             xmlRelaxNGSetParserErrors( rngctxt,
7450             (xmlRelaxNGValidityErrorFunc) LibXML_error_handler_ctx,
7451             (xmlRelaxNGValidityWarningFunc)LibXML_error_handler_ctx,
7452             saved_error );
7453             #endif
7454              
7455 2 50         if ( EXTERNAL_ENTITY_LOADER_FUNC == NULL && (parser_options & XML_PARSE_NONET) ) {
    50          
7456 0           old_ext_ent_loader = xmlGetExternalEntityLoader();
7457 0           xmlSetExternalEntityLoader( xmlNoNetExternalEntityLoader );
7458             }
7459              
7460 2           RETVAL = xmlRelaxNGParse( rngctxt );
7461              
7462 2 50         if ( EXTERNAL_ENTITY_LOADER_FUNC == NULL && (parser_options & XML_PARSE_NONET) )
    50          
7463 0           xmlSetExternalEntityLoader( (xmlExternalEntityLoader)old_ext_ent_loader );
7464              
7465 2           xmlRelaxNGFreeParserCtxt( rngctxt );
7466 2           CLEANUP_ERROR_HANDLER;
7467 2 100         REPORT_ERROR((RETVAL == NULL) ? 0 : recover);
7468             OUTPUT:
7469             RETVAL
7470              
7471             int
7472             validate( self, doc )
7473             xmlRelaxNGPtr self
7474             xmlDocPtr doc
7475             PREINIT:
7476 7           xmlRelaxNGValidCtxtPtr vctxt = NULL;
7477 7           PREINIT_SAVED_ERROR
7478             CODE:
7479 7           INIT_ERROR_HANDLER;
7480              
7481 7 50         if (doc) {
7482 7 50         PmmClearPSVI(doc);
    50          
    50          
    100          
7483 7 50         PmmInvalidatePSVI(doc);
    50          
7484             }
7485 7           vctxt = xmlRelaxNGNewValidCtxt( self );
7486 7 50         if ( vctxt == NULL ) {
7487 0           CLEANUP_ERROR_HANDLER;
7488 0           REPORT_ERROR(0);
7489 0           croak( "cannot initialize the validation context" );
7490             }
7491             #ifndef WITH_SERRORS
7492             /* Register Error callbacks */
7493             xmlRelaxNGSetValidErrors( vctxt,
7494             (xmlRelaxNGValidityErrorFunc)LibXML_error_handler_ctx,
7495             (xmlRelaxNGValidityWarningFunc)LibXML_error_handler_ctx,
7496             saved_error );
7497             #endif /* WITH_SERRORS */
7498             /* ** test only **
7499             xmlRelaxNGSetValidErrors( vctxt,
7500             (xmlRelaxNGValidityErrorFunc)fprintf,
7501             (xmlRelaxNGValidityWarningFunc)fprintf,
7502             stderr );
7503             */
7504 7           RETVAL = xmlRelaxNGValidateDoc( vctxt, doc );
7505 7           xmlRelaxNGFreeValidCtxt( vctxt );
7506 7           CLEANUP_ERROR_HANDLER;
7507 7           REPORT_ERROR(0);
7508 3 50         if ( RETVAL == 1 ) {
7509 0           XSRETURN_UNDEF;
7510             }
7511 3 50         if ( RETVAL == -1 ) {
7512 0           croak( "API Error" );
7513             XSRETURN_UNDEF;
7514             }
7515             OUTPUT:
7516             RETVAL
7517              
7518              
7519             MODULE = XML::LibXML PACKAGE = XML::LibXML::Schema
7520              
7521             void
7522             DESTROY( self )
7523             xmlSchemaPtr self
7524             CODE:
7525 5           xmlSchemaFree( self );
7526              
7527              
7528             xmlSchemaPtr
7529             parse_location( self, url, parser_options = 0, recover = FALSE )
7530             char * url
7531             int parser_options
7532             bool recover
7533             PREINIT:
7534 5           const char * CLASS = "XML::LibXML::Schema";
7535 5           xmlSchemaParserCtxtPtr rngctxt = NULL;
7536 5           xmlExternalEntityLoader old_ext_ent_loader = NULL;
7537 5           PREINIT_SAVED_ERROR
7538             CODE:
7539 5           INIT_ERROR_HANDLER;
7540              
7541 5           rngctxt = xmlSchemaNewParserCtxt( url );
7542 5 50         if ( rngctxt == NULL ) {
7543 0           CLEANUP_ERROR_HANDLER;
7544 0           REPORT_ERROR(0);
7545 0           croak( "failed to initialize Schema parser" );
7546             }
7547              
7548             /* Register Error callbacks */
7549 5           xmlSchemaSetParserErrors( rngctxt,
7550             (xmlSchemaValidityErrorFunc)LibXML_error_handler_ctx,
7551             (xmlSchemaValidityWarningFunc)LibXML_error_handler_ctx,
7552             saved_error );
7553              
7554 5 50         if ( EXTERNAL_ENTITY_LOADER_FUNC == NULL && (parser_options & XML_PARSE_NONET) ) {
    100          
7555 1           old_ext_ent_loader = xmlGetExternalEntityLoader();
7556 1           xmlSetExternalEntityLoader( xmlNoNetExternalEntityLoader );
7557             }
7558              
7559 5           RETVAL = xmlSchemaParse( rngctxt );
7560              
7561 5 50         if ( EXTERNAL_ENTITY_LOADER_FUNC == NULL && (parser_options & XML_PARSE_NONET) )
    100          
7562 1           xmlSetExternalEntityLoader( (xmlExternalEntityLoader)old_ext_ent_loader );
7563              
7564 5           xmlSchemaFreeParserCtxt( rngctxt );
7565 5           CLEANUP_ERROR_HANDLER;
7566 5 100         REPORT_ERROR((RETVAL == NULL) ? 0 : recover);
7567             OUTPUT:
7568             RETVAL
7569              
7570              
7571             xmlSchemaPtr
7572             parse_buffer( self, perlstring, parser_options = 0, recover = FALSE )
7573             SV * perlstring
7574             int parser_options
7575             bool recover
7576             PREINIT:
7577 4           const char * CLASS = "XML::LibXML::Schema";
7578 4           xmlSchemaParserCtxtPtr rngctxt = NULL;
7579 4           xmlExternalEntityLoader old_ext_ent_loader = NULL;
7580 4           char * string = NULL;
7581 4           STRLEN len = 0;
7582 4           PREINIT_SAVED_ERROR
7583             INIT:
7584 4 50         string = SvPV( perlstring, len );
7585 4 50         if ( string == NULL ) {
7586 0           croak( "cannot parse empty string" );
7587             }
7588             CODE:
7589 4           INIT_ERROR_HANDLER;
7590              
7591 4           rngctxt = xmlSchemaNewMemParserCtxt( string,len );
7592 4 50         if ( rngctxt == NULL ) {
7593 0           CLEANUP_ERROR_HANDLER;
7594 0           REPORT_ERROR(0);
7595 0           croak( "failed to initialize Schema parser" );
7596             }
7597              
7598             /* Register Error callbacks */
7599 4           xmlSchemaSetParserErrors( rngctxt,
7600             (xmlSchemaValidityErrorFunc)LibXML_error_handler_ctx,
7601             (xmlSchemaValidityWarningFunc)LibXML_error_handler_ctx,
7602             saved_error );
7603              
7604 4 50         if ( EXTERNAL_ENTITY_LOADER_FUNC == NULL && (parser_options & XML_PARSE_NONET) ) {
    100          
7605 1           old_ext_ent_loader = xmlGetExternalEntityLoader();
7606 1           xmlSetExternalEntityLoader( xmlNoNetExternalEntityLoader );
7607             }
7608              
7609 4           RETVAL = xmlSchemaParse( rngctxt );
7610              
7611 4 50         if ( EXTERNAL_ENTITY_LOADER_FUNC == NULL && (parser_options & XML_PARSE_NONET) )
    100          
7612 1           xmlSetExternalEntityLoader( (xmlExternalEntityLoader)old_ext_ent_loader );
7613              
7614 4           xmlSchemaFreeParserCtxt( rngctxt );
7615 4           CLEANUP_ERROR_HANDLER;
7616 4 100         REPORT_ERROR((RETVAL == NULL) ? 0 : recover);
7617             OUTPUT:
7618             RETVAL
7619              
7620              
7621             int
7622             validate( self, node )
7623             xmlSchemaPtr self
7624             xmlNodePtr node
7625             PREINIT:
7626 3           xmlSchemaValidCtxtPtr vctxt = NULL;
7627 3           PREINIT_SAVED_ERROR
7628             CODE:
7629 3           INIT_ERROR_HANDLER;
7630              
7631 3 100         if (node->type == XML_DOCUMENT_NODE) {
7632 2 50         PmmClearPSVI((xmlDocPtr)node);
    50          
    50          
    50          
7633 2 50         PmmInvalidatePSVI((xmlDocPtr)node);
    50          
7634             }
7635 3           vctxt = xmlSchemaNewValidCtxt( self );
7636 3 50         if ( vctxt == NULL ) {
7637 0           CLEANUP_ERROR_HANDLER;
7638 0           REPORT_ERROR(0);
7639 0           croak( "cannot initialize the validation context" );
7640             }
7641              
7642             /* Register Error callbacks */
7643 3           xmlSchemaSetValidErrors( vctxt,
7644             (xmlSchemaValidityErrorFunc)LibXML_error_handler_ctx,
7645             (xmlSchemaValidityWarningFunc)LibXML_error_handler_ctx,
7646             saved_error );
7647              
7648 3 100         if (node->type == XML_DOCUMENT_NODE) {
7649 2           RETVAL = xmlSchemaValidateDoc(vctxt, (xmlDocPtr)node);
7650             }
7651             else {
7652 1           RETVAL = xmlSchemaValidateOneElement(vctxt, node);
7653             }
7654              
7655 3           xmlSchemaFreeValidCtxt( vctxt );
7656              
7657 3           CLEANUP_ERROR_HANDLER;
7658 3           REPORT_ERROR(0);
7659 2 50         if ( RETVAL > 0 ) {
7660 0           XSRETURN_UNDEF;
7661             }
7662 2 50         if ( RETVAL == -1 ) {
7663 0           croak( "API Error" );
7664             XSRETURN_UNDEF;
7665             }
7666             OUTPUT:
7667             RETVAL
7668              
7669             #endif /* HAVE_SCHEMAS */
7670              
7671             MODULE = XML::LibXML::XPathContext PACKAGE = XML::LibXML::XPathContext
7672              
7673             # PROTOTYPES: DISABLE
7674              
7675             SV*
7676             new( CLASS, ... )
7677             const char * CLASS
7678             PREINIT:
7679 30           SV * pnode = &PL_sv_undef;
7680             INIT:
7681             xmlXPathContextPtr ctxt;
7682             CODE:
7683 30 100         if( items > 1 )
7684 26           pnode = ST(1);
7685              
7686 30           ctxt = xmlXPathNewContext( NULL );
7687 30           ctxt->namespaces = NULL;
7688              
7689 30           New(0, ctxt->user, sizeof(XPathContextData), XPathContextData);
7690 30 50         if (ctxt->user == NULL) {
7691 0           croak("XPathContext: failed to allocate proxy object\n");
7692             }
7693              
7694 30 100         if (SvOK(pnode)) {
    50          
    50          
7695 26           XPathContextDATA(ctxt)->node = newSVsv(pnode);
7696             } else {
7697 4           XPathContextDATA(ctxt)->node = &PL_sv_undef;
7698             }
7699              
7700 30           XPathContextDATA(ctxt)->pool = NULL;
7701 30           XPathContextDATA(ctxt)->varLookup = NULL;
7702 30           XPathContextDATA(ctxt)->varData = NULL;
7703              
7704 30           xmlXPathRegisterFunc(ctxt,
7705             (const xmlChar *) "document",
7706             perlDocumentFunction);
7707              
7708 30           RETVAL = NEWSV(0,0),
7709 30           RETVAL = sv_setref_pv( RETVAL,
7710             CLASS,
7711             (void*)ctxt );
7712             OUTPUT:
7713             RETVAL
7714              
7715             void
7716             DESTROY( self )
7717             SV * self
7718             INIT:
7719 30 50         xmlXPathContextPtr ctxt = INT2PTR(xmlXPathContextPtr,SvIV(SvRV(self)));
7720             CODE:
7721             xs_warn( "DESTROY XPATH CONTEXT" );
7722 30 50         if (ctxt) {
7723 30 50         if (XPathContextDATA(ctxt) != NULL) {
7724 30 100         if (XPathContextDATA(ctxt)->node != NULL &&
    100          
7725 1 50         SvOK(XPathContextDATA(ctxt)->node)) {
    50          
7726 27           SvREFCNT_dec(XPathContextDATA(ctxt)->node);
7727             }
7728 30 100         if (XPathContextDATA(ctxt)->varLookup != NULL &&
    50          
7729 0 0         SvOK(XPathContextDATA(ctxt)->varLookup)) {
    0          
7730 2           SvREFCNT_dec(XPathContextDATA(ctxt)->varLookup);
7731             }
7732 30 100         if (XPathContextDATA(ctxt)->varData != NULL &&
    50          
7733 0 0         SvOK(XPathContextDATA(ctxt)->varData)) {
    0          
7734 1           SvREFCNT_dec(XPathContextDATA(ctxt)->varData);
7735             }
7736 30 50         if (XPathContextDATA(ctxt)->pool != NULL &&
    0          
7737 0 0         SvOK(XPathContextDATA(ctxt)->pool)) {
    0          
7738 0           SvREFCNT_dec((SV *)XPathContextDATA(ctxt)->pool);
7739             }
7740 30           Safefree(XPathContextDATA(ctxt));
7741             }
7742              
7743 30 100         if (ctxt->namespaces != NULL) {
7744 4           xmlFree( ctxt->namespaces );
7745             }
7746 30 100         if (ctxt->funcLookupData != NULL && SvROK((SV*)ctxt->funcLookupData)
    50          
7747 1 50         && SvTYPE(SvRV((SV *)ctxt->funcLookupData)) == SVt_PVHV) {
7748 1           SvREFCNT_dec((SV *)ctxt->funcLookupData);
7749             }
7750              
7751 30           xmlXPathFreeContext(ctxt);
7752             }
7753              
7754             SV*
7755             getContextNode( self )
7756             SV * self
7757             INIT:
7758 27 50         xmlXPathContextPtr ctxt = INT2PTR(xmlXPathContextPtr,SvIV(SvRV(self)));
7759 27 50         if ( ctxt == NULL ) {
7760 0           croak("XPathContext: missing xpath context\n");
7761             }
7762             CODE:
7763 27 100         if(XPathContextDATA(ctxt)->node != NULL) {
7764 14           RETVAL = newSVsv(XPathContextDATA(ctxt)->node);
7765             } else {
7766 13           RETVAL = &PL_sv_undef;
7767             }
7768             OUTPUT:
7769             RETVAL
7770              
7771             int
7772             getContextPosition( self )
7773             SV * self
7774             INIT:
7775 4 50         xmlXPathContextPtr ctxt = INT2PTR(xmlXPathContextPtr,SvIV(SvRV(self)));
7776 4 50         if ( ctxt == NULL ) {
7777 0           croak("XPathContext: missing xpath context\n");
7778             }
7779             CODE:
7780 4           RETVAL = ctxt->proximityPosition;
7781             OUTPUT:
7782             RETVAL
7783              
7784             int
7785             getContextSize( self )
7786             SV * self
7787             INIT:
7788 5 50         xmlXPathContextPtr ctxt = INT2PTR(xmlXPathContextPtr,SvIV(SvRV(self)));
7789 5 50         if ( ctxt == NULL ) {
7790 0           croak("XPathContext: missing xpath context\n");
7791             }
7792             CODE:
7793 5           RETVAL = ctxt->contextSize;
7794             OUTPUT:
7795             RETVAL
7796              
7797             void
7798             setContextNode( self , pnode )
7799             SV * self
7800             SV * pnode
7801             INIT:
7802 40 50         xmlXPathContextPtr ctxt = INT2PTR(xmlXPathContextPtr,SvIV(SvRV(self)));
7803 40 50         if ( ctxt == NULL ) {
7804 0           croak("XPathContext: missing xpath context\n");
7805             }
7806             PPCODE:
7807 40 100         if (XPathContextDATA(ctxt)->node != NULL) {
7808 27           SvREFCNT_dec(XPathContextDATA(ctxt)->node);
7809             }
7810 40 100         if (SvOK(pnode)) {
    50          
    50          
7811 25           XPathContextDATA(ctxt)->node = newSVsv(pnode);
7812             } else {
7813 15           XPathContextDATA(ctxt)->node = NULL;
7814             }
7815              
7816             void
7817             setContextPosition( self , position )
7818             SV * self
7819             int position
7820             INIT:
7821 4 50         xmlXPathContextPtr ctxt = INT2PTR(xmlXPathContextPtr,SvIV(SvRV(self)));
7822 4 50         if ( ctxt == NULL )
7823 0           croak("XPathContext: missing xpath context\n");
7824 4 100         if ( position < -1 || position > ctxt->contextSize )
    100          
7825 3           croak("XPathContext: invalid position\n");
7826             PPCODE:
7827 1           ctxt->proximityPosition = position;
7828              
7829             void
7830             setContextSize( self , size )
7831             SV * self
7832             int size
7833             INIT:
7834 4 50         xmlXPathContextPtr ctxt = INT2PTR(xmlXPathContextPtr,SvIV(SvRV(self)));
7835 4 50         if ( ctxt == NULL )
7836 0           croak("XPathContext: missing xpath context\n");
7837 4 100         if ( size < -1 )
7838 1           croak("XPathContext: invalid size\n");
7839             PPCODE:
7840 3           ctxt->contextSize = size;
7841 3 100         if ( size == 0 )
7842 1           ctxt->proximityPosition = 0;
7843 2 100         else if ( size > 0 )
7844 1           ctxt->proximityPosition = 1;
7845             else
7846 1           ctxt->proximityPosition = -1;
7847              
7848             void
7849             registerNs( pxpath_context, prefix, ns_uri )
7850             SV * pxpath_context
7851             SV * prefix
7852             SV * ns_uri
7853             PREINIT:
7854 11           xmlXPathContextPtr ctxt = NULL;
7855             INIT:
7856 11 50         ctxt = INT2PTR(xmlXPathContextPtr,SvIV(SvRV(pxpath_context)));
7857 11 50         if ( ctxt == NULL ) {
7858 0           croak("XPathContext: missing xpath context\n");
7859             }
7860 11           LibXML_configure_xpathcontext(ctxt);
7861             PPCODE:
7862 11 100         if(SvOK(ns_uri)) {
    50          
    50          
7863 8 50         if(xmlXPathRegisterNs(ctxt, (xmlChar *) SvPV_nolen(prefix),
    50          
    50          
7864 8           (xmlChar *) SvPV_nolen(ns_uri)) == -1) {
7865 0           croak("XPathContext: cannot register namespace\n");
7866             }
7867             } else {
7868 3 50         if(xmlXPathRegisterNs(ctxt, (xmlChar *) SvPV_nolen(prefix), NULL) == -1) {
    50          
7869 0           croak("XPathContext: cannot unregister namespace\n");
7870             }
7871             }
7872              
7873             SV*
7874             lookupNs( pxpath_context, prefix )
7875             SV * pxpath_context
7876             SV * prefix
7877             PREINIT:
7878 3           xmlXPathContextPtr ctxt = NULL;
7879             INIT:
7880 3 50         ctxt = INT2PTR(xmlXPathContextPtr,SvIV(SvRV(pxpath_context)));
7881 3 50         if ( ctxt == NULL ) {
7882 0           croak("XPathContext: missing xpath context\n");
7883             }
7884 3           LibXML_configure_xpathcontext(ctxt);
7885             CODE:
7886 3 50         RETVAL = C2Sv(xmlXPathNsLookup(ctxt, (xmlChar *) SvPV_nolen(prefix)), NULL);
7887             OUTPUT:
7888             RETVAL
7889              
7890             SV*
7891             getVarLookupData( self )
7892             SV * self
7893             INIT:
7894 6 50         xmlXPathContextPtr ctxt = INT2PTR(xmlXPathContextPtr,SvIV(SvRV(self)));
7895 6 50         if ( ctxt == NULL ) {
7896 0           croak("XPathContext: missing xpath context\n");
7897             }
7898             CODE:
7899 6 100         if(XPathContextDATA(ctxt)->varData != NULL) {
7900 5           RETVAL = newSVsv(XPathContextDATA(ctxt)->varData);
7901             } else {
7902 1           RETVAL = &PL_sv_undef;
7903             }
7904             OUTPUT:
7905             RETVAL
7906              
7907             SV*
7908             getVarLookupFunc( self )
7909             SV * self
7910             INIT:
7911 2 50         xmlXPathContextPtr ctxt = INT2PTR(xmlXPathContextPtr,SvIV(SvRV(self)));
7912 2 50         if ( ctxt == NULL ) {
7913 0           croak("XPathContext: missing xpath context\n");
7914             }
7915             CODE:
7916 2 100         if(XPathContextDATA(ctxt)->varData != NULL) {
7917 1           RETVAL = newSVsv(XPathContextDATA(ctxt)->varLookup);
7918             } else {
7919 1           RETVAL = &PL_sv_undef;
7920             }
7921             OUTPUT:
7922             RETVAL
7923              
7924             void
7925             registerVarLookupFunc( pxpath_context, lookup_func, lookup_data )
7926             SV * pxpath_context
7927             SV * lookup_func
7928             SV * lookup_data
7929             PREINIT:
7930 4           xmlXPathContextPtr ctxt = NULL;
7931 4           XPathContextDataPtr data = NULL;
7932             INIT:
7933 4 50         ctxt = INT2PTR(xmlXPathContextPtr,SvIV(SvRV(pxpath_context)));
7934 4 50         if ( ctxt == NULL )
7935 0           croak("XPathContext: missing xpath context\n");
7936 4           data = XPathContextDATA(ctxt);
7937 4 50         if ( data == NULL )
7938 0           croak("XPathContext: missing xpath context private data\n");
7939 4           LibXML_configure_xpathcontext(ctxt);
7940             /* free previous lookup function and data */
7941 4 100         if (data->varLookup && SvOK(data->varLookup))
    50          
    0          
    0          
7942 1           SvREFCNT_dec(data->varLookup);
7943 4 100         if (data->varData && SvOK(data->varData))
    50          
    0          
    0          
7944 1           SvREFCNT_dec(data->varData);
7945 4           data->varLookup=NULL;
7946 4           data->varData=NULL;
7947             PPCODE:
7948 4 100         if (SvOK(lookup_func)) {
    50          
    50          
7949 6 50         if ( SvROK(lookup_func) && SvTYPE(SvRV(lookup_func)) == SVt_PVCV ) {
    50          
7950 3           data->varLookup = newSVsv(lookup_func);
7951 3 100         if (SvOK(lookup_data))
    50          
    50          
7952 2           data->varData = newSVsv(lookup_data);
7953 3           xmlXPathRegisterVariableLookup(ctxt,
7954             LibXML_generic_variable_lookup, ctxt);
7955 3 50         if (ctxt->varLookupData==NULL || ctxt->varLookupData != ctxt) {
    50          
7956 0           croak( "XPathContext: registration failure\n" );
7957             }
7958             } else {
7959 0           croak("XPathContext: 1st argument is not a CODE reference\n");
7960             }
7961             } else {
7962             /* unregister */
7963 1           xmlXPathRegisterVariableLookup(ctxt, NULL, NULL);
7964             }
7965              
7966             void
7967             registerFunctionNS( pxpath_context, name, uri, func)
7968             SV * pxpath_context
7969             char * name
7970             SV * uri
7971             SV * func
7972             PREINIT:
7973 14           xmlXPathContextPtr ctxt = NULL;
7974             SV * pfdr;
7975             SV * key;
7976             STRLEN len;
7977             char *strkey;
7978              
7979             INIT:
7980 14 50         ctxt = INT2PTR(xmlXPathContextPtr,SvIV(SvRV(pxpath_context)));
7981 14 50         if ( ctxt == NULL ) {
7982 0           croak("XPathContext: missing xpath context\n");
7983             }
7984 14           LibXML_configure_xpathcontext(ctxt);
7985 14 100         if ( !SvOK(func) ||
    50          
    50          
    50          
7986 11 0         (SvOK(func) && ((SvROK(func) && SvTYPE(SvRV(func)) == SVt_PVCV )
    0          
    100          
    50          
7987 1 50         || SvPOK(func)))) {
7988 14 100         if (ctxt->funcLookupData == NULL) {
7989 1 50         if (SvOK(func)) {
    0          
    0          
7990 1           pfdr = newRV_noinc((SV*) newHV());
7991 1           ctxt->funcLookupData = pfdr;
7992             } else {
7993             /* looks like no perl function was never registered, */
7994             /* nothing to unregister */
7995 0           warn("XPathContext: nothing to unregister\n");
7996 0           return;
7997             }
7998             } else {
7999 13 50         if (SvTYPE(SvRV((SV *)ctxt->funcLookupData)) == SVt_PVHV) {
8000             /* good, it's a HV */
8001 13           pfdr = (SV *)ctxt->funcLookupData;
8002             } else {
8003 0           croak ("XPathContext: cannot register: funcLookupData structure occupied\n");
8004             }
8005             }
8006 14           key = newSVpvn("",0);
8007 14 100         if (SvOK(uri)) {
    50          
    50          
8008 2           sv_catpv(key, "{");
8009 2           sv_catsv(key, uri);
8010 2           sv_catpv(key, "}");
8011             }
8012 14           sv_catpv(key, (const char*)name);
8013 14 50         strkey = SvPV(key, len);
8014             /* warn("Trying to store function '%s' in %d\n", strkey, pfdr); */
8015 14 100         if (SvOK(func)) {
    50          
    50          
8016 11           (void) hv_store((HV *)SvRV(pfdr),strkey, len, newSVsv(func), 0);
8017             } else {
8018             /* unregister */
8019 3           (void) hv_delete((HV *)SvRV(pfdr),strkey, len, G_DISCARD);
8020             }
8021 14           SvREFCNT_dec(key);
8022             } else {
8023 0           croak("XPathContext: 3rd argument is not a CODE reference or function name\n");
8024             }
8025             PPCODE:
8026 14 100         if (SvOK(uri)) {
    50          
    50          
8027 3 100         xmlXPathRegisterFuncNS(ctxt, (xmlChar *) name,
    50          
8028 4           (xmlChar *) SvPV(uri, len),
8029 1 50         (SvOK(func) ?
    50          
8030             LibXML_generic_extension_function : NULL));
8031             } else {
8032 14 100         xmlXPathRegisterFunc(ctxt, (xmlChar *) name,
8033 2 50         (SvOK(func) ?
    50          
8034             LibXML_generic_extension_function : NULL));
8035             }
8036              
8037             void
8038             _free_node_pool( pxpath_context )
8039             SV * pxpath_context
8040             PREINIT:
8041 130           xmlXPathContextPtr ctxt = NULL;
8042             INIT:
8043 130 50         ctxt = INT2PTR(xmlXPathContextPtr,SvIV(SvRV(pxpath_context)));
8044 130 50         if ( ctxt == NULL ) {
8045 0           croak("XPathContext: missing xpath context\n");
8046             }
8047             PPCODE:
8048 130 100         if (XPathContextDATA(ctxt)->pool != NULL) {
8049 20           SvREFCNT_dec((SV *)XPathContextDATA(ctxt)->pool);
8050 20           XPathContextDATA(ctxt)->pool = NULL;
8051             }
8052              
8053             void
8054             _findnodes( pxpath_context, perl_xpath )
8055             SV * pxpath_context
8056             SV * perl_xpath
8057             PREINIT:
8058 61           xmlXPathContextPtr ctxt = NULL;
8059 61           ProxyNodePtr owner = NULL;
8060 61           xmlXPathObjectPtr found = NULL;
8061 61           xmlNodeSetPtr nodelist = NULL;
8062 61           SV * element = NULL ;
8063 61           xmlChar * xpath = NULL;
8064 61           xmlXPathCompExprPtr comp = NULL;
8065 61           PREINIT_SAVED_ERROR
8066             INIT:
8067 61 50         ctxt = INT2PTR(xmlXPathContextPtr,SvIV(SvRV(pxpath_context)));
8068 61 50         if ( ctxt == NULL ) {
8069 0           croak("XPathContext: missing xpath context\n");
8070             }
8071 61           LibXML_configure_xpathcontext(ctxt);
8072 61 50         if ( ctxt->node == NULL ) {
8073 0           croak("XPathContext: lost current node\n");
8074             }
8075 61 100         if (sv_isobject(perl_xpath) && sv_isa(perl_xpath,"XML::LibXML::XPathExpression")) {
    50          
8076 4 50         comp = INT2PTR(xmlXPathCompExprPtr,SvIV((SV*)SvRV( perl_xpath )));
8077 4 50         if (!comp) XSRETURN_UNDEF;
8078             } else {
8079 57           xpath = nodeSv2C(perl_xpath, ctxt->node);
8080 57 50         if ( !(xpath && xmlStrlen(xpath)) ) {
    50          
8081 0 0         if ( xpath )
8082 0           xmlFree(xpath);
8083 0           croak("XPathContext: empty XPath found\n");
8084             XSRETURN_UNDEF;
8085             }
8086             }
8087             PPCODE:
8088 61           INIT_ERROR_HANDLER;
8089              
8090 61           PUTBACK ;
8091 61 100         if (comp) {
8092 4           found = domXPathCompFindCtxt( ctxt, comp, 0 );
8093             } else {
8094 57           found = domXPathFindCtxt( ctxt, xpath, 0 );
8095 57           xmlFree(xpath);
8096             }
8097 61           SPAGAIN ;
8098              
8099 61 100         if (found != NULL) {
8100 59           nodelist = found->nodesetval;
8101             } else {
8102 2           nodelist = NULL;
8103             }
8104 61           CLEANUP_ERROR_HANDLER;
8105 61 100         if ( nodelist ) {
8106 59           REPORT_ERROR(1);
8107 59 50         if ( nodelist->nodeNr > 0 ) {
8108             int i;
8109 59           const char * cls = "XML::LibXML::Node";
8110             xmlNodePtr tnode;
8111 59           int l = nodelist->nodeNr;
8112 3135 100         for( i = 0 ; i < l; i++){
8113             /* we have to create a new instance of an objectptr.
8114             * and then place the current node into the new object.
8115             * afterwards we can push the object to the array!
8116             */
8117 3076           element = NULL;
8118 3076           tnode = nodelist->nodeTab[i];
8119 3076 50         if (tnode->type == XML_NAMESPACE_DECL) {
8120 0           xmlNsPtr newns = xmlCopyNamespace((xmlNsPtr)tnode);
8121 0 0         if ( newns != NULL ) {
8122 0           element = NEWSV(0,0);
8123 0           cls = PmmNodeTypeName( tnode );
8124 0           element = sv_setref_pv( element,
8125             (const char *)cls,
8126             newns
8127             );
8128             }
8129             else {
8130 0           continue;
8131             }
8132             }
8133             else {
8134 3076 100         if (tnode->doc) {
8135 3073 50         owner = PmmOWNERPO(PmmNewNode((xmlNodePtr) tnode->doc));
    50          
8136             } else {
8137             /* we try to find a known node on the ancestor axis */
8138 3           xmlNodePtr n = tnode;
8139 5 50         while (n && n->_private == NULL) n = n->parent;
    100          
8140 3 50         if (n) owner = PmmOWNERPO(((ProxyNodePtr)n->_private));
    50          
    50          
8141 0           else owner = NULL; /* self contained node */
8142             }
8143 3076           element = PmmNodeToSv(tnode, owner);
8144             }
8145 3076 50         XPUSHs( sv_2mortal(element) );
8146             }
8147             }
8148             /* prevent libxml2 from freeing the actual nodes */
8149 59 50         if (found->boolval) found->boolval=0;
8150 59           xmlXPathFreeObject(found);
8151             }
8152             else {
8153 2           xmlXPathFreeObject(found);
8154 2           REPORT_ERROR(0);
8155             }
8156              
8157             void
8158             _find( pxpath_context, pxpath, to_bool )
8159             SV * pxpath_context
8160             SV * pxpath
8161             int to_bool
8162             PREINIT:
8163 69           xmlXPathContextPtr ctxt = NULL;
8164 69           ProxyNodePtr owner = NULL;
8165 69           xmlXPathObjectPtr found = NULL;
8166 69           xmlNodeSetPtr nodelist = NULL;
8167 69           xmlChar * xpath = NULL;
8168 69           xmlXPathCompExprPtr comp = NULL;
8169 69           PREINIT_SAVED_ERROR
8170             INIT:
8171 69 50         ctxt = INT2PTR(xmlXPathContextPtr,SvIV(SvRV(pxpath_context)));
8172 69 50         if ( ctxt == NULL ) {
8173 0           croak("XPathContext: missing xpath context\n");
8174             }
8175 69           LibXML_configure_xpathcontext(ctxt);
8176 69 100         if ( ctxt->node == NULL ) {
8177 1           croak("XPathContext: lost current node\n");
8178             }
8179 68 100         if (sv_isobject(pxpath) && sv_isa(pxpath,"XML::LibXML::XPathExpression")) {
    50          
8180 3 50         comp = INT2PTR(xmlXPathCompExprPtr,SvIV((SV*)SvRV( pxpath )));
8181 3 50         if (!comp) XSRETURN_UNDEF;
8182             } else {
8183 65           xpath = nodeSv2C(pxpath, ctxt->node);
8184 65 50         if ( !(xpath && xmlStrlen(xpath)) ) {
    50          
8185 0 0         if ( xpath )
8186 0           xmlFree(xpath);
8187 0           croak("XPathContext: empty XPath found\n");
8188             XSRETURN_UNDEF;
8189             }
8190             }
8191             PPCODE:
8192 68           INIT_ERROR_HANDLER;
8193 68           PUTBACK ;
8194 68 100         if (comp) {
8195 3           found = domXPathCompFindCtxt( ctxt, comp, to_bool );
8196             } else {
8197 65           found = domXPathFindCtxt( ctxt, xpath, to_bool );
8198 64           xmlFree(xpath);
8199             }
8200 67           SPAGAIN ;
8201 67           CLEANUP_ERROR_HANDLER;
8202 67 100         if (found) {
8203 59           REPORT_ERROR(1);
8204 59           switch (found->type) {
8205             case XPATH_NODESET:
8206             /* return as a NodeList */
8207             /* access ->nodesetval */
8208 10 50         XPUSHs(sv_2mortal(newSVpv("XML::LibXML::NodeList", 0)));
8209 10           nodelist = found->nodesetval;
8210 10 50         if ( nodelist ) {
8211 10 50         if ( nodelist->nodeNr > 0 ) {
8212             int i;
8213 10           const char * cls = "XML::LibXML::Node";
8214             xmlNodePtr tnode;
8215             SV * element;
8216 10           int l = nodelist->nodeNr;
8217              
8218 6021 100         for( i = 0 ; i < l; i++){
8219             /* we have to create a new instance of an
8220             * objectptr. and then
8221             * place the current node into the new
8222             * object. afterwards we can
8223             * push the object to the array!
8224             */
8225 6011           tnode = nodelist->nodeTab[i];
8226              
8227             /* let's be paranoid */
8228 6011 50         if (tnode->type == XML_NAMESPACE_DECL) {
8229 0           xmlNsPtr newns = xmlCopyNamespace((xmlNsPtr)tnode);
8230 0 0         if ( newns != NULL ) {
8231 0           element = NEWSV(0,0);
8232 0           cls = PmmNodeTypeName( tnode );
8233 0           element = sv_setref_pv( element,
8234             (const char *)cls,
8235             (void*)newns
8236             );
8237             }
8238             else {
8239 0           continue;
8240             }
8241             }
8242             else {
8243 6011 50         if (tnode->doc) {
8244 6011 50         owner = PmmOWNERPO(PmmNewNode((xmlNodePtr) tnode->doc));
    50          
8245             } else {
8246             /* we try to find a known node on the ancestor axis */
8247 0           xmlNodePtr n = tnode;
8248 0 0         while (n && n->_private == NULL) n = n->parent;
    0          
8249 0 0         if (n) owner = PmmOWNERPO(((ProxyNodePtr)n->_private));
    0          
    0          
8250 0           else owner = NULL; /* self contained node */
8251             }
8252 6011           element = PmmNodeToSv(tnode, owner);
8253             }
8254 6011 50         XPUSHs( sv_2mortal(element) );
8255             }
8256             }
8257             }
8258             /* prevent libxml2 from freeing the actual nodes */
8259 10 50         if (found->boolval) found->boolval=0;
8260 10           break;
8261             case XPATH_BOOLEAN:
8262             /* return as a Boolean */
8263             /* access ->boolval */
8264 14 50         XPUSHs(sv_2mortal(newSVpv("XML::LibXML::Boolean", 0)));
8265 14 50         XPUSHs(sv_2mortal(newSViv(found->boolval)));
8266 14           break;
8267             case XPATH_NUMBER:
8268             /* return as a Number */
8269             /* access ->floatval */
8270 24 50         XPUSHs(sv_2mortal(newSVpv("XML::LibXML::Number", 0)));
8271 24 50         XPUSHs(sv_2mortal(newSVnv(found->floatval)));
8272 24           break;
8273             case XPATH_STRING:
8274             /* access ->stringval */
8275             /* return as a Literal */
8276 11 50         XPUSHs(sv_2mortal(newSVpv("XML::LibXML::Literal", 0)));
8277 11 50         XPUSHs(sv_2mortal(C2Sv(found->stringval, NULL)));
8278 11           break;
8279             default:
8280 0           croak("Unknown XPath return type");
8281             }
8282 59           xmlXPathFreeObject(found);
8283             }
8284             else {
8285 8           REPORT_ERROR(0);
8286             }
8287              
8288             MODULE = XML::LibXML PACKAGE = XML::LibXML::InputCallback
8289              
8290             void
8291             lib_cleanup_callbacks( self )
8292             CODE:
8293 677           xmlCleanupInputCallbacks();
8294 677           xmlRegisterDefaultInputCallbacks();
8295              
8296             void
8297             lib_init_callbacks( self )
8298             CODE:
8299 677           xmlRegisterDefaultInputCallbacks(); /* important */
8300 677           xmlRegisterInputCallbacks((xmlInputMatchCallback) LibXML_input_match,
8301             (xmlInputOpenCallback) LibXML_input_open,
8302             (xmlInputReadCallback) LibXML_input_read,
8303             (xmlInputCloseCallback) LibXML_input_close);
8304              
8305             #ifdef HAVE_READER_SUPPORT
8306              
8307             MODULE = XML::LibXML PACKAGE = XML::LibXML::Reader
8308              
8309             xmlTextReaderPtr
8310             _newForFile(CLASS, filename, encoding, options)
8311             const char* CLASS
8312             const char* filename
8313             const char * encoding = SvOK($arg) ? SvPV_nolen($arg) : NULL;
8314             int options = SvOK($arg) ? SvIV($arg) : 0;
8315             CODE:
8316 9           RETVAL = xmlReaderForFile(filename, encoding, options);
8317             INIT_READER_ERROR_HANDLER(RETVAL);
8318             OUTPUT:
8319             RETVAL
8320              
8321             xmlTextReaderPtr
8322             _newForIO(CLASS, fh, url, encoding, options)
8323             const char* CLASS
8324             SV * fh
8325             const char * url = SvOK($arg) ? SvPV_nolen($arg) : NULL;
8326             const char * encoding = SvOK($arg) ? SvPV_nolen($arg) : NULL;
8327             int options = SvOK($arg) ? SvIV($arg) : 0;
8328             CODE:
8329 1           (void)SvREFCNT_inc(fh); /* _dec'd by LibXML_close_perl */
8330 1           RETVAL = xmlReaderForIO((xmlInputReadCallback) LibXML_read_perl,
8331             (xmlInputCloseCallback) LibXML_close_perl,
8332             (void *) fh, url, encoding, options);
8333             INIT_READER_ERROR_HANDLER(RETVAL)
8334             OUTPUT:
8335             RETVAL
8336              
8337             xmlTextReaderPtr
8338             _newForString(CLASS, string, url, encoding, options)
8339             const char* CLASS
8340             SV * string
8341             const char * url = SvOK($arg) ? SvPV_nolen($arg) : NULL;
8342             const char * encoding = SvOK($arg) ? SvPV_nolen($arg) : NULL;
8343             int options = SvOK($arg) ? SvIV($arg) : 0;
8344             CODE:
8345 8 50         if (encoding == NULL && SvUTF8( string )) {
    100          
8346 2           encoding = "UTF-8";
8347             }
8348 8 50         RETVAL = xmlReaderForDoc((xmlChar* )SvPV_nolen(string), url, encoding, options);
8349             INIT_READER_ERROR_HANDLER(RETVAL)
8350             OUTPUT:
8351             RETVAL
8352              
8353             xmlTextReaderPtr
8354             _newForFd(CLASS, fd, url, encoding, options)
8355             const char* CLASS
8356             int fd
8357             const char * url = SvOK($arg) ? SvPV_nolen($arg) : NULL;
8358             const char * encoding = SvOK($arg) ? SvPV_nolen($arg) : NULL;
8359             int options = SvOK($arg) ? SvIV($arg) : 0;
8360             CODE:
8361 1           RETVAL = xmlReaderForFd(fd, url, encoding, options);
8362             INIT_READER_ERROR_HANDLER(RETVAL)
8363             OUTPUT:
8364             RETVAL
8365              
8366             xmlTextReaderPtr
8367             _newForDOM(CLASS, perl_doc)
8368             const char* CLASS
8369             SV * perl_doc
8370             CODE:
8371 1 50         PmmREFCNT_inc(SvPROXYNODE(perl_doc)); /* _dec in DESTROY */
8372 1           RETVAL = xmlReaderWalker((xmlDocPtr) PmmSvNode(perl_doc));
8373             OUTPUT:
8374             RETVAL
8375              
8376             int
8377             attributeCount(reader)
8378             xmlTextReaderPtr reader
8379             CODE:
8380 1           RETVAL = xmlTextReaderAttributeCount(reader);
8381             OUTPUT:
8382             RETVAL
8383              
8384             SV *
8385             baseURI(reader)
8386             xmlTextReaderPtr reader
8387             PREINIT:
8388 1           const xmlChar *result = NULL;
8389             CODE:
8390 1           result = xmlTextReaderConstBaseUri(reader);
8391 1           RETVAL = C2Sv(result, NULL);
8392             OUTPUT:
8393             RETVAL
8394              
8395             long
8396             byteConsumed(reader)
8397             xmlTextReaderPtr reader
8398             CODE:
8399 1           RETVAL = xmlTextReaderByteConsumed(reader);
8400             OUTPUT:
8401             RETVAL
8402              
8403             int
8404             _close(reader)
8405             xmlTextReaderPtr reader
8406             CODE:
8407 1           RETVAL = xmlTextReaderClose(reader);
8408             OUTPUT:
8409             RETVAL
8410              
8411             SV *
8412             encoding(reader)
8413             xmlTextReaderPtr reader
8414             PREINIT:
8415 1           const xmlChar *result = NULL;
8416             CODE:
8417 1           result = xmlTextReaderConstEncoding(reader);
8418 1           RETVAL = C2Sv(result, NULL);
8419             OUTPUT:
8420             RETVAL
8421              
8422             SV *
8423             localName(reader)
8424             xmlTextReaderPtr reader
8425             PREINIT:
8426 2           const xmlChar *result = NULL;
8427             CODE:
8428 2           result = xmlTextReaderConstLocalName(reader);
8429 2           RETVAL = C2Sv(result, NULL);
8430             OUTPUT:
8431             RETVAL
8432              
8433             SV *
8434             name(reader)
8435             xmlTextReaderPtr reader
8436             PREINIT:
8437 46           const xmlChar *result = NULL;
8438             CODE:
8439 46           result = xmlTextReaderConstName(reader);
8440 46           RETVAL = C2Sv(result, NULL);
8441             OUTPUT:
8442             RETVAL
8443              
8444             SV *
8445             namespaceURI(reader)
8446             xmlTextReaderPtr reader
8447             PREINIT:
8448 36           const xmlChar *result = NULL;
8449             CODE:
8450 36           result = xmlTextReaderConstNamespaceUri(reader);
8451 36           RETVAL = C2Sv(result, NULL);
8452             OUTPUT:
8453             RETVAL
8454              
8455             SV *
8456             prefix(reader)
8457             xmlTextReaderPtr reader
8458             PREINIT:
8459 2           const xmlChar *result = NULL;
8460             CODE:
8461 2           result = xmlTextReaderConstPrefix(reader);
8462 2           RETVAL = C2Sv(result, NULL);
8463             OUTPUT:
8464             RETVAL
8465              
8466             SV *
8467             value(reader)
8468             xmlTextReaderPtr reader
8469             PREINIT:
8470 29           const xmlChar *result = NULL;
8471             CODE:
8472 29           result = xmlTextReaderConstValue(reader);
8473 29           RETVAL = C2Sv(result, NULL);
8474             OUTPUT:
8475             RETVAL
8476              
8477             SV *
8478             xmlLang(reader)
8479             xmlTextReaderPtr reader
8480             PREINIT:
8481 2           const xmlChar *result = NULL;
8482             CODE:
8483 2           result = xmlTextReaderConstXmlLang(reader);
8484 2           RETVAL = C2Sv(result, NULL);
8485             OUTPUT:
8486             RETVAL
8487              
8488              
8489             SV *
8490             xmlVersion(reader)
8491             xmlTextReaderPtr reader
8492             PREINIT:
8493 1           const xmlChar *result = NULL;
8494             CODE:
8495 1           result = xmlTextReaderConstXmlVersion(reader);
8496 1           RETVAL = C2Sv(result, NULL);
8497             OUTPUT:
8498             RETVAL
8499              
8500              
8501             int
8502             depth(reader)
8503             xmlTextReaderPtr reader
8504             CODE:
8505 1           RETVAL = xmlTextReaderDepth(reader);
8506             OUTPUT:
8507             RETVAL
8508              
8509              
8510             SV *
8511             getAttribute(reader, name)
8512             xmlTextReaderPtr reader
8513             char * name
8514             PREINIT:
8515 1           xmlChar *result = NULL;
8516             CODE:
8517 1           result = xmlTextReaderGetAttribute(reader, (xmlChar*) name);
8518 1           RETVAL = C2Sv(result, NULL);
8519 1           xmlFree(result);
8520             OUTPUT:
8521             RETVAL
8522              
8523             SV *
8524             getAttributeNo(reader, no)
8525             xmlTextReaderPtr reader
8526             int no
8527             PREINIT:
8528 1           xmlChar *result = NULL;
8529             CODE:
8530 1           result = xmlTextReaderGetAttributeNo(reader, no);
8531 1           RETVAL = C2Sv(result, NULL);
8532 1           xmlFree(result);
8533             OUTPUT:
8534             RETVAL
8535              
8536             SV *
8537             getAttributeNs(reader, localName, namespaceURI)
8538             xmlTextReaderPtr reader
8539             char * localName
8540             char * namespaceURI = SvOK($arg) ? SvPV_nolen($arg) : NULL;
8541             PREINIT:
8542 1           xmlChar *result = NULL;
8543             CODE:
8544 1           result = xmlTextReaderGetAttributeNs(reader, (xmlChar*) localName,
8545             (xmlChar*) namespaceURI);
8546 1           RETVAL = C2Sv(result, NULL);
8547 1           xmlFree(result);
8548             OUTPUT:
8549             RETVAL
8550              
8551             int
8552             columnNumber(reader)
8553             xmlTextReaderPtr reader
8554             CODE:
8555 1           RETVAL = xmlTextReaderGetParserColumnNumber(reader);
8556             OUTPUT:
8557             RETVAL
8558              
8559             int
8560             lineNumber(reader)
8561             xmlTextReaderPtr reader
8562             CODE:
8563 1           RETVAL = xmlTextReaderGetParserLineNumber(reader);
8564             OUTPUT:
8565             RETVAL
8566              
8567             int
8568             _getParserProp(reader, prop)
8569             xmlTextReaderPtr reader
8570             int prop
8571             CODE:
8572 1           RETVAL = xmlTextReaderGetParserProp(reader, prop);
8573             OUTPUT:
8574             RETVAL
8575              
8576             int
8577             hasAttributes(reader)
8578             xmlTextReaderPtr reader
8579             CODE:
8580 1           RETVAL = xmlTextReaderHasAttributes(reader);
8581             OUTPUT:
8582             RETVAL
8583              
8584             int
8585             hasValue(reader)
8586             xmlTextReaderPtr reader
8587             CODE:
8588 1           RETVAL = xmlTextReaderHasValue(reader);
8589             OUTPUT:
8590             RETVAL
8591              
8592             SV*
8593             getAttributeHash(reader)
8594             xmlTextReaderPtr reader
8595             PREINIT:
8596             HV* hv;
8597             SV* sv;
8598             const xmlChar* name;
8599 0           PREINIT_SAVED_ERROR
8600             CODE:
8601 0           INIT_ERROR_HANDLER;
8602 0           hv=newHV();
8603 0 0         if (xmlTextReaderHasAttributes(reader) && xmlTextReaderMoveToFirstAttribute(reader)==1) {
    0          
8604             do {
8605 0           name = xmlTextReaderConstName(reader);
8606 0           sv=C2Sv((xmlTextReaderConstValue(reader)),NULL);
8607 0 0         if (sv && hv_store(hv, (const char*) name, xmlStrlen(name), sv, 0)==NULL) {
    0          
8608 0           SvREFCNT_dec(sv); /* free if not needed by hv_stores */
8609             }
8610 0 0         } while (xmlTextReaderMoveToNextAttribute(reader)==1);
8611 0           xmlTextReaderMoveToElement(reader);
8612             }
8613 0           RETVAL=newRV_noinc((SV*)hv);
8614 0           CLEANUP_ERROR_HANDLER;
8615 0           REPORT_ERROR(0);
8616             OUTPUT:
8617             RETVAL
8618              
8619             int
8620             isDefault(reader)
8621             xmlTextReaderPtr reader
8622             CODE:
8623 1           RETVAL = xmlTextReaderIsDefault(reader);
8624             OUTPUT:
8625             RETVAL
8626              
8627             int
8628             isEmptyElement(reader)
8629             xmlTextReaderPtr reader
8630             CODE:
8631 1           RETVAL = xmlTextReaderIsEmptyElement(reader);
8632             OUTPUT:
8633             RETVAL
8634              
8635             int
8636             isNamespaceDecl(reader)
8637             xmlTextReaderPtr reader
8638             CODE:
8639 1           RETVAL = xmlTextReaderIsNamespaceDecl(reader);
8640             OUTPUT:
8641             RETVAL
8642              
8643             int
8644             isValid(reader)
8645             xmlTextReaderPtr reader
8646             CODE:
8647 1           RETVAL = xmlTextReaderIsValid(reader);
8648             OUTPUT:
8649             RETVAL
8650              
8651             SV *
8652             lookupNamespace(reader, prefix)
8653             xmlTextReaderPtr reader
8654             char * prefix = SvOK($arg) ? SvPV_nolen($arg) : NULL;
8655             PREINIT:
8656 1           xmlChar *result = NULL;
8657             CODE:
8658 1           result = xmlTextReaderLookupNamespace(reader, (xmlChar*) prefix);
8659 1           RETVAL = C2Sv(result, NULL);
8660 1           xmlFree(result);
8661             OUTPUT:
8662             RETVAL
8663              
8664              
8665             int
8666             moveToAttribute(reader, name)
8667             xmlTextReaderPtr reader
8668             char * name
8669             CODE:
8670 1           RETVAL = xmlTextReaderMoveToAttribute(reader, (xmlChar*) name);
8671             OUTPUT:
8672             RETVAL
8673              
8674             int
8675             moveToAttributeNo(reader, no)
8676             xmlTextReaderPtr reader
8677             int no
8678             CODE:
8679 1           RETVAL = xmlTextReaderMoveToAttributeNo(reader, no);
8680             OUTPUT:
8681             RETVAL
8682              
8683             int
8684             moveToAttributeNs(reader, localName, namespaceURI)
8685             xmlTextReaderPtr reader
8686             char * localName
8687             char * namespaceURI = SvOK($arg) ? SvPV_nolen($arg) : NULL;
8688             CODE:
8689 1           RETVAL = xmlTextReaderMoveToAttributeNs(reader,
8690             (xmlChar*) localName, (xmlChar*) namespaceURI);
8691             OUTPUT:
8692             RETVAL
8693              
8694             int
8695             moveToElement(reader)
8696             xmlTextReaderPtr reader
8697             CODE:
8698 2           RETVAL = xmlTextReaderMoveToElement(reader);
8699             OUTPUT:
8700             RETVAL
8701              
8702             int
8703             moveToFirstAttribute(reader)
8704             xmlTextReaderPtr reader
8705             CODE:
8706 1           RETVAL = xmlTextReaderMoveToFirstAttribute(reader);
8707             OUTPUT:
8708             RETVAL
8709              
8710             int
8711             moveToNextAttribute(reader)
8712             xmlTextReaderPtr reader
8713             CODE:
8714 1           RETVAL = xmlTextReaderMoveToNextAttribute(reader);
8715             OUTPUT:
8716             RETVAL
8717              
8718             int
8719             next(reader)
8720             xmlTextReaderPtr reader
8721             PREINIT:
8722 1           PREINIT_SAVED_ERROR
8723             CODE:
8724 1           INIT_ERROR_HANDLER;
8725 1           RETVAL = xmlTextReaderNext(reader);
8726 1           CLEANUP_ERROR_HANDLER;
8727 1           REPORT_ERROR(0);
8728             OUTPUT:
8729             RETVAL
8730              
8731             #define LIBXML_READER_NEXT_SIBLING(ret,reader) \
8732             ret = xmlTextReaderNextSibling(reader); \
8733             if (ret == -1) \
8734             { \
8735             int depth; \
8736             depth = xmlTextReaderDepth(reader); \
8737             ret = xmlTextReaderRead(reader); \
8738             while (ret == 1 && xmlTextReaderDepth(reader) > depth) { \
8739             ret = xmlTextReaderNext(reader); \
8740             } \
8741             if (ret == 1) { \
8742             if (xmlTextReaderDepth(reader) != depth) { \
8743             ret = 0; \
8744             } else if (xmlTextReaderNodeType(reader) == XML_READER_TYPE_END_ELEMENT) { \
8745             ret = xmlTextReaderRead(reader); \
8746             } \
8747             } \
8748             }
8749              
8750             int
8751             nextSibling(reader)
8752             xmlTextReaderPtr reader
8753             PREINIT:
8754 2           PREINIT_SAVED_ERROR
8755             CODE:
8756 2           INIT_ERROR_HANDLER;
8757 10 50         LIBXML_READER_NEXT_SIBLING(RETVAL,reader)
    50          
    100          
    50          
    50          
    50          
8758 2           CLEANUP_ERROR_HANDLER;
8759 2           REPORT_ERROR(0);
8760             OUTPUT:
8761             RETVAL
8762              
8763             int
8764             nextSiblingElement(reader, name = NULL, nsURI = NULL)
8765             xmlTextReaderPtr reader
8766             const char * name
8767             const char * nsURI
8768             PREINIT:
8769 1           PREINIT_SAVED_ERROR
8770             CODE:
8771 1           INIT_ERROR_HANDLER;
8772             do {
8773 10 50         LIBXML_READER_NEXT_SIBLING(RETVAL,reader)
    50          
    100          
    50          
    50          
    100          
8774 6 100         if (LIBXML_READER_TEST_ELEMENT(reader,name,nsURI)) {
    50          
    0          
    50          
    0          
    50          
    100          
    50          
    50          
8775             break;
8776             }
8777 5 50         } while (RETVAL == 1);
8778 1           CLEANUP_ERROR_HANDLER;
8779 1           REPORT_ERROR(0);
8780             OUTPUT:
8781             RETVAL
8782              
8783             int
8784             nextElement(reader, name = NULL, nsURI = NULL)
8785             xmlTextReaderPtr reader
8786             const char * name
8787             const char * nsURI
8788             PREINIT:
8789 6           PREINIT_SAVED_ERROR
8790             CODE:
8791 6           INIT_ERROR_HANDLER;
8792             do {
8793 10           RETVAL = xmlTextReaderRead(reader);
8794 10 100         if (LIBXML_READER_TEST_ELEMENT(reader,name,nsURI)) {
    50          
    100          
    50          
    50          
    0          
    0          
    0          
    0          
8795             break;
8796             }
8797 4 50         } while (RETVAL == 1);
8798 6           CLEANUP_ERROR_HANDLER;
8799 6           REPORT_ERROR(0);
8800             OUTPUT:
8801             RETVAL
8802              
8803             int
8804             nextPatternMatch(reader, compiled)
8805             xmlTextReaderPtr reader
8806             xmlPatternPtr compiled
8807             PREINIT:
8808 5           PREINIT_SAVED_ERROR
8809 5           xmlNodePtr node = NULL;
8810             CODE:
8811 5 50         if ( compiled == NULL )
8812 0           croak("Usage: $reader->nextPatternMatch( a-XML::LibXML::Pattern-object )");
8813             do {
8814 42           RETVAL = xmlTextReaderRead(reader);
8815 42           node = xmlTextReaderCurrentNode(reader);
8816 42 100         if (node && xmlPatternMatch(compiled, node)) {
    100          
8817 4           break;
8818             }
8819 38 100         } while (RETVAL == 1);
8820 5           CLEANUP_ERROR_HANDLER;
8821 5           REPORT_ERROR(0);
8822             OUTPUT:
8823             RETVAL
8824              
8825             int
8826             skipSiblings(reader)
8827             xmlTextReaderPtr reader
8828             PREINIT:
8829             int depth;
8830             PREINIT:
8831 1           PREINIT_SAVED_ERROR
8832             CODE:
8833 1           INIT_ERROR_HANDLER;
8834 1           depth = xmlTextReaderDepth(reader);
8835 1           RETVAL = -1;
8836 1 50         if (depth > 0) {
8837             do {
8838 3           RETVAL = xmlTextReaderNext(reader);
8839 3 50         } while (RETVAL == 1 && xmlTextReaderDepth(reader) >= depth);
    100          
8840 1 50         if (xmlTextReaderNodeType(reader) != XML_READER_TYPE_END_ELEMENT) {
8841 0           RETVAL = -1;
8842             }
8843             }
8844 1           CLEANUP_ERROR_HANDLER;
8845 1           REPORT_ERROR(0);
8846             OUTPUT:
8847             RETVAL
8848              
8849             int
8850             nodeType(reader)
8851             xmlTextReaderPtr reader
8852             CODE:
8853 179           RETVAL = xmlTextReaderNodeType(reader);
8854             OUTPUT:
8855             RETVAL
8856              
8857             SV*
8858             quoteChar(reader)
8859             xmlTextReaderPtr reader
8860             PREINIT:
8861             int ret;
8862             CODE:
8863 0           ret = xmlTextReaderQuoteChar(reader);
8864 0 0         if (ret == -1) XSRETURN_UNDEF;
8865 0           RETVAL = newSVpvf("%c",ret);
8866             OUTPUT:
8867             RETVAL
8868              
8869             int
8870             read(reader)
8871             xmlTextReaderPtr reader
8872             PREINIT:
8873 199           PREINIT_SAVED_ERROR
8874             CODE:
8875 199           INIT_ERROR_HANDLER;
8876 199           RETVAL = xmlTextReaderRead(reader);
8877 199           CLEANUP_ERROR_HANDLER;
8878 199           REPORT_ERROR(0);
8879             OUTPUT:
8880             RETVAL
8881              
8882             int
8883             readAttributeValue(reader)
8884             xmlTextReaderPtr reader
8885             PREINIT:
8886 1           PREINIT_SAVED_ERROR
8887             CODE:
8888 1           INIT_ERROR_HANDLER;
8889 1           RETVAL = xmlTextReaderReadAttributeValue(reader);
8890 1           CLEANUP_ERROR_HANDLER;
8891 1           REPORT_ERROR(0);
8892             OUTPUT:
8893             RETVAL
8894              
8895              
8896             SV *
8897             readInnerXml(reader)
8898             xmlTextReaderPtr reader
8899             PREINIT:
8900 1           xmlChar *result = NULL;
8901             PREINIT:
8902 1           PREINIT_SAVED_ERROR
8903             CODE:
8904 1           INIT_ERROR_HANDLER;
8905 1           result = xmlTextReaderReadInnerXml(reader);
8906 1           CLEANUP_ERROR_HANDLER;
8907 1           REPORT_ERROR(0);
8908 1 50         if (!result) XSRETURN_UNDEF;
8909 1           RETVAL = C2Sv(result, NULL);
8910 1           xmlFree(result);
8911             OUTPUT:
8912             RETVAL
8913              
8914             SV *
8915             readOuterXml(reader)
8916             xmlTextReaderPtr reader
8917             PREINIT:
8918 3           xmlChar *result = NULL;
8919             PREINIT:
8920 3           PREINIT_SAVED_ERROR
8921             CODE:
8922 3           INIT_ERROR_HANDLER;
8923 3           result = xmlTextReaderReadOuterXml(reader);
8924 3           CLEANUP_ERROR_HANDLER;
8925 3           REPORT_ERROR(0);
8926 3 50         if (result) {
8927 3           RETVAL = C2Sv(result, NULL);
8928 3           xmlFree(result);
8929             } else {
8930 0           XSRETURN_UNDEF;
8931             }
8932             OUTPUT:
8933             RETVAL
8934              
8935             int
8936             readState(reader)
8937             xmlTextReaderPtr reader
8938             CODE:
8939 1           RETVAL = xmlTextReaderReadState(reader);
8940             OUTPUT:
8941             RETVAL
8942              
8943             int
8944             _setParserProp(reader, prop, value)
8945             xmlTextReaderPtr reader
8946             int prop
8947             int value
8948             CODE:
8949 0           RETVAL = xmlTextReaderSetParserProp(reader, prop, value);
8950             OUTPUT:
8951             RETVAL
8952              
8953             int
8954             standalone(reader)
8955             xmlTextReaderPtr reader
8956             CODE:
8957 1           RETVAL = xmlTextReaderStandalone(reader);
8958             OUTPUT:
8959             RETVAL
8960              
8961             SV *
8962             _nodePath(reader)
8963             xmlTextReaderPtr reader
8964             PREINIT:
8965 8           xmlNodePtr node = NULL;
8966 8           xmlChar * path = NULL;
8967             CODE:
8968 8           node = xmlTextReaderCurrentNode(reader);
8969 8 50         if ( node ==NULL ) {
8970 0           XSRETURN_UNDEF;
8971             }
8972 8           path = xmlGetNodePath( node );
8973 8 50         if ( path == NULL ) {
8974 0           XSRETURN_UNDEF;
8975             }
8976 8           RETVAL = C2Sv(path,NULL);
8977 8           xmlFree(path);
8978             OUTPUT:
8979             RETVAL
8980              
8981             #ifdef LIBXML_PATTERN_ENABLED
8982              
8983             int
8984             matchesPattern(reader, compiled)
8985             xmlTextReaderPtr reader
8986             xmlPatternPtr compiled
8987             PREINIT:
8988 41           xmlNodePtr node = NULL;
8989             CODE:
8990 41 50         if ( compiled == NULL )
8991 0           XSRETURN_UNDEF;
8992 41           node = xmlTextReaderCurrentNode(reader);
8993 41 50         if ( node ==NULL ) {
8994 0           XSRETURN_UNDEF;
8995             }
8996 41           RETVAL = xmlPatternMatch(compiled, node);
8997             OUTPUT:
8998             RETVAL
8999              
9000             #endif /* LIBXML_PATTERN_ENABLED */
9001              
9002             SV *
9003             copyCurrentNode(reader,expand = 0)
9004             xmlTextReaderPtr reader
9005             int expand
9006             PREINIT:
9007 2           xmlNodePtr node = NULL;
9008             xmlNodePtr copy;
9009 2           xmlDocPtr doc = NULL;
9010             ProxyNodePtr proxy;
9011             PREINIT:
9012 2           PREINIT_SAVED_ERROR
9013             CODE:
9014 2           INIT_ERROR_HANDLER;
9015 2 100         if (expand) {
9016 1           node = xmlTextReaderExpand(reader);
9017             }
9018             else {
9019 1           node = xmlTextReaderCurrentNode(reader);
9020             }
9021 2 50         if (node) {
9022 2           doc = xmlTextReaderCurrentDoc(reader);
9023             }
9024 2 50         if (!doc) {
9025 0           CLEANUP_ERROR_HANDLER;
9026 0           REPORT_ERROR(0);
9027 0           XSRETURN_UNDEF;
9028             }
9029 2 50         if (xmlTextReaderGetParserProp(reader,XML_PARSER_VALIDATE))
9030 0 0         PmmInvalidatePSVI(doc); /* the document may have psvi info */
    0          
9031              
9032 2           copy = PmmCloneNode( node, expand );
9033 2 50         if ( copy == NULL ) {
9034 0           CLEANUP_ERROR_HANDLER;
9035 0           REPORT_ERROR(0);
9036 0           XSRETURN_UNDEF;
9037             }
9038 2 50         if ( copy->type == XML_DTD_NODE ) {
9039 0           RETVAL = PmmNodeToSv(copy, NULL);
9040             }
9041             else {
9042 2           ProxyNodePtr docfrag = NULL;
9043              
9044 2 50         if ( doc != NULL ) {
9045 2           xmlSetTreeDoc(copy, doc);
9046             }
9047 2           proxy = PmmNewNode((xmlNodePtr)doc);
9048 2 100         if (PmmREFCNT(proxy) == 0) {
9049 1           PmmREFCNT_inc(proxy);
9050             }
9051 2           LibXML_set_reader_preserve_flag(reader);
9052              
9053 2           docfrag = PmmNewFragment( doc );
9054 2           xmlAddChild( PmmNODE(docfrag), copy );
9055 2           RETVAL = PmmNodeToSv(copy, docfrag);
9056             }
9057 2           CLEANUP_ERROR_HANDLER;
9058 2           REPORT_ERROR(0);
9059             OUTPUT:
9060             RETVAL
9061              
9062             SV *
9063             document(reader)
9064             xmlTextReaderPtr reader
9065             PREINIT:
9066 3           xmlDocPtr doc = NULL;
9067             CODE:
9068 3           doc = xmlTextReaderCurrentDoc(reader);
9069 3 50         if (!doc) XSRETURN_UNDEF;
9070 3           RETVAL = PmmNodeToSv((xmlNodePtr)doc, NULL);
9071             /* FIXME: taint the document with PmmInvalidatePSVI if the reader did validation */
9072 3 50         if ( PmmREFCNT(SvPROXYNODE(RETVAL))==1 ) {
    50          
9073             /* will be decremented in Reader destructor */
9074 0 0         PmmREFCNT_inc(SvPROXYNODE(RETVAL));
9075             }
9076 3 100         if (xmlTextReaderGetParserProp(reader,XML_PARSER_VALIDATE))
9077 2 50         PmmInvalidatePSVI(doc); /* the document may have psvi info */
    50          
9078              
9079 3           LibXML_set_reader_preserve_flag(reader);
9080              
9081             OUTPUT:
9082             RETVAL
9083              
9084             int
9085             _preservePattern(reader,pattern,ns_map=NULL)
9086             xmlTextReaderPtr reader
9087             char * pattern
9088             AV * ns_map
9089             PREINIT:
9090 2           xmlChar** namespaces = NULL;
9091             SV** aux;
9092             int last,i;
9093             CODE:
9094 2 100         if (ns_map) {
9095 1           last = av_len(ns_map);
9096 1 50         New(0,namespaces, last+2, xmlChar*);
9097 3 100         for( i = 0; i <= last ; i++ ) {
9098 2           aux = av_fetch(ns_map,i,0);
9099 2 50         namespaces[i]=(xmlChar*) SvPV_nolen(*aux);
9100             }
9101 1           namespaces[i]=0;
9102             }
9103 2           RETVAL = xmlTextReaderPreservePattern(reader,(const xmlChar*) pattern,
9104             (const xmlChar**)namespaces);
9105 2           Safefree(namespaces);
9106             OUTPUT:
9107             RETVAL
9108              
9109             SV *
9110             preserveNode(reader)
9111             xmlTextReaderPtr reader
9112             PREINIT:
9113             xmlNodePtr node;
9114             xmlDocPtr doc;
9115             ProxyNodePtr proxy;
9116 1           PREINIT_SAVED_ERROR
9117             CODE:
9118 1           INIT_ERROR_HANDLER;
9119 1           doc = xmlTextReaderCurrentDoc(reader);
9120 1 50         if (!doc) {
9121 0           CLEANUP_ERROR_HANDLER;
9122 0           REPORT_ERROR(0);
9123 0           XSRETURN_UNDEF;
9124             }
9125 1           proxy = PmmNewNode((xmlNodePtr)doc);
9126 1 50         if ( PmmREFCNT(proxy) == 0 ) {
9127             /* new proxy node */
9128 0           PmmREFCNT_inc(proxy);
9129             }
9130 1           LibXML_set_reader_preserve_flag(reader);
9131              
9132 1           node = xmlTextReaderPreserve(reader);
9133 1           CLEANUP_ERROR_HANDLER;
9134 1           REPORT_ERROR(0);
9135 1 50         if (node) {
9136 1           RETVAL = PmmNodeToSv(node, proxy);
9137             } else {
9138 0           XSRETURN_UNDEF;
9139             }
9140             OUTPUT:
9141             RETVAL
9142              
9143             int
9144             finish(reader)
9145             xmlTextReaderPtr reader
9146             PREINIT:
9147 10           PREINIT_SAVED_ERROR
9148             CODE:
9149 10           INIT_ERROR_HANDLER;
9150             while (1) {
9151 102           RETVAL = xmlTextReaderRead(reader);
9152 102 100         if (RETVAL!=1) break;
9153 92           }
9154 10           CLEANUP_ERROR_HANDLER;
9155 10           REPORT_ERROR(0);
9156 5           RETVAL++; /* we want 0 - fail, 1- success */
9157             OUTPUT:
9158             RETVAL
9159              
9160             #ifdef HAVE_SCHEMAS
9161              
9162             int
9163             _setRelaxNGFile(reader,rng)
9164             xmlTextReaderPtr reader
9165             char* rng
9166             CODE:
9167 2           RETVAL = xmlTextReaderRelaxNGValidate(reader,rng);
9168             OUTPUT:
9169             RETVAL
9170              
9171             int
9172             _setRelaxNG(reader,rng_doc)
9173             xmlTextReaderPtr reader
9174             xmlRelaxNGPtr rng_doc
9175             CODE:
9176 2           RETVAL = xmlTextReaderRelaxNGSetSchema(reader,rng_doc);
9177             OUTPUT:
9178             RETVAL
9179              
9180             int
9181             _setXSDFile(reader,xsd)
9182             xmlTextReaderPtr reader
9183             char* xsd
9184             CODE:
9185 2           RETVAL = xmlTextReaderSchemaValidate(reader,xsd);
9186             OUTPUT:
9187             RETVAL
9188              
9189             int
9190             _setXSD(reader,xsd_doc)
9191             xmlTextReaderPtr reader
9192             xmlSchemaPtr xsd_doc
9193             CODE:
9194 2           RETVAL = xmlTextReaderSetSchema(reader,xsd_doc);
9195             OUTPUT:
9196             RETVAL
9197              
9198             #endif /* HAVE_SCHEMAS */
9199              
9200             void
9201             _DESTROY(reader)
9202             xmlTextReaderPtr reader
9203             PREINIT:
9204             xmlDocPtr doc;
9205             ProxyNodePtr proxy;
9206             /* SV * error_sv = NULL;
9207             xmlTextReaderErrorFunc f = NULL; */
9208             CODE:
9209              
9210 20 100         if ( LibXML_get_reader_preserve_flag(reader) ) {
9211 2           doc = xmlTextReaderCurrentDoc(reader);
9212 2 50         if (doc) {
9213 2           proxy = PmmNewNode((xmlNodePtr)doc);
9214 2 50         if ( PmmREFCNT(proxy) == 0 ) {
9215 0           PmmREFCNT_inc(proxy);
9216             }
9217 2           PmmREFCNT_dec(proxy);
9218             }
9219             }
9220 20 100         if (xmlTextReaderReadState(reader) != XML_TEXTREADER_MODE_CLOSED) {
9221 19           xmlTextReaderClose(reader);
9222             }
9223             /* xmlTextReaderGetErrorHandler(reader, &f, (void **) &error_sv);
9224             if (error_sv) {
9225             sv_2mortal(error_sv);
9226             } */
9227 20           xmlFreeTextReader(reader);
9228              
9229             #endif /* HAVE_READER_SUPPORT */
9230              
9231             #ifdef WITH_SERRORS
9232              
9233             MODULE = XML::LibXML PACKAGE = XML::LibXML::LibError
9234              
9235             int
9236             domain( self )
9237             xmlErrorPtr self
9238             CODE:
9239 2578           RETVAL = self->domain;
9240             OUTPUT:
9241             RETVAL
9242              
9243             int
9244             code( self )
9245             xmlErrorPtr self
9246             CODE:
9247 2578           RETVAL = self->code;
9248             OUTPUT:
9249             RETVAL
9250              
9251             int
9252             line( self )
9253             xmlErrorPtr self
9254             CODE:
9255 2578           RETVAL = self->line;
9256             OUTPUT:
9257             RETVAL
9258              
9259             int
9260             num1( self )
9261             xmlErrorPtr self
9262             ALIAS:
9263             int1 = 1
9264             CODE:
9265             PERL_UNUSED_VAR(ix);
9266 2578           RETVAL = self->int1;
9267             OUTPUT:
9268             RETVAL
9269              
9270             int
9271             num2( self )
9272             xmlErrorPtr self
9273             ALIAS:
9274             int2 = 1
9275             CODE:
9276             PERL_UNUSED_VAR(ix);
9277 2578           RETVAL = self->int2;
9278             OUTPUT:
9279             RETVAL
9280              
9281             int
9282             level( self )
9283             xmlErrorPtr self
9284             CODE:
9285 2578           RETVAL = (int)self->level;
9286             OUTPUT:
9287             RETVAL
9288              
9289             char *
9290             message( self )
9291             xmlErrorPtr self
9292             CODE:
9293 2578           RETVAL = self->message;
9294             OUTPUT:
9295             RETVAL
9296              
9297             char *
9298             file( self )
9299             xmlErrorPtr self
9300             CODE:
9301 2578           RETVAL = (char*)self->file;
9302             OUTPUT:
9303             RETVAL
9304              
9305             char *
9306             str1( self )
9307             xmlErrorPtr self
9308             CODE:
9309 2578           RETVAL = (char*)self->str1;
9310             OUTPUT:
9311             RETVAL
9312              
9313             char *
9314             str2( self )
9315             xmlErrorPtr self
9316             CODE:
9317 2578           RETVAL = (char*)self->str2;
9318             OUTPUT:
9319             RETVAL
9320              
9321             char *
9322             str3( self )
9323             xmlErrorPtr self
9324             CODE:
9325 2578           RETVAL = (char*)self->str3;
9326             OUTPUT:
9327             RETVAL
9328              
9329             void
9330             context_and_column( self )
9331             xmlErrorPtr self
9332             PREINIT:
9333             xmlParserInputPtr input;
9334             const xmlChar *cur, *base, *col_cur;
9335             unsigned int n, col; /* GCC warns if signed, because compared with sizeof() */
9336             xmlChar content[81]; /* space for 80 chars + line terminator */
9337             xmlChar *ctnt;
9338             int domain;
9339 2578           xmlParserCtxtPtr ctxt = NULL;
9340             PPCODE:
9341 2578           domain = self->domain;
9342 2578 100         if ((domain == XML_FROM_PARSER) || (domain == XML_FROM_HTML) ||
    100          
    100          
9343 82 100         (domain == XML_FROM_DTD) || (domain == XML_FROM_NAMESPACE) ||
    100          
9344 75 100         (domain == XML_FROM_IO) || (domain == XML_FROM_VALID)) {
9345 2519           ctxt = (xmlParserCtxtPtr) self->ctxt;
9346             }
9347 2578 100         if (ctxt == NULL) XSRETURN_EMPTY;
9348 2513           input = ctxt->input;
9349 2513 100         if ((input != NULL) && (input->filename == NULL) &&
    100          
    50          
9350 332           (ctxt->inputNr > 1)) {
9351 0           input = ctxt->inputTab[ctxt->inputNr - 2];
9352             }
9353 2513 100         if (input == NULL) XSRETURN_EMPTY;
9354 2511           cur = input->cur;
9355 2511           base = input->base;
9356             /* skip backwards over any end-of-lines */
9357 2530 100         while ((cur > base) && ((*(cur) == '\n') || (*(cur) == '\r'))) {
    100          
    50          
9358 19           cur--;
9359             }
9360 2511           n = 0;
9361             /* search backwards for beginning-of-line (to max buff size) */
9362 109483 100         while ((n++ < (sizeof(content)-1)) && (cur > base) &&
    100          
    100          
9363 106973 100         (*(cur) != '\n') && (*(cur) != '\r'))
9364 106972           cur--;
9365             /* search backwards for beginning-of-line for calculating the
9366             * column. */
9367 2511           col_cur = cur;
9368 1297482 100         while ((col_cur > base) && (*(col_cur) != '\n') && (*(col_cur) != '\r'))
    100          
    100          
9369 1294971           col_cur--;
9370 2511 100         if ((*(cur) == '\n') || (*(cur) == '\r')) cur++;
    100          
9371 2511 100         if ((*(col_cur) == '\n') || (*(col_cur) == '\r')) col_cur++;
    100          
9372             /* calculate the error position in terms of the current position */
9373 2511           col = input->cur - col_cur;
9374             /* search forward for end-of-line (to max buff size) */
9375 2511           n = 0;
9376 2511           ctnt = content;
9377             /* copy selected text to our buffer */
9378 187187 100         while ((*cur != 0) && (*(cur) != '\n') &&
    100          
    50          
9379 186575 100         (*(cur) != '\r') && (n < sizeof(content)-1)) {
9380 184676           *ctnt++ = *cur++;
9381 184676           n++;
9382             }
9383 2511           *ctnt = 0;
9384 2511 50         EXTEND(SP,2);
9385 2511           PUSHs(sv_2mortal(C2Sv(content, NULL)));
9386 2511           PUSHs(sv_2mortal(newSViv(col)));
9387              
9388             #endif /* WITH_SERRORS */
9389              
9390              
9391             #ifdef LIBXML_PATTERN_ENABLED
9392              
9393             MODULE = XML::LibXML PACKAGE = XML::LibXML::Pattern
9394              
9395             xmlPatternPtr
9396             _compilePattern(CLASS, ppattern, pattern_type, ns_map=NULL)
9397             SV * ppattern
9398             AV * ns_map
9399             int pattern_type
9400             PREINIT:
9401 1           xmlChar * pattern = Sv2C(ppattern, NULL);
9402 1           xmlChar** namespaces = NULL;
9403             SV** aux;
9404             int last,i;
9405 1           PREINIT_SAVED_ERROR
9406             CODE:
9407 1 50         if ( pattern == NULL )
9408 0           XSRETURN_UNDEF;
9409 1 50         if (ns_map) {
9410 1           last = av_len(ns_map);
9411 1 50         New(0,namespaces, last+2, xmlChar*);
9412 3 100         for( i = 0; i <= last ; i++ ) {
9413 2           aux = av_fetch(ns_map,i,0);
9414 2 50         namespaces[i]=(xmlChar*) SvPV_nolen(*aux);
9415             }
9416 1           namespaces[i]=0;
9417             }
9418 1           INIT_ERROR_HANDLER;
9419 1           RETVAL = xmlPatterncompile(pattern, NULL, pattern_type, (const xmlChar **) namespaces);
9420 1           Safefree(namespaces);
9421 1           xmlFree( pattern );
9422 1           CLEANUP_ERROR_HANDLER;
9423 1           REPORT_ERROR(0);
9424 1 50         if ( RETVAL == NULL ) {
9425 0           croak("Compilation of pattern failed");
9426             }
9427             OUTPUT:
9428             RETVAL
9429              
9430             int
9431             matchesNode(self, node)
9432             xmlPatternPtr self
9433             xmlNodePtr node
9434             CODE:
9435 34 50         if ( node ==NULL ) {
9436 0           XSRETURN_UNDEF;
9437             }
9438 34           RETVAL = xmlPatternMatch(self, node);
9439             OUTPUT:
9440             RETVAL
9441              
9442             void
9443             DESTROY( self )
9444             xmlPatternPtr self
9445             CODE:
9446             xs_warn( "DESTROY PATTERN OBJECT" );
9447 1           xmlFreePattern(self);
9448              
9449             #endif /* LIBXML_PATTERN_ENABLED */
9450              
9451             #ifdef LIBXML_REGEXP_ENABLED
9452              
9453             MODULE = XML::LibXML PACKAGE = XML::LibXML::RegExp
9454              
9455             xmlRegexpPtr
9456             _compile(CLASS, pregexp)
9457             SV * pregexp
9458             PREINIT:
9459 3           xmlChar * regexp = Sv2C(pregexp, NULL);
9460 3           PREINIT_SAVED_ERROR
9461             CODE:
9462 3 50         if ( regexp == NULL )
9463 0           XSRETURN_UNDEF;
9464 3           INIT_ERROR_HANDLER;
9465 3           RETVAL = xmlRegexpCompile(regexp);
9466 3           xmlFree( regexp );
9467 3           CLEANUP_ERROR_HANDLER;
9468 3           REPORT_ERROR(0);
9469 2 50         if ( RETVAL == NULL ) {
9470 0           croak("Compilation of regexp failed");
9471             }
9472             OUTPUT:
9473             RETVAL
9474              
9475             int
9476             matches(self, pvalue)
9477             xmlRegexpPtr self
9478             SV* pvalue
9479             PREINIT:
9480 8           xmlChar * value = Sv2C(pvalue, NULL);
9481             CODE:
9482 8 50         if ( value == NULL )
9483 0           XSRETURN_UNDEF;
9484 8           RETVAL = xmlRegexpExec(self,value);
9485 8           xmlFree( value );
9486             OUTPUT:
9487             RETVAL
9488              
9489             int
9490             isDeterministic(self)
9491             xmlRegexpPtr self
9492             CODE:
9493 2           RETVAL = xmlRegexpIsDeterminist(self);
9494             OUTPUT:
9495             RETVAL
9496              
9497             void
9498             DESTROY( self )
9499             xmlRegexpPtr self
9500             CODE:
9501             xs_warn( "DESTROY REGEXP OBJECT" );
9502 2           xmlRegFreeRegexp(self);
9503              
9504             #endif /* LIBXML_REGEXP_ENABLED */
9505              
9506              
9507             MODULE = XML::LibXML PACKAGE = XML::LibXML::XPathExpression
9508              
9509             xmlXPathCompExprPtr
9510             new(CLASS, pxpath)
9511             SV * pxpath
9512             PREINIT:
9513 10           xmlChar * xpath = Sv2C(pxpath, NULL);
9514 10           PREINIT_SAVED_ERROR
9515             CODE:
9516 10 50         if ( pxpath == NULL )
9517 0           XSRETURN_UNDEF;
9518 10           INIT_ERROR_HANDLER;
9519 10           RETVAL = xmlXPathCompile( xpath );
9520 10           xmlFree( xpath );
9521 10           CLEANUP_ERROR_HANDLER;
9522 10           REPORT_ERROR(0);
9523 10 50         if ( RETVAL == NULL ) {
9524 0           croak("Compilation of XPath expression failed!");
9525             }
9526             OUTPUT:
9527             RETVAL
9528              
9529             void
9530             DESTROY( self )
9531             xmlXPathCompExprPtr self
9532             CODE:
9533             xs_warn( "DESTROY COMPILED XPATH OBJECT" );
9534 10           xmlXPathFreeCompExpr(self);
9535              
9536             MODULE = XML::LibXML PACKAGE = XML::LibXML::Common
9537              
9538             PROTOTYPES: DISABLE
9539              
9540             SV*
9541             encodeToUTF8( encoding, string )
9542             const char * encoding
9543             SV * string
9544             PREINIT:
9545 17           xmlChar * realstring = NULL;
9546 17           xmlChar * tstr = NULL;
9547 17           xmlCharEncoding enc = 0;
9548 17           STRLEN len = 0;
9549 17           xmlBufferPtr in = NULL, out = NULL;
9550 17           xmlCharEncodingHandlerPtr coder = NULL;
9551 17           PREINIT_SAVED_ERROR
9552             CODE:
9553 17 100         if (!SvOK(string)) {
    50          
    50          
9554 2           XSRETURN_UNDEF;
9555 16 100         } else if (!SvCUR(string)) {
9556 1           XSRETURN_PV("");
9557             }
9558 15 50         realstring = (xmlChar*) SvPV(string, len);
9559 15 50         if ( realstring != NULL ) {
9560             /* warn("encode %s", realstring ); */
9561             #ifdef HAVE_UTF8
9562 15 50         if ( !DO_UTF8(string) && encoding != NULL ) {
    0          
    50          
9563             #else
9564             if ( encoding != NULL ) {
9565             #endif
9566 15           enc = xmlParseCharEncoding( encoding );
9567              
9568 15 50         if ( enc == 0 ) {
9569             /* this happens if the encoding is "" or NULL */
9570 0           enc = XML_CHAR_ENCODING_UTF8;
9571             }
9572              
9573 29 100         if ( enc == XML_CHAR_ENCODING_UTF8 ) {
9574             /* copy the string */
9575             /* warn( "simply copy the string" ); */
9576 4           tstr = xmlStrndup( realstring, len );
9577             }
9578             else {
9579 11           INIT_ERROR_HANDLER;
9580 11 100         if ( enc > 1 ) {
9581 10           coder= xmlGetCharEncodingHandler( enc );
9582             }
9583 1 50         else if ( enc == XML_CHAR_ENCODING_ERROR ){
9584 1           coder =xmlFindCharEncodingHandler( encoding );
9585             }
9586             else {
9587 0           croak("no encoder found\n");
9588             }
9589 11 100         if ( coder == NULL ) {
9590 1           croak( "cannot encode string" );
9591             }
9592 10           in = xmlBufferCreateStatic((void*)realstring, len );
9593 10           out = xmlBufferCreate();
9594 10 50         if ( xmlCharEncInFunc( coder, out, in ) >= 0 ) {
9595 10           tstr = xmlStrdup( out->content );
9596             }
9597              
9598 10           xmlBufferFree( in );
9599 10           xmlBufferFree( out );
9600 10           xmlCharEncCloseFunc( coder );
9601              
9602 10           CLEANUP_ERROR_HANDLER;
9603 10           REPORT_ERROR(0);
9604             }
9605             }
9606             else {
9607 0           tstr = xmlStrndup( realstring, len );
9608             }
9609              
9610 14 50         if ( !tstr ) {
9611 0           croak( "return value missing!" );
9612             }
9613              
9614 14           len = xmlStrlen( tstr );
9615 14           RETVAL = newSVpvn( (const char *)tstr, len );
9616             #ifdef HAVE_UTF8
9617 14           SvUTF8_on(RETVAL);
9618             #endif
9619 14           xmlFree(tstr);
9620             }
9621             else {
9622 0           XSRETURN_UNDEF;
9623             }
9624             OUTPUT:
9625             RETVAL
9626              
9627             SV*
9628             decodeFromUTF8( encoding, string )
9629             const char * encoding
9630             SV* string
9631             PREINIT:
9632 9           xmlChar * tstr = NULL;
9633 9           xmlChar * realstring = NULL;
9634 9           xmlCharEncoding enc = 0;
9635 9           STRLEN len = 0;
9636 9           xmlBufferPtr in = NULL, out = NULL;
9637 9           xmlCharEncodingHandlerPtr coder = NULL;
9638 9           PREINIT_SAVED_ERROR
9639             CODE:
9640             #ifdef HAVE_UTF8
9641 9 100         if ( !SvOK(string) ) {
    50          
    50          
9642 2           XSRETURN_UNDEF;
9643 8 100         } else if (!SvCUR(string)) {
9644 1           XSRETURN_PV("");
9645 7 50         } else if ( !SvUTF8(string) ) {
9646 0           croak("string is not utf8!!");
9647             } else {
9648             #endif
9649 7 50         realstring = (xmlChar*) SvPV(string, len);
9650 7 50         if ( realstring != NULL ) {
9651             /* warn("decode %s", realstring ); */
9652 7           enc = xmlParseCharEncoding( encoding );
9653 7 50         if ( enc == 0 ) {
9654             /* this happens if the encoding is "" or NULL */
9655 0           enc = XML_CHAR_ENCODING_UTF8;
9656             }
9657              
9658 7 100         if ( enc == XML_CHAR_ENCODING_UTF8 ) {
9659             /* copy the string */
9660             /* warn( "simply copy the string" ); */
9661 1           tstr = xmlStrdup( realstring );
9662 1           len = xmlStrlen( tstr );
9663             }
9664             else {
9665 6           INIT_ERROR_HANDLER;
9666 6 100         if ( enc > 1 ) {
9667 4           coder= xmlGetCharEncodingHandler( enc );
9668             }
9669 2 50         else if ( enc == XML_CHAR_ENCODING_ERROR ){
9670 2           coder = xmlFindCharEncodingHandler( encoding );
9671             }
9672             else {
9673 0           croak("no encoder found\n");
9674             }
9675              
9676 6 50         if ( coder == NULL ) {
9677 0           croak( "cannot encode string" );
9678             }
9679              
9680 6           in = xmlBufferCreate();
9681 6           out = xmlBufferCreate();
9682 6           xmlBufferCCat( in, (char*) realstring );
9683 6 50         if ( xmlCharEncOutFunc( coder, out, in ) >= 0 ) {
9684 6           len = xmlBufferLength( out );
9685 6           tstr = xmlCharStrndup( (char*) xmlBufferContent( out ), len );
9686             }
9687              
9688 6           xmlBufferFree( in );
9689 6           xmlBufferFree( out );
9690 6           xmlCharEncCloseFunc( coder );
9691 6           CLEANUP_ERROR_HANDLER;
9692 6           REPORT_ERROR(0);
9693 6 50         if ( !tstr ) {
9694 0           croak( "return value missing!" );
9695             }
9696             }
9697              
9698 7           RETVAL = newSVpvn( (const char *)tstr, len );
9699 7           xmlFree( tstr );
9700             #ifdef HAVE_UTF8
9701 7 100         if ( enc == XML_CHAR_ENCODING_UTF8 ) {
9702 7           SvUTF8_on(RETVAL);
9703             }
9704             #endif
9705             }
9706             else {
9707 0           XSRETURN_UNDEF;
9708             }
9709             #ifdef HAVE_UTF8
9710             }
9711             #endif
9712             OUTPUT:
9713             RETVAL