File Coverage

LibXML.xs
Criterion Covered Total %
statement 3247 3902 83.2
branch 2022 4242 47.6
condition n/a
subroutine n/a
pod n/a
total 5269 8144 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 464           LibXML_struct_error_callback(SV * saved_error, SV * libErr )
203             {
204              
205             dTHX;
206 464           dSP;
207              
208 464 50         if ( saved_error == NULL ) {
209 0           warn( "have no save_error\n" );
210             }
211              
212 464           ENTER;
213 464           SAVETMPS;
214 464 50         PUSHMARK(SP);
215              
216 464 50         XPUSHs(sv_2mortal(libErr));
217 464 50         if ( saved_error != NULL && SvOK(saved_error) ) {
    100          
    50          
    50          
218 300 50         XPUSHs(saved_error);
219             }
220 464           PUTBACK;
221              
222 464 50         if ( saved_error != NULL ) {
223 464           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 464           SPAGAIN;
228              
229 464 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 464           sv_setsv(saved_error, POPs);
234             }
235              
236 464           PUTBACK;
237 464 50         FREETMPS;
238 464           LEAVE;
239 464           }
240              
241             void
242 461           LibXML_struct_error_handler(SV * saved_error, xmlErrorPtr error )
243             {
244 461           const char * CLASS = "XML::LibXML::LibError";
245             SV* libErr;
246              
247 461           libErr = NEWSV(0,0);
248 461           sv_setref_pv( libErr, CLASS, (void*)error );
249 461           LibXML_struct_error_callback( saved_error, libErr);
250 461           }
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 1622           LibXML_report_error_ctx(SV * saved_error, int recover)
361             {
362             #ifdef WITH_SERRORS
363 1622 50         if( saved_error!=NULL && SvOK( saved_error ) ) {
    100          
    50          
    50          
364 160 100         if (!recover || recover==1) {
    100          
365             dTHX;
366 156           dSP;
367              
368 156           ENTER;
369 156           SAVETMPS;
370 156 50         PUSHMARK(SP);
371 156 50         EXTEND(SP, 1);
372 156           PUSHs(saved_error);
373 156           PUTBACK;
374 156 100         if (recover==1) {
375 3           call_pv( "XML::LibXML::Error::_report_warning", G_SCALAR | G_DISCARD);
376             } else {
377 153           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 1469           }
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 905           LibXML_get_recover(HV * real_obj)
475             {
476 905           SV** item = hv_fetch( real_obj, "XML_LIBXML_RECOVER", 18, 0 );
477 905 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 1010           LibXML_init_parser( SV * self, xmlParserCtxtPtr ctxt ) {
898             /* we fetch all switches and callbacks from the hash */
899 1010           HV* real_obj = NULL;
900 1010           SV** item = NULL;
901 1010           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 1010 50         if ( self != NULL ) {
918             /* first fetch the values from the hash */
919 1010           real_obj = (HV *)SvRV(self);
920              
921 1010           item = hv_fetch( real_obj, "XML_LIBXML_PARSER_OPTIONS", 25, 0 );
922 1010 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 1010 100         if ((parserOptions & XML_PARSE_DTDLOAD) == 0) {
929 882           parserOptions &= ~(XML_PARSE_DTDVALID | XML_PARSE_DTDATTR | XML_PARSE_NOENT );
930             }
931 1010 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 1010 100         if (parserOptions & XML_PARSE_NOBLANKS) {
942 61           xmlKeepBlanksDefault(0);
943             }
944             else {
945 949           xmlKeepBlanksDefault(1);
946             }
947              
948 1010           item = hv_fetch( real_obj, "XML_LIBXML_LINENUMBERS", 22, 0 );
949 1010 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 1008 100         if (ctxt) ctxt->linenumbers = 0;
954             }
955              
956 1010 100         if(EXTERNAL_ENTITY_LOADER_FUNC == NULL)
957             {
958 1009           item = hv_fetch(real_obj, "ext_ent_handler", 15, 0);
959 1009 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 1006 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 1010           return real_obj;
976             }
977              
978             void
979 1008           LibXML_cleanup_parser() {
980             #ifndef WITH_SERRORS
981             xmlGetWarningsDefaultValue = 0;
982             #endif
983 1008 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 1008           }
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 78           int recover = 0;
2544 78           xmlParserCtxtPtr ctxt = NULL;
2545 78           PREINIT_SAVED_ERROR
2546             CODE:
2547 78           RETVAL = &PL_sv_undef;
2548 78           INIT_ERROR_HANDLER;
2549              
2550             /* create empty context */
2551 78           ctxt = xmlCreatePushParserCtxt( NULL, NULL, NULL, 0, NULL );
2552 78           real_obj = LibXML_init_parser(self,ctxt);
2553 78           recover = LibXML_get_recover(real_obj);
2554 78 100         if ( with_sax == 1 ) {
2555 36           PmmSAXInitContext( ctxt, self, saved_error );
2556             }
2557              
2558 78           RETVAL = PmmContextSv( ctxt );
2559              
2560 78           LibXML_cleanup_parser();
2561 78           CLEANUP_ERROR_HANDLER;
2562 78           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 300           int recover = 0;
2574 300           xmlParserCtxtPtr ctxt = NULL;
2575 300           STRLEN len = 0;
2576 300           char * chunk = NULL;
2577 300           PREINIT_SAVED_ERROR
2578             INIT:
2579 300           ctxt = PmmSvContext( pctxt );
2580 300 50         if ( ctxt == NULL ) {
2581 0           croak( "parser context already freed\n" );
2582 0           XSRETURN_UNDEF;
2583             }
2584 300 50         if ( data == &PL_sv_undef ) {
2585 0           XSRETURN_UNDEF;
2586             }
2587 300 50         chunk = SvPV( data, len );
2588 300 50         if ( len <= 0 ) {
2589             xs_warn( "empty string" );
2590 0           XSRETURN_UNDEF;
2591             }
2592             CODE:
2593 300           RETVAL = 0;
2594 300           INIT_ERROR_HANDLER;
2595 300           real_obj = LibXML_init_parser(self,NULL);
2596 300           recover = LibXML_get_recover(real_obj);
2597              
2598 300           xmlParseChunk(ctxt, (const char *)chunk, len, 0);
2599              
2600 300           LibXML_cleanup_parser();
2601 300           CLEANUP_ERROR_HANDLER;
2602 300           REPORT_ERROR(recover);
2603              
2604 299 100         if ( ctxt->wellFormed == 0 ) {
2605 6           croak( "XML not well-formed in xmlParseChunk\n" );
2606             XSRETURN_UNDEF;
2607             }
2608 293           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 41           xmlParserCtxtPtr ctxt = NULL;
2621 41           xmlDocPtr real_doc = NULL;
2622 41           PREINIT_SAVED_ERROR
2623             INIT:
2624 41           ctxt = PmmSvContext( pctxt );
2625 41 50         if ( ctxt == NULL ) {
2626 0           croak( "parser context already freed\n" );
2627             XSRETURN_UNDEF;
2628             }
2629             CODE:
2630 41           RETVAL = &PL_sv_undef;
2631 41           INIT_ERROR_HANDLER;
2632 41           real_obj = LibXML_init_parser(self,NULL);
2633              
2634 41           xmlParseChunk(ctxt, "", 0, 1); /* finish the parse */
2635             xs_warn( "Finished with push parser\n" );
2636              
2637 41           well_formed = ctxt->wellFormed;
2638 41           real_doc = ctxt->myDoc;
2639 41           ctxt->myDoc = NULL;
2640 41           xmlFreeParserCtxt(ctxt);
2641 41 50         PmmNODE( SvPROXYNODE( pctxt ) ) = NULL;
2642              
2643 41 50         if ( real_doc != NULL ) {
2644 41 100         if ( restore || well_formed ) {
    100          
2645 39           RETVAL = LibXML_NodeToSv( real_obj, INT2PTR(xmlNodePtr,real_doc) );
2646             } else {
2647 2           xmlFreeDoc(real_doc);
2648 2           real_doc = NULL;
2649             }
2650             }
2651              
2652 41           LibXML_cleanup_parser();
2653 41           CLEANUP_ERROR_HANDLER;
2654 41           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 78 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           memset(&cvp, 0, sizeof(cvp));
4029 3           cvp.userData = saved_error;
4030 3           cvp.error = (xmlValidityErrorFunc)LibXML_validity_error_ctx;
4031 3           cvp.warning = (xmlValidityWarningFunc)LibXML_validity_warning_ctx;
4032              
4033 3 50         PmmClearPSVI(self);
    50          
    50          
    100          
4034 3 50         PmmInvalidatePSVI(self);
    50          
4035 3 100         if (items > 1) {
4036 2           dtd_sv = ST(1);
4037 2 50         if ( sv_isobject(dtd_sv) && (SvTYPE(SvRV(dtd_sv)) == SVt_PVMG) ) {
    50          
4038 2           dtd = (xmlDtdPtr)PmmSvNode(dtd_sv);
4039             }
4040 2           RETVAL = xmlValidateDtd(&cvp, self, dtd);
4041             }
4042             else {
4043 1           RETVAL = xmlValidateDocument(&cvp, self);
4044             }
4045 3           CLEANUP_ERROR_HANDLER;
4046             /* REPORT_ERROR(1); */
4047             OUTPUT:
4048             RETVAL
4049              
4050             int
4051             validate(self, ...)
4052             xmlDocPtr self
4053             PREINIT:
4054             xmlValidCtxt cvp;
4055             xmlDtdPtr dtd;
4056             SV * dtd_sv;
4057 5           PREINIT_SAVED_ERROR
4058             CODE:
4059 5           INIT_ERROR_HANDLER;
4060              
4061 5           memset(&cvp, 0, sizeof(cvp));
4062 5           cvp.userData = saved_error;
4063 5           cvp.error = (xmlValidityErrorFunc)LibXML_validity_error_ctx;
4064 5           cvp.warning = (xmlValidityWarningFunc)LibXML_validity_warning_ctx;
4065              
4066 5 50         PmmClearPSVI(self);
    50          
    50          
    100          
4067 5 50         PmmInvalidatePSVI(self);
    50          
4068              
4069 5 100         if (items > 1) {
4070 2           dtd_sv = ST(1);
4071 2 50         if ( sv_isobject(dtd_sv) && (SvTYPE(SvRV(dtd_sv)) == SVt_PVMG) ) {
    50          
4072 2           dtd = (xmlDtdPtr)PmmSvNode(dtd_sv);
4073             }
4074             else {
4075 0           CLEANUP_ERROR_HANDLER;
4076 0           croak("is_valid: argument must be a DTD object");
4077             }
4078 2           RETVAL = xmlValidateDtd(&cvp, self , dtd);
4079             }
4080             else {
4081 3           RETVAL = xmlValidateDocument(&cvp, self);
4082             }
4083 5           CLEANUP_ERROR_HANDLER;
4084 5           REPORT_ERROR(RETVAL ? 1 : 0);
4085             OUTPUT:
4086             RETVAL
4087              
4088             SV*
4089             cloneNode( self, deep=0 )
4090             xmlDocPtr self
4091             int deep
4092             PREINIT:
4093 2           xmlDocPtr ret = NULL;
4094             CODE:
4095 2           ret = xmlCopyDoc( self, deep );
4096 2 50         if ( ret == NULL ) {
4097 0           XSRETURN_UNDEF;
4098             }
4099 2           RETVAL = PmmNodeToSv((xmlNodePtr)ret, NULL);
4100             OUTPUT:
4101             RETVAL
4102              
4103             SV*
4104             getElementById( self, id )
4105             xmlDocPtr self
4106             const char * id
4107             ALIAS:
4108             XML::LibXML::Document::getElementsById = 1
4109             PREINIT:
4110             xmlNodePtr elem;
4111             xmlAttrPtr attr;
4112             CODE:
4113             PERL_UNUSED_VAR(ix);
4114 22 50         if ( id != NULL ) {
4115 22           attr = xmlGetID(self, (xmlChar *) id);
4116 22 100         if (attr == NULL)
4117 5           elem = NULL;
4118 17 50         else if (attr->type == XML_ATTRIBUTE_NODE)
4119 17           elem = attr->parent;
4120 0 0         else if (attr->type == XML_ELEMENT_NODE)
4121 0           elem = (xmlNodePtr) attr;
4122             else
4123 0           elem = NULL;
4124 22 100         if (elem != NULL) {
4125 17           RETVAL = PmmNodeToSv(elem, PmmPROXYNODE(self));
4126             }
4127             else {
4128 5           XSRETURN_UNDEF;
4129             }
4130             }
4131             else {
4132 0           XSRETURN_UNDEF;
4133             }
4134             OUTPUT:
4135             RETVAL
4136              
4137             int
4138             indexElements ( self )
4139             xmlDocPtr self
4140             CODE:
4141             #if LIBXML_VERSION >= 20508
4142 0           RETVAL = xmlXPathOrderDocElems( self );
4143             #else
4144             RETVAL = -2;
4145             #endif
4146             OUTPUT:
4147             RETVAL
4148              
4149             MODULE = XML::LibXML PACKAGE = XML::LibXML::Node
4150              
4151             void
4152             DESTROY( node )
4153             SV * node
4154             PREINIT:
4155             int count;
4156             SV *is_shared;
4157             CODE:
4158             #ifdef XML_LIBXML_THREADS
4159             if ( (is_shared = get_sv("XML::LibXML::__threads_shared", 0)) == NULL ) {
4160             is_shared = &PL_sv_undef;
4161             }
4162             if ( SvTRUE(is_shared) ) {
4163             dSP;
4164             ENTER;
4165             SAVETMPS;
4166             PUSHMARK(SP);
4167             XPUSHs(node);
4168             PUTBACK;
4169             count = call_pv("threads::shared::is_shared", G_SCALAR);
4170             SPAGAIN;
4171             if (count != 1)
4172             croak("Couldn't checks if the variable is shared or not\n");
4173             is_shared = POPs;
4174             PUTBACK;
4175             FREETMPS;
4176             LEAVE;
4177             if (is_shared != &PL_sv_undef) {
4178             XSRETURN_UNDEF;
4179             }
4180             }
4181             if( PmmUSEREGISTRY ) {
4182             SvLOCK(PROXY_NODE_REGISTRY_MUTEX);
4183             PmmRegistryREFCNT_dec(SvPROXYNODE(node));
4184             }
4185             #endif
4186 20452 50         PmmREFCNT_dec(SvPROXYNODE(node));
4187             #ifdef XML_LIBXML_THREADS
4188             if( PmmUSEREGISTRY )
4189             SvUNLOCK(PROXY_NODE_REGISTRY_MUTEX);
4190             #endif
4191              
4192             SV*
4193             nodeName( self )
4194             xmlNodePtr self
4195             ALIAS:
4196             XML::LibXML::Node::getName = 1
4197             XML::LibXML::Element::tagName = 2
4198             PREINIT:
4199 253           xmlChar * name = NULL;
4200             CODE:
4201             PERL_UNUSED_VAR(ix);
4202 253           name = (xmlChar*)domName( self );
4203 253 50         if ( name != NULL ) {
4204 253           RETVAL = C2Sv(name,NULL);
4205 253           xmlFree( name );
4206             }
4207             else {
4208 0           XSRETURN_UNDEF;
4209             }
4210             OUTPUT:
4211             RETVAL
4212              
4213             SV*
4214             localname( self )
4215             xmlNodePtr self
4216             ALIAS:
4217             XML::LibXML::Node::getLocalName = 1
4218             XML::LibXML::Attr::name = 2
4219             XML::LibXML::Node::localName = 3
4220             CODE:
4221             PERL_UNUSED_VAR(ix);
4222 126 100         if ( self->type == XML_ELEMENT_NODE
4223 55 50         || self->type == XML_ATTRIBUTE_NODE
4224 0 0         || self->type == XML_ELEMENT_DECL
4225 0 0         || self->type == XML_ATTRIBUTE_DECL ) {
4226 126           RETVAL = C2Sv(self->name,NULL);
4227             }
4228             else {
4229 0           XSRETURN_UNDEF;
4230             }
4231             OUTPUT:
4232             RETVAL
4233              
4234             SV*
4235             prefix( self )
4236             xmlNodePtr self
4237             ALIAS:
4238             XML::LibXML::Node::getPrefix = 1
4239             CODE:
4240             PERL_UNUSED_VAR(ix);
4241 58 100         if( ( self->type == XML_ELEMENT_NODE
4242 14 50         || self->type == XML_ATTRIBUTE_NODE
4243 0 0         || self->type == XML_PI_NODE )
4244 58 100         && self->ns != NULL
4245 11 100         && self->ns->prefix != NULL ) {
4246 6           RETVAL = C2Sv(self->ns->prefix, NULL);
4247             }
4248             else {
4249 52           XSRETURN_UNDEF;
4250             }
4251             OUTPUT:
4252             RETVAL
4253              
4254             SV*
4255             namespaceURI( self )
4256             xmlNodePtr self
4257             ALIAS:
4258             getNamespaceURI = 1
4259             PREINIT:
4260             xmlChar * nsURI;
4261             CODE:
4262             PERL_UNUSED_VAR(ix);
4263 77 100         if ( ( self->type == XML_ELEMENT_NODE
4264 26 50         || self->type == XML_ATTRIBUTE_NODE
4265 0 0         || self->type == XML_PI_NODE )
4266 77 100         && self->ns != NULL
4267 25 50         && self->ns->href != NULL ) {
4268 25           nsURI = xmlStrdup(self->ns->href);
4269 25           RETVAL = C2Sv( nsURI, NULL );
4270 25           xmlFree( nsURI );
4271             }
4272             else {
4273 52           XSRETURN_UNDEF;
4274             }
4275             OUTPUT:
4276             RETVAL
4277              
4278              
4279             SV*
4280             lookupNamespaceURI( self, svprefix=&PL_sv_undef )
4281             xmlNodePtr self
4282             SV * svprefix
4283             PREINIT:
4284             xmlChar * nsURI;
4285 23           xmlChar * prefix = NULL;
4286             xmlNsPtr ns;
4287             CODE:
4288 23           prefix = nodeSv2C( svprefix , self );
4289 23 100         if ( prefix != NULL && xmlStrlen(prefix) == 0) {
    100          
4290 5           xmlFree( prefix );
4291 5           prefix = NULL;
4292             }
4293 23           ns = xmlSearchNs( self->doc, self, prefix );
4294 23 100         if ( prefix != NULL) {
4295 17           xmlFree( prefix );
4296             }
4297 23 100         if ( ns != NULL ) {
4298 16           nsURI = xmlStrdup(ns->href);
4299 16           RETVAL = C2Sv( nsURI, NULL );
4300 16           xmlFree( nsURI );
4301             }
4302             else {
4303 7           XSRETURN_UNDEF;
4304             }
4305             OUTPUT:
4306             RETVAL
4307              
4308             SV*
4309             lookupNamespacePrefix( self, svuri )
4310             xmlNodePtr self
4311             SV * svuri
4312             PREINIT:
4313             xmlChar * nsprefix;
4314 7           xmlChar * href = NULL;
4315             CODE:
4316 7           href = nodeSv2C( svuri , self );
4317 11 50         if ( href != NULL && xmlStrlen(href) > 0) {
    50          
4318 7           xmlNsPtr ns = xmlSearchNsByHref( self->doc, self, href );
4319 7           xmlFree( href );
4320 7 100         if ( ns != NULL ) {
4321 4 100         if ( ns->prefix != NULL ) {
4322 3           nsprefix = xmlStrdup( ns->prefix );
4323 3           RETVAL = C2Sv( nsprefix, NULL );
4324 3           xmlFree(nsprefix);
4325             } else {
4326 4           RETVAL = newSVpv("",0);
4327             }
4328             }
4329             else {
4330 3           XSRETURN_UNDEF;
4331             }
4332             }
4333             else {
4334 0           XSRETURN_UNDEF;
4335             }
4336             OUTPUT:
4337             RETVAL
4338              
4339              
4340             void
4341             setNodeName( self , value )
4342             xmlNodePtr self
4343             SV* value
4344             ALIAS:
4345             setName = 1
4346             PREINIT:
4347             xmlChar* string;
4348             xmlChar* localname;
4349             xmlChar* prefix;
4350             CODE:
4351             PERL_UNUSED_VAR(ix);
4352 11           string = nodeSv2C( value , self );
4353 11 100         if ( !LibXML_test_node_name( string ) ) {
4354 4           xmlFree(string);
4355 4           croak( "bad name" );
4356             }
4357 7 100         if( ( self->type == XML_ELEMENT_NODE
4358 2 50         || self->type == XML_ATTRIBUTE_NODE
4359 0 0         || self->type == XML_PI_NODE)
4360 7 100         && self->ns ){
4361 5           localname = xmlSplitQName2(string, &prefix);
4362 5 100         if ( localname == NULL ) {
4363 3           localname = xmlStrdup( string );
4364             }
4365 5           xmlNodeSetName(self, localname );
4366 5           xmlFree(localname);
4367 5           xmlFree(prefix);
4368             }
4369             else {
4370             xs_warn("node name normal\n");
4371 2           xmlNodeSetName(self, string );
4372             }
4373 7           xmlFree(string);
4374              
4375             void
4376             setRawName( self, value )
4377             xmlNodePtr self
4378             SV * value
4379             PREINIT:
4380             xmlChar* string;
4381             xmlChar* localname;
4382             xmlChar* prefix;
4383             CODE:
4384 0           string = nodeSv2C( value , self );
4385 0 0         if ( !string || xmlStrlen( string) <= 0 ) {
    0          
4386 0           xmlFree(string);
4387 0           XSRETURN_UNDEF;
4388             }
4389 0 0         if( ( self->type == XML_ELEMENT_NODE
4390 0 0         || self->type == XML_ATTRIBUTE_NODE
4391 0 0         || self->type == XML_PI_NODE)
4392 0 0         && self->ns ){
4393 0           localname = xmlSplitQName2(string, &prefix);
4394 0           xmlNodeSetName(self, localname );
4395 0           xmlFree(localname);
4396 0           xmlFree(prefix);
4397             }
4398             else {
4399 0           xmlNodeSetName(self, string );
4400             }
4401 0           xmlFree(string);
4402              
4403              
4404             SV*
4405             nodeValue( self, useDomEncoding = &PL_sv_undef )
4406             xmlNodePtr self
4407             SV * useDomEncoding
4408             ALIAS:
4409             XML::LibXML::Attr::value = 1
4410             XML::LibXML::Attr::getValue = 2
4411             XML::LibXML::Text::data = 3
4412             XML::LibXML::Node::getValue = 4
4413             XML::LibXML::Node::getData = 5
4414             PREINIT:
4415 172           xmlChar * content = NULL;
4416             CODE:
4417             PERL_UNUSED_VAR(ix);
4418 171           content = domGetNodeValue( self );
4419              
4420 171 100         if ( content != NULL ) {
4421 169 50         if ( SvTRUE(useDomEncoding) ) {
    50          
    0          
    50          
    50          
    50          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
4422 0           RETVAL = nodeC2Sv(content, self);
4423             }
4424             else {
4425 169           RETVAL = C2Sv(content, NULL);
4426             }
4427 169           xmlFree(content);
4428             }
4429             else {
4430 2           XSRETURN_UNDEF;
4431             }
4432             OUTPUT:
4433             RETVAL
4434              
4435             int
4436             nodeType( self )
4437             xmlNodePtr self
4438             ALIAS:
4439             XML::LibXML::Node::getType = 1
4440             CODE:
4441             PERL_UNUSED_VAR(ix);
4442 213           RETVAL = self->type;
4443             OUTPUT:
4444             RETVAL
4445              
4446             SV*
4447             parentNode( self )
4448             xmlNodePtr self
4449             ALIAS:
4450             XML::LibXML::Attr::ownerElement = 1
4451             XML::LibXML::Node::getParentNode = 2
4452             XML::LibXML::Attr::getOwnerElement = 3
4453             CODE:
4454             PERL_UNUSED_VAR(ix);
4455 316 50         RETVAL = PmmNodeToSv( self->parent,
4456 158 50         PmmOWNERPO( PmmPROXYNODE(self) ) );
4457             OUTPUT:
4458             RETVAL
4459              
4460             SV*
4461             nextSibling( self )
4462             xmlNodePtr self
4463             ALIAS:
4464             getNextSibling = 1
4465             CODE:
4466             PERL_UNUSED_VAR(ix);
4467 30 50         RETVAL = PmmNodeToSv( self->next,
4468 15 50         PmmOWNERPO(PmmPROXYNODE(self)) );
4469             OUTPUT:
4470             RETVAL
4471              
4472             SV*
4473             nextNonBlankSibling( self )
4474             xmlNodePtr self
4475             PREINIT:
4476             xmlNodePtr next;
4477             CODE:
4478 14           next = self->next;
4479 28 100         while (next != NULL && xmlIsBlankNode(next))
    100          
4480 14           next = next->next;
4481 28 50         RETVAL = PmmNodeToSv( next,
4482 14 50         PmmOWNERPO(PmmPROXYNODE(self)) );
4483             OUTPUT:
4484             RETVAL
4485              
4486              
4487             SV*
4488             previousSibling( self )
4489             xmlNodePtr self
4490             ALIAS:
4491             getPreviousSibling = 1
4492             CODE:
4493             PERL_UNUSED_VAR(ix);
4494 8 50         RETVAL = PmmNodeToSv( self->prev,
4495 4 50         PmmOWNERPO( PmmPROXYNODE(self) ) );
4496             OUTPUT:
4497             RETVAL
4498              
4499             SV*
4500             previousNonBlankSibling( self )
4501             xmlNodePtr self
4502             PREINIT:
4503             xmlNodePtr prev;
4504             CODE:
4505 14           prev = self->prev;
4506 30 100         while (prev != NULL && xmlIsBlankNode(prev))
    100          
4507 16           prev = prev->prev;
4508 28 50         RETVAL = PmmNodeToSv( prev,
4509 14 50         PmmOWNERPO(PmmPROXYNODE(self)) );
4510             OUTPUT:
4511             RETVAL
4512              
4513              
4514             void
4515             _childNodes( self, only_nonblank = 0 )
4516             xmlNodePtr self
4517             int only_nonblank
4518             ALIAS:
4519             XML::LibXML::Node::getChildnodes = 1
4520             PREINIT:
4521             xmlNodePtr cld;
4522             SV * element;
4523 165           int len = 0;
4524 165 50         int wantarray = GIMME_V;
4525             PPCODE:
4526             PERL_UNUSED_VAR(ix);
4527 165 50         if ( self->type != XML_ATTRIBUTE_NODE ) {
4528 165           cld = self->children;
4529             xs_warn("childnodes start");
4530 620 100         while ( cld ) {
4531 455 100         if ( !(only_nonblank && xmlIsBlankNode(cld)) ) {
    100          
4532 439 50         if( wantarray != G_SCALAR ) {
4533 439 50         element = PmmNodeToSv(cld, PmmOWNERPO(PmmPROXYNODE(self)) );
    100          
4534 439 50         XPUSHs(sv_2mortal(element));
4535             }
4536 439           len++;
4537             }
4538 455           cld = cld->next;
4539             }
4540             }
4541 165 50         if ( wantarray == G_SCALAR ) {
4542 0 0         XPUSHs(sv_2mortal(newSViv(len)) );
4543             }
4544              
4545             void
4546             _getChildrenByTagNameNS( self, namespaceURI, node_name )
4547             xmlNodePtr self
4548             SV * namespaceURI
4549             SV * node_name
4550             PREINIT:
4551             xmlChar * name;
4552             xmlChar * nsURI;
4553             xmlNodePtr cld;
4554             SV * element;
4555 12           int len = 0;
4556 12           int name_wildcard = 0;
4557 12           int ns_wildcard = 0;
4558 12 50         int wantarray = GIMME_V;
4559             PPCODE:
4560 12           name = nodeSv2C(node_name, self );
4561 12           nsURI = nodeSv2C(namespaceURI, self );
4562              
4563 12 50         if ( nsURI != NULL ) {
4564 12 50         if (xmlStrlen(nsURI) == 0 ) {
4565 0           xmlFree(nsURI);
4566 0           nsURI = NULL;
4567 12 100         } else if (xmlStrcmp( nsURI, (xmlChar *)"*" )==0) {
4568 9           ns_wildcard = 1;
4569             }
4570             }
4571 12 50         if ( name !=NULL && xmlStrcmp( name, (xmlChar *)"*" ) == 0) {
    100          
4572 6           name_wildcard = 1;
4573             }
4574 12 50         if ( self->type != XML_ATTRIBUTE_NODE ) {
4575 12           cld = self->children;
4576             xs_warn("childnodes start");
4577 48 100         while ( cld ) {
4578 60 100         if (((name_wildcard && (cld->type == XML_ELEMENT_NODE)) ||
4579 24           xmlStrcmp( name, cld->name ) == 0)
4580 24 100         && (ns_wildcard ||
    100          
4581 3 50         (cld->ns != NULL &&
4582 6 50         xmlStrcmp(nsURI,cld->ns->href) == 0 ) ||
4583 3 50         (cld->ns == NULL && nsURI == NULL))) {
4584 21 50         if( wantarray != G_SCALAR ) {
4585 21 50         element = PmmNodeToSv(cld, PmmOWNERPO(PmmPROXYNODE(self)) );
    50          
4586 21 50         XPUSHs(sv_2mortal(element));
4587             }
4588 21           len++;
4589             }
4590 36           cld = cld->next;
4591             }
4592             }
4593 12 50         if ( wantarray == G_SCALAR ) {
4594 0 0         XPUSHs(sv_2mortal(newSViv(len)) );
4595             }
4596 12           xmlFree(name);
4597 12 50         if (nsURI) xmlFree(nsURI);
4598              
4599             SV*
4600             firstChild( self )
4601             xmlNodePtr self
4602             ALIAS:
4603             getFirstChild = 1
4604             CODE:
4605             PERL_UNUSED_VAR(ix);
4606 102 50         RETVAL = PmmNodeToSv( self->children,
4607 51 100         PmmOWNERPO( PmmPROXYNODE(self) ) );
4608             OUTPUT:
4609             RETVAL
4610              
4611             SV*
4612             firstNonBlankChild( self )
4613             xmlNodePtr self
4614             PREINIT:
4615             xmlNodePtr child;
4616             CODE:
4617 2           child = self->children;
4618 4 50         while (child !=NULL && xmlIsBlankNode(child))
    100          
4619 2           child = child->next;
4620 4 50         RETVAL = PmmNodeToSv( child,
4621 2 50         PmmOWNERPO( PmmPROXYNODE(self) ) );
4622             OUTPUT:
4623             RETVAL
4624              
4625             SV*
4626             lastChild( self )
4627             xmlNodePtr self
4628             ALIAS:
4629             getLastChild = 1
4630             CODE:
4631             PERL_UNUSED_VAR(ix);
4632 56 50         RETVAL = PmmNodeToSv( self->last,
4633 28 100         PmmOWNERPO( PmmPROXYNODE(self) ) );
4634             OUTPUT:
4635             RETVAL
4636              
4637             void
4638             _attributes( self )
4639             xmlNodePtr self
4640             ALIAS:
4641             XML::LibXML::Node::getAttributes = 1
4642             PREINIT:
4643 51           xmlAttrPtr attr = NULL;
4644 51           xmlNsPtr ns = NULL;
4645             SV * element;
4646 51           int len=0;
4647 51 50         int wantarray = GIMME_V;
4648             PPCODE:
4649             PERL_UNUSED_VAR(ix);
4650 51 50         if ( self->type != XML_ATTRIBUTE_NODE
4651 51 100         && self->type != XML_DTD_NODE ) {
4652 50           attr = self->properties;
4653 83 100         while ( attr != NULL ) {
4654 33 50         if ( wantarray != G_SCALAR ) {
4655 66 50         element = PmmNodeToSv((xmlNodePtr)attr,
4656 33 50         PmmOWNERPO(PmmPROXYNODE(self)) );
4657 33 50         XPUSHs(sv_2mortal(element));
4658             }
4659 33           attr = attr->next;
4660 33           len++;
4661             }
4662 50 50         if (self->type == XML_ELEMENT_NODE) {
4663 50           ns = self->nsDef;
4664 64 100         while ( ns != NULL ) {
4665 14           const char * CLASS = "XML::LibXML::Namespace";
4666 14 50         if ( wantarray != G_SCALAR ) {
4667             /* namespace handling is kinda odd:
4668             * as soon we have a namespace isolated from its
4669             * owner, we loose the context. therefore it is
4670             * forbidden to access the NS information directly.
4671             * instead the use will receive a copy of the real
4672             * namespace, that can be destroied and is not
4673             * bound to a document.
4674             *
4675             * this avoids segfaults in the end.
4676             */
4677 14 100         if ((ns->prefix != NULL || ns->href != NULL)) {
    50          
4678 14           xmlNsPtr tns = xmlCopyNamespace(ns);
4679 14 50         if ( tns != NULL ) {
4680 14           element = sv_newmortal();
4681 14 50         XPUSHs(sv_setref_pv( element,
4682             (char *)CLASS,
4683             (void*)tns));
4684             }
4685             }
4686             }
4687 14           ns = ns->next;
4688 14           len++;
4689             }
4690             }
4691             }
4692 51 50         if( wantarray == G_SCALAR ) {
4693 0 0         XPUSHs( sv_2mortal(newSViv(len)) );
4694             }
4695              
4696             int
4697             hasChildNodes( self )
4698             xmlNodePtr self
4699             CODE:
4700 125 100         if ( self->type == XML_ATTRIBUTE_NODE ) {
4701 2           RETVAL = 0;
4702             }
4703             else {
4704 123           RETVAL = self->children ? 1 : 0 ;
4705             }
4706             OUTPUT:
4707             RETVAL
4708              
4709             int
4710             hasAttributes( self )
4711             xmlNodePtr self
4712             CODE:
4713 2 50         if ( self->type == XML_ATTRIBUTE_NODE
4714 2 100         || self->type == XML_DTD_NODE ) {
4715 1           RETVAL = 0;
4716             }
4717             else {
4718 1           RETVAL = self->properties ? 1 : 0 ;
4719             }
4720             OUTPUT:
4721             RETVAL
4722              
4723             SV*
4724             ownerDocument( self )
4725             xmlNodePtr self
4726             ALIAS:
4727             XML::LibXML::Node::getOwnerDocument = 1
4728             CODE:
4729             PERL_UNUSED_VAR(ix);
4730             xs_warn( "GET OWNERDOC\n" );
4731 19 50         if( self != NULL
4732 19 100         && self->doc != NULL ){
4733 17           RETVAL = PmmNodeToSv((xmlNodePtr)(self->doc), NULL);
4734             }
4735             else {
4736 2           XSRETURN_UNDEF;
4737             }
4738             OUTPUT:
4739             RETVAL
4740              
4741             SV*
4742             ownerNode( self )
4743             xmlNodePtr self
4744             ALIAS:
4745             XML::LibXML::Node::getOwner = 1
4746             XML::LibXML::Node::getOwnerElement = 2
4747             CODE:
4748             PERL_UNUSED_VAR(ix);
4749 0 0         RETVAL = PmmNodeToSv(PmmNODE(PmmOWNERPO(PmmPROXYNODE(self))), NULL);
    0          
4750             OUTPUT:
4751             RETVAL
4752              
4753              
4754             void
4755             normalize( self )
4756             xmlNodePtr self
4757             CODE:
4758 3           domNodeNormalize( self );
4759              
4760              
4761             SV*
4762             insertBefore( self, nNode, refNode )
4763             xmlNodePtr self
4764             xmlNodePtr nNode
4765             SV * refNode
4766             PREINIT:
4767 9           xmlNodePtr oNode=NULL, rNode;
4768             INIT:
4769 9           oNode = PmmSvNode(refNode);
4770             CODE:
4771 9           rNode = domInsertBefore( self, nNode, oNode );
4772 8 50         if ( rNode != NULL ) {
4773 16 50         RETVAL = PmmNodeToSv( rNode,
4774 8 100         PmmOWNERPO(PmmPROXYNODE(self)) );
4775 8 100         if (rNode->type == XML_DTD_NODE) {
4776 2           LibXML_set_int_subset(self->doc, rNode);
4777             }
4778 8 50         PmmFixOwner(PmmPROXYNODE(rNode), PmmOWNERPO(PmmPROXYNODE(self)));
    100          
4779             }
4780             else {
4781 0           XSRETURN_UNDEF;
4782             }
4783             OUTPUT:
4784             RETVAL
4785              
4786             SV*
4787             insertAfter( self, nNode, refNode )
4788             xmlNodePtr self
4789             xmlNodePtr nNode
4790             SV* refNode
4791             PREINIT:
4792 6           xmlNodePtr oNode = NULL, rNode;
4793             INIT:
4794 6           oNode = PmmSvNode(refNode);
4795             CODE:
4796 6           rNode = domInsertAfter( self, nNode, oNode );
4797 6 50         if ( rNode != NULL ) {
4798 12 50         RETVAL = PmmNodeToSv( rNode,
4799 6 100         PmmOWNERPO(PmmPROXYNODE(self)) );
4800 6 100         if (rNode->type == XML_DTD_NODE) {
4801 2           LibXML_set_int_subset(self->doc, rNode);
4802             }
4803 6 50         PmmFixOwner(PmmPROXYNODE(rNode), PmmOWNERPO(PmmPROXYNODE(self)));
    100          
4804             }
4805             else {
4806 0           XSRETURN_UNDEF;
4807             }
4808             OUTPUT:
4809             RETVAL
4810              
4811             SV*
4812             replaceChild( self, nNode, oNode )
4813             xmlNodePtr self
4814             xmlNodePtr nNode
4815             xmlNodePtr oNode
4816             PREINIT:
4817 5           xmlNodePtr ret = NULL;
4818             CODE:
4819             // if newNode == oldNode or self == newNode then do nothing, just return nNode.
4820 5 50         if (nNode == oNode || self == nNode ) {
    50          
4821 0           ret = nNode;
4822 0 0         RETVAL = PmmNodeToSv(ret, PmmOWNERPO(PmmPROXYNODE(ret)));
    0          
4823             }
4824             else{
4825 5 100         if ( self->type == XML_DOCUMENT_NODE ) {
4826 2           switch ( nNode->type ) {
4827             case XML_ELEMENT_NODE:
4828 0           warn("replaceChild with an element on a document node not supported yet!");
4829 0           XSRETURN_UNDEF;
4830             break;
4831             case XML_DOCUMENT_FRAG_NODE:
4832 0           warn("replaceChild with a document fragment node on a document node not supported yet!");
4833 0           XSRETURN_UNDEF;
4834             break;
4835             case XML_TEXT_NODE:
4836             case XML_CDATA_SECTION_NODE:
4837 0           warn("replaceChild with a text node not supported on a document node!");
4838 0           XSRETURN_UNDEF;
4839             break;
4840             default:
4841 2           break;
4842             }
4843             }
4844 5           ret = domReplaceChild( self, nNode, oNode );
4845 5 50         if (ret == NULL) {
4846 0           XSRETURN_UNDEF;
4847             }
4848             else {
4849 5           LibXML_reparent_removed_node(ret);
4850 5 50         RETVAL = PmmNodeToSv(ret, PmmOWNERPO(PmmPROXYNODE(ret)));
    50          
4851 5 100         if (nNode->type == XML_DTD_NODE) {
4852 2           LibXML_set_int_subset(nNode->doc, nNode);
4853             }
4854 5 50         if ( nNode->_private != NULL ) {
4855 10 50         PmmFixOwner( PmmPROXYNODE(nNode),
4856 5 100         PmmOWNERPO(PmmPROXYNODE(self)) );
4857             }
4858             }
4859             }
4860             OUTPUT:
4861             RETVAL
4862              
4863             SV*
4864             replaceNode( self,nNode )
4865             xmlNodePtr self
4866             xmlNodePtr nNode
4867             PREINIT:
4868 5           xmlNodePtr ret = NULL;
4869 5           ProxyNodePtr owner = NULL;
4870             CODE:
4871 5 50         if ( domIsParent( self, nNode ) == 1 ) {
4872 0           XSRETURN_UNDEF;
4873             }
4874 5 50         owner = PmmOWNERPO(PmmPROXYNODE(self));
    50          
4875              
4876 5 100         if ( self->type != XML_ATTRIBUTE_NODE ) {
4877 4           ret = domReplaceChild( self->parent, nNode, self);
4878             }
4879             else {
4880 1           ret = xmlReplaceNode( self, nNode );
4881             }
4882 5 50         if ( ret ) {
4883 5           LibXML_reparent_removed_node(ret);
4884 5 50         RETVAL = PmmNodeToSv(ret, PmmOWNERPO(PmmPROXYNODE(ret)));
    50          
4885 5 100         if (nNode->type == XML_DTD_NODE) {
4886 3           LibXML_set_int_subset(nNode->doc, nNode);
4887             }
4888 5 50         if ( nNode->_private != NULL ) {
4889 5           PmmFixOwner(PmmPROXYNODE(nNode), owner);
4890             }
4891             }
4892             else {
4893 0           croak( "replacement failed" );
4894             XSRETURN_UNDEF;
4895             }
4896             OUTPUT:
4897             RETVAL
4898              
4899             SV*
4900             removeChild( self, node )
4901             xmlNodePtr self
4902             xmlNodePtr node
4903             PREINIT:
4904             xmlNodePtr ret;
4905             CODE:
4906 15           ret = domRemoveChild( self, node );
4907 15 100         if (ret == NULL) {
4908 1           XSRETURN_UNDEF;
4909             }
4910             else {
4911 14           LibXML_reparent_removed_node(ret);
4912 14           RETVAL = PmmNodeToSv(ret, NULL);
4913             }
4914             OUTPUT:
4915             RETVAL
4916              
4917             void
4918             removeChildNodes( self )
4919             xmlNodePtr self
4920             PREINIT:
4921             xmlNodePtr elem, fragment;
4922             ProxyNodePtr docfrag;
4923             CODE:
4924 2           docfrag = PmmNewFragment( self->doc );
4925 2           fragment = PmmNODE( docfrag );
4926 2           elem = self->children;
4927 6 100         while ( elem ) {
4928 4           xmlNodePtr next = elem->next;
4929 4           xmlUnlinkNode( elem );
4930 4 50         if (elem->type == XML_ATTRIBUTE_NODE
4931 4 100         || elem->type == XML_DTD_NODE) {
4932 1 50         if (PmmPROXYNODE(elem) == NULL) {
4933 0           xmlFreeNode(elem);
4934             }
4935             }
4936             else {
4937             /* this following piece is the function of domAppendChild()
4938             * but in this special case we can avoid most of the logic of
4939             * that function.
4940             */
4941 3 100         if ( fragment->children != NULL ) {
4942             xs_warn("unlink node!\n");
4943 1           domAddNodeToList( elem, fragment->last, NULL );
4944             }
4945             else {
4946 2           fragment->children = elem;
4947 2           fragment->last = elem;
4948 2           elem->parent= fragment;
4949             }
4950 3           PmmFixOwnerNode( elem, docfrag );
4951             }
4952 4           elem = next;
4953             }
4954              
4955 2           self->children = self->last = NULL;
4956 2 50         if ( PmmREFCNT(docfrag) <= 0 ) {
4957             xs_warn( "have not references left" );
4958 2           PmmREFCNT_inc( docfrag );
4959 2           PmmREFCNT_dec( docfrag );
4960             }
4961              
4962             void
4963             unbindNode( self )
4964             xmlNodePtr self
4965             ALIAS:
4966             XML::LibXML::Node::unlink = 1
4967             XML::LibXML::Node::unlinkNode = 2
4968             PREINIT:
4969 10           ProxyNodePtr docfrag = NULL;
4970             CODE:
4971             PERL_UNUSED_VAR(ix);
4972 10 50         if ( self->type != XML_DOCUMENT_NODE
4973 10 50         && self->type != XML_DOCUMENT_FRAG_NODE ) {
4974 10           xmlUnlinkNode( self );
4975 10           LibXML_reparent_removed_node(self);
4976             }
4977              
4978             SV*
4979             appendChild( self, nNode )
4980             xmlNodePtr self
4981             xmlNodePtr nNode
4982             PREINIT:
4983             xmlNodePtr rNode;
4984             CODE:
4985 61 100         if (self->type == XML_DOCUMENT_NODE ) {
4986             /* NOT_SUPPORTED_ERR
4987             */
4988 3           switch ( nNode->type ) {
4989             case XML_ELEMENT_NODE:
4990 1           warn("Appending an element to a document node not supported yet!");
4991 1           XSRETURN_UNDEF;
4992             break;
4993             case XML_DOCUMENT_FRAG_NODE:
4994 0           warn("Appending a document fragment node to a document node not supported yet!");
4995 0           XSRETURN_UNDEF;
4996             break;
4997             case XML_TEXT_NODE:
4998             case XML_CDATA_SECTION_NODE:
4999 0           warn("Appending text node not supported on a document node yet!");
5000 0           XSRETURN_UNDEF;
5001             break;
5002             default:
5003 2           break;
5004             }
5005             }
5006              
5007 60           rNode = domAppendChild( self, nNode );
5008              
5009 59 50         if ( rNode == NULL ) {
5010 0           XSRETURN_UNDEF;
5011             }
5012              
5013 118 50         RETVAL = PmmNodeToSv( nNode,
5014 59 100         PmmOWNERPO(PmmPROXYNODE(self)) );
5015 59 100         if (nNode->type == XML_DTD_NODE) {
5016 1           LibXML_set_int_subset(self->doc, nNode);
5017             }
5018 59 50         PmmFixOwner( SvPROXYNODE(RETVAL), PmmPROXYNODE(self) );
5019             OUTPUT:
5020             RETVAL
5021              
5022             SV*
5023             addChild( self, nNode )
5024             xmlNodePtr self
5025             xmlNodePtr nNode
5026             PREINIT:
5027 39           xmlNodePtr retval = NULL;
5028             ProxyNodePtr proxy;
5029             CODE:
5030 39           switch ( nNode->type ) {
5031             case XML_DOCUMENT_FRAG_NODE:
5032 0           croak("Adding document fragments with addChild not supported!");
5033             XSRETURN_UNDEF;
5034             case XML_DOCUMENT_NODE :
5035             case XML_HTML_DOCUMENT_NODE :
5036             case XML_DOCB_DOCUMENT_NODE :
5037 0           croak("addChild: HIERARCHY_REQUEST_ERR\n");
5038             XSRETURN_UNDEF;
5039             case XML_NOTATION_NODE :
5040             case XML_NAMESPACE_DECL :
5041             case XML_DTD_NODE :
5042             case XML_DOCUMENT_TYPE_NODE :
5043             case XML_ENTITY_DECL :
5044             case XML_ELEMENT_DECL :
5045             case XML_ATTRIBUTE_DECL :
5046 0           croak("addChild: unsupported node type!");
5047             XSRETURN_UNDEF;
5048             default:
5049 39           break;
5050             }
5051              
5052 39           xmlUnlinkNode(nNode);
5053 39           proxy = PmmPROXYNODE(nNode);
5054 39           retval = xmlAddChild( self, nNode );
5055              
5056 39 50         if ( retval == NULL ) {
5057 0           croak( "Error: addChild failed (check node types)!\n" );
5058             }
5059              
5060 39 100         if ( retval != nNode ) {
5061             xs_warn( "node was lost during operation\n" );
5062 1           PmmNODE(proxy) = NULL;
5063             }
5064              
5065 78 50         RETVAL = PmmNodeToSv( retval,
5066 39 100         PmmOWNERPO(PmmPROXYNODE(self)) );
5067 39 100         if ( retval != self ) {
5068 38 50         PmmFixOwner( SvPROXYNODE(RETVAL), PmmPROXYNODE(self) );
5069             }
5070             OUTPUT:
5071             RETVAL
5072              
5073              
5074             SV*
5075             addSibling( self, nNode )
5076             xmlNodePtr self
5077             xmlNodePtr nNode
5078             PREINIT:
5079 6           xmlNodePtr ret = NULL;
5080 6           ProxyNodePtr owner = NULL;
5081             CODE:
5082 6 50         if ( nNode->type == XML_DOCUMENT_FRAG_NODE ) {
5083 0           croak("Adding document fragments with addSibling not yet supported!");
5084             XSRETURN_UNDEF;
5085             }
5086 6 50         owner = PmmOWNERPO(PmmPROXYNODE(self));
    50          
5087              
5088 6 100         if (self->type == XML_TEXT_NODE && nNode->type == XML_TEXT_NODE
    50          
5089 2 50         && self->name == nNode->name) {
5090             /* As a result of text merging, the added node may be freed. */
5091 1           xmlNodePtr copy = xmlCopyNode(nNode, 0);
5092 1           ret = xmlAddSibling(self, copy);
5093              
5094 1 50         if (ret) {
5095 1           RETVAL = PmmNodeToSv(ret, owner);
5096             /* Unlink original node. */
5097 1           xmlUnlinkNode(nNode);
5098 1           LibXML_reparent_removed_node(nNode);
5099             }
5100             else {
5101 0           xmlFreeNode(copy);
5102 0           XSRETURN_UNDEF;
5103             }
5104             }
5105             else {
5106 5           ret = xmlAddSibling( self, nNode );
5107              
5108 5 50         if ( ret ) {
5109 5           RETVAL = PmmNodeToSv(ret, owner);
5110 5 100         if (nNode->type == XML_DTD_NODE) {
5111 2           LibXML_set_int_subset(self->doc, nNode);
5112             }
5113 5 50         PmmFixOwner(SvPROXYNODE(RETVAL), owner);
5114             }
5115             else {
5116 0           XSRETURN_UNDEF;
5117             }
5118             }
5119             OUTPUT:
5120             RETVAL
5121              
5122             SV*
5123             cloneNode( self, deep=0 )
5124             xmlNodePtr self
5125             int deep
5126             PREINIT:
5127             xmlNodePtr ret;
5128 6           xmlDocPtr doc = NULL;
5129 6           ProxyNodePtr docfrag = NULL;
5130             CODE:
5131 6           ret = PmmCloneNode( self, deep );
5132 6 50         if ( ret == NULL ) {
5133 0           XSRETURN_UNDEF;
5134             }
5135              
5136 6 100         if ( ret->type == XML_DTD_NODE ) {
5137 1           RETVAL = PmmNodeToSv(ret, NULL);
5138             }
5139             else {
5140 5           doc = self->doc;
5141              
5142 5 50         if ( doc != NULL ) {
5143 5           xmlSetTreeDoc(ret, doc); /* setting to self, no need to clear psvi */
5144             }
5145              
5146 5           docfrag = PmmNewFragment( doc );
5147 5           xmlAddChild( PmmNODE(docfrag), ret );
5148 5           RETVAL = PmmNodeToSv(ret, docfrag);
5149             }
5150             OUTPUT:
5151             RETVAL
5152              
5153             int
5154             isSameNode( self, oNode )
5155             xmlNodePtr self
5156             xmlNodePtr oNode
5157             ALIAS:
5158             XML::LibXML::Node::isEqual = 1
5159             CODE:
5160             PERL_UNUSED_VAR(ix);
5161 152           RETVAL = ( self == oNode ) ? 1 : 0;
5162             OUTPUT:
5163             RETVAL
5164              
5165             IV
5166             unique_key( self )
5167             xmlNodePtr self
5168             CODE:
5169             /* Cast pointer to IV */
5170 50           RETVAL = PTR2IV(self);
5171             OUTPUT:
5172             RETVAL
5173              
5174             SV *
5175             baseURI( self )
5176             xmlNodePtr self
5177             PREINIT:
5178             xmlChar * uri;
5179             CODE:
5180 13           uri = xmlNodeGetBase( self->doc, self );
5181 13           RETVAL = C2Sv( uri, NULL );
5182 13           xmlFree( uri );
5183             OUTPUT:
5184             RETVAL
5185              
5186             void
5187             setBaseURI( self, URI )
5188             xmlNodePtr self
5189             SV * URI
5190             PREINIT:
5191             xmlChar * uri;
5192             CODE:
5193 7           uri = nodeSv2C( URI, self );
5194 7 50         if ( uri != NULL ) {
5195 7           xmlNodeSetBase( self, uri );
5196             }
5197              
5198             SV*
5199             toString( self, format=0, useDomEncoding = &PL_sv_undef )
5200             xmlNodePtr self
5201             SV * useDomEncoding
5202             int format
5203             ALIAS:
5204             XML::LibXML::Node::serialize = 1
5205             PREINIT:
5206             xmlBufferPtr buffer;
5207 156           const xmlChar *ret = NULL;
5208 156           SV* internalFlag = NULL;
5209 156           int oldTagFlag = xmlSaveNoEmptyTags;
5210             CODE:
5211             PERL_UNUSED_VAR(ix);
5212 156           internalFlag = get_sv("XML::LibXML::setTagCompression", 0);
5213              
5214 156 50         if ( internalFlag ) {
5215 156 50         xmlSaveNoEmptyTags = SvTRUE(internalFlag);
    50          
    0          
    50          
    0          
    0          
    50          
    0          
    0          
    0          
    0          
    0          
    50          
    50          
    100          
    50          
    0          
    100          
    0          
5216             }
5217 156           buffer = xmlBufferCreate();
5218              
5219 156 100         if ( format <= 0 ) {
5220 152           xmlNodeDump( buffer,
5221 152           self->doc,
5222             self, 0, format);
5223             }
5224             else {
5225 4           int t_indent_var = xmlIndentTreeOutput;
5226 4           xmlIndentTreeOutput = 1;
5227 4           xmlNodeDump( buffer,
5228 4           self->doc,
5229             self, 0, format);
5230 4           xmlIndentTreeOutput = t_indent_var;
5231             }
5232              
5233 156           ret = xmlBufferContent( buffer );
5234              
5235 156           xmlSaveNoEmptyTags = oldTagFlag;
5236              
5237 156 50         if ( ret != NULL ) {
5238 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          
5239 2           RETVAL = nodeC2Sv((xmlChar*)ret, PmmNODE(PmmPROXYNODE(self))) ;
5240 2           SvUTF8_off(RETVAL);
5241             }
5242             else {
5243 154           RETVAL = C2Sv((xmlChar*)ret, NULL) ;
5244             }
5245 156           xmlBufferFree( buffer );
5246             }
5247             else {
5248 0           xmlBufferFree( buffer );
5249             xs_warn("Failed to convert node to string");
5250 0           XSRETURN_UNDEF;
5251             }
5252             OUTPUT:
5253             RETVAL
5254              
5255              
5256             SV *
5257             _toStringC14N(self, comments=0, xpath=&PL_sv_undef, exclusive=0, inc_prefix_list=NULL, xpath_context)
5258             xmlNodePtr self
5259             int comments
5260             SV * xpath
5261             int exclusive
5262             char** inc_prefix_list
5263             SV * xpath_context
5264              
5265             PREINIT:
5266 24           xmlChar *result = NULL;
5267 24           xmlChar *nodepath = NULL;
5268 24           xmlXPathContextPtr child_ctxt = NULL;
5269 24           xmlXPathObjectPtr xpath_res = NULL;
5270 24           xmlNodeSetPtr nodelist = NULL;
5271 24           xmlNodePtr refNode = NULL;
5272 24           PREINIT_SAVED_ERROR
5273             INIT:
5274             /* due to how c14n is implemented, the nodeset it receives must
5275             include child nodes; ie, child nodes aren't assumed to be rendered.
5276             so we use an xpath expression to find all of the child nodes. */
5277              
5278 24 50         if ( self->doc == NULL ) {
5279 0           croak("Node passed to toStringC14N must be part of a document");
5280             }
5281              
5282 24           refNode = self;
5283             CODE:
5284 24 50         if ( xpath != NULL && xpath != &PL_sv_undef ) {
    100          
5285 11           nodepath = Sv2C( xpath, NULL );
5286             }
5287              
5288 24 100         if ( nodepath != NULL && xmlStrlen( nodepath ) == 0 ) {
    50          
5289 0           xmlFree( nodepath );
5290 0           nodepath = NULL;
5291             }
5292              
5293 24 100         if ( nodepath == NULL
5294 13 100         && self->type != XML_DOCUMENT_NODE
5295 3 50         && self->type != XML_HTML_DOCUMENT_NODE
5296 3 50         && self->type != XML_DOCB_DOCUMENT_NODE
5297             ) {
5298 3 50         if (comments)
5299 0           nodepath = xmlStrdup( (const xmlChar *) "(. | .//node() | .//@* | .//namespace::*)" );
5300             else
5301 3           nodepath = xmlStrdup( (const xmlChar *) "(. | .//node() | .//@* | .//namespace::*)[not(self::comment())]" );
5302             }
5303              
5304 24 100         if ( nodepath != NULL ) {
5305 14 100         if ( self->type == XML_DOCUMENT_NODE
5306 4 50         || self->type == XML_HTML_DOCUMENT_NODE
5307 4 50         || self->type == XML_DOCB_DOCUMENT_NODE ) {
5308 10           refNode = xmlDocGetRootElement( self->doc );
5309             }
5310 14 100         if (SvOK(xpath_context)) {
    50          
    50          
5311 2 50         child_ctxt = INT2PTR(xmlXPathContextPtr,SvIV(SvRV(xpath_context)));
5312 2 50         if ( child_ctxt == NULL ) {
5313 0           croak("XPathContext: missing xpath context\n");
5314             }
5315             } else {
5316 12           xpath_context = NULL;
5317 12           child_ctxt = xmlXPathNewContext(self->doc);
5318             }
5319 14 50         if (!child_ctxt) {
5320 0 0         if ( nodepath != NULL ) {
5321 0           xmlFree( nodepath );
5322             }
5323 0           croak("Failed to create xpath context");
5324             }
5325              
5326 14           child_ctxt->node = self;
5327 14           LibXML_configure_namespaces(child_ctxt);
5328              
5329 14           xpath_res = xmlXPathEval(nodepath, child_ctxt);
5330 14 100         if (child_ctxt->namespaces != NULL) {
5331 13           xmlFree( child_ctxt->namespaces );
5332 13           child_ctxt->namespaces = NULL;
5333             }
5334 14 100         if (!xpath_context) xmlXPathFreeContext(child_ctxt);
5335 14 50         if ( nodepath != NULL ) {
5336 14           xmlFree( nodepath );
5337             }
5338              
5339 14 50         if (xpath_res == NULL) {
5340 0           croak("2 Failed to compile xpath expression");
5341             }
5342              
5343 14           nodelist = xpath_res->nodesetval;
5344 14 50         if ( nodelist == NULL ) {
5345 0           xmlXPathFreeObject(xpath_res);
5346 0           croak( "cannot canonize empty nodeset!" );
5347             }
5348             }
5349              
5350 24           INIT_ERROR_HANDLER;
5351              
5352 24           xmlC14NDocDumpMemory( self->doc,
5353             nodelist,
5354             exclusive, (xmlChar **) inc_prefix_list,
5355             comments,
5356             &result );
5357              
5358 24 100         if ( xpath_res ) xmlXPathFreeObject(xpath_res);
5359 24           CLEANUP_ERROR_HANDLER;
5360 24           REPORT_ERROR(0);
5361              
5362 24 50         if (result == NULL) {
5363 0           croak("Failed to convert doc to string in doc->toStringC14N");
5364             } else {
5365 24           RETVAL = C2Sv( result, NULL );
5366 24           xmlFree(result);
5367             }
5368             OUTPUT:
5369             RETVAL
5370              
5371             SV*
5372             string_value ( self, useDomEncoding = &PL_sv_undef )
5373             xmlNodePtr self
5374             SV * useDomEncoding
5375             ALIAS:
5376             to_literal = 1
5377             textContent = 2
5378             PREINIT:
5379 100           xmlChar * string = NULL;
5380             CODE:
5381             PERL_UNUSED_VAR(ix);
5382             /* we can't just return a string, because of UTF8! */
5383 100           string = xmlXPathCastNodeToString(self);
5384 100 50         if ( SvTRUE(useDomEncoding) ) {
    50          
    0          
    100          
    50          
    50          
    50          
    0          
    0          
    0          
    0          
    0          
    50          
    50          
    50          
    0          
    0          
    50          
    0          
5385 1           RETVAL = nodeC2Sv(string,
5386             self);
5387             }
5388             else {
5389 99           RETVAL = C2Sv(string,
5390             NULL);
5391             }
5392 100           xmlFree(string);
5393             OUTPUT:
5394             RETVAL
5395              
5396             double
5397             to_number ( self )
5398             xmlNodePtr self
5399             CODE:
5400 0           RETVAL = xmlXPathCastNodeToNumber(self);
5401             OUTPUT:
5402             RETVAL
5403              
5404              
5405             void
5406             _find( pnode, pxpath, to_bool )
5407             SV* pnode
5408             SV * pxpath
5409             int to_bool
5410             PREINIT:
5411 54           xmlNodePtr node = PmmSvNode(pnode);
5412 54           ProxyNodePtr owner = NULL;
5413 54           xmlXPathObjectPtr found = NULL;
5414 54           xmlNodeSetPtr nodelist = NULL;
5415 54           xmlChar * xpath = NULL;
5416 54           xmlXPathCompExprPtr comp = NULL;
5417 54           PREINIT_SAVED_ERROR
5418             INIT:
5419 54 50         if ( node == NULL ) {
5420 0           croak( "lost node" );
5421             }
5422 54 100         if (sv_isobject(pxpath) && sv_isa(pxpath,"XML::LibXML::XPathExpression")) {
    50          
5423 3 50         comp = INT2PTR(xmlXPathCompExprPtr,SvIV((SV*)SvRV( pxpath )));
5424 3 50         if (!comp) XSRETURN_UNDEF;
5425             } else {
5426 51           xpath = nodeSv2C(pxpath, node);
5427 51 50         if ( !(xpath && xmlStrlen(xpath)) ) {
    50          
5428             xs_warn( "bad xpath\n" );
5429 0 0         if ( xpath )
5430 0           xmlFree(xpath);
5431 0           croak( "empty XPath found" );
5432             XSRETURN_UNDEF;
5433             }
5434             }
5435             PPCODE:
5436 54           INIT_ERROR_HANDLER;
5437 54 100         if (comp) {
5438 3           found = domXPathCompFind( node, comp, to_bool );
5439             } else {
5440 51           found = domXPathFind( node, xpath, to_bool );
5441 51           xmlFree( xpath );
5442             }
5443 54           CLEANUP_ERROR_HANDLER;
5444 54 100         if (found) {
5445 42           REPORT_ERROR(1);
5446 42           switch (found->type) {
5447             case XPATH_NODESET:
5448             /* return as a NodeList */
5449             /* access ->nodesetval */
5450 25 50         XPUSHs(sv_2mortal(newSVpv("XML::LibXML::NodeList", 0)));
5451 25           nodelist = found->nodesetval;
5452 25 50         if ( nodelist ) {
5453 25 50         if ( nodelist->nodeNr > 0 ) {
5454             int i;
5455 25           const char * cls = "XML::LibXML::Node";
5456             xmlNodePtr tnode;
5457             SV * element;
5458 25           int l = nodelist->nodeNr;
5459              
5460 25 50         owner = PmmOWNERPO(SvPROXYNODE(pnode));
    50          
    0          
    50          
    100          
    50          
    50          
5461 65 100         for( i=0 ; i < l; i++){
5462             /* we have to create a new instance of an
5463             * objectptr. and then
5464             * place the current node into the new
5465             * object. afterwards we can
5466             * push the object to the array!
5467             */
5468 40           tnode = nodelist->nodeTab[i];
5469              
5470             /* let's be paranoid */
5471 40 50         if (tnode->type == XML_NAMESPACE_DECL) {
5472 0           xmlNsPtr newns = xmlCopyNamespace((xmlNsPtr)tnode);
5473 0 0         if ( newns != NULL ) {
5474 0           element = NEWSV(0,0);
5475 0           cls = PmmNodeTypeName( tnode );
5476 0           element = sv_setref_pv( element,
5477             (const char *)cls,
5478             (void*)newns
5479             );
5480             }
5481             else {
5482 0           continue;
5483             }
5484             }
5485             else {
5486 40           element = PmmNodeToSv(tnode, owner);
5487             }
5488              
5489 40 50         XPUSHs( sv_2mortal(element) );
5490             }
5491             }
5492 25           xmlXPathFreeNodeSet( found->nodesetval );
5493 25           found->nodesetval = NULL;
5494             }
5495 25           break;
5496             case XPATH_BOOLEAN:
5497             /* return as a Boolean */
5498             /* access ->boolval */
5499 12 50         XPUSHs(sv_2mortal(newSVpv("XML::LibXML::Boolean", 0)));
5500 12 50         XPUSHs(sv_2mortal(newSViv(found->boolval)));
5501 12           break;
5502             case XPATH_NUMBER:
5503             /* return as a Number */
5504             /* access ->floatval */
5505 2 50         XPUSHs(sv_2mortal(newSVpv("XML::LibXML::Number", 0)));
5506 2 50         XPUSHs(sv_2mortal(newSVnv(found->floatval)));
5507 2           break;
5508             case XPATH_STRING:
5509             /* access ->stringval */
5510             /* return as a Literal */
5511 3 50         XPUSHs(sv_2mortal(newSVpv("XML::LibXML::Literal", 0)));
5512 3 50         XPUSHs(sv_2mortal(C2Sv(found->stringval, NULL)));
5513 3           break;
5514             default:
5515 0           croak("Unknown XPath return type");
5516             }
5517 42           xmlXPathFreeObject(found);
5518             } else {
5519 12           REPORT_ERROR(0);
5520             }
5521              
5522             void
5523             _findnodes( pnode, perl_xpath )
5524             SV* pnode
5525             SV * perl_xpath
5526             PREINIT:
5527 95           xmlNodePtr node = PmmSvNode(pnode);
5528 95           ProxyNodePtr owner = NULL;
5529 95           xmlNodeSetPtr nodelist = NULL;
5530 95           SV * element = NULL ;
5531 95           xmlChar * xpath = NULL ;
5532 95           xmlXPathCompExprPtr comp = NULL;
5533 95           PREINIT_SAVED_ERROR
5534             INIT:
5535 95 50         if ( node == NULL ) {
5536 0 0         if ( xpath )
5537 0           xmlFree(xpath);
5538 0           croak( "lost node" );
5539             }
5540 95 100         if (sv_isobject(perl_xpath) && sv_isa(perl_xpath,"XML::LibXML::XPathExpression")) {
    50          
5541 3 50         comp = INT2PTR(xmlXPathCompExprPtr,SvIV((SV*)SvRV( perl_xpath )));
5542 3 50         if (!comp) XSRETURN_UNDEF;
5543             } else {
5544 92           xpath = nodeSv2C(perl_xpath, node);
5545 92 50         if ( !(xpath && xmlStrlen(xpath)) ) {
    50          
5546             xs_warn( "bad xpath\n" );
5547 0 0         if ( xpath )
5548 0           xmlFree(xpath);
5549 0           croak( "empty XPath found" );
5550             XSRETURN_UNDEF;
5551             }
5552             }
5553             PPCODE:
5554 95           INIT_ERROR_HANDLER;
5555 95 100         if (comp) {
5556 3           nodelist = domXPathCompSelect( node, comp );
5557             } else {
5558 92           nodelist = domXPathSelect( node, xpath );
5559 92           xmlFree(xpath);
5560             }
5561 95           CLEANUP_ERROR_HANDLER;
5562              
5563 95 100         if ( nodelist ) {
5564 87           REPORT_ERROR(1);
5565 87 100         if ( nodelist->nodeNr > 0 ) {
5566             int i;
5567 81           int len = nodelist->nodeNr;
5568 81           const char * cls = "XML::LibXML::Node";
5569             xmlNodePtr tnode;
5570 81 50         owner = PmmOWNERPO(SvPROXYNODE(pnode));
    50          
    0          
    50          
    100          
    50          
    50          
5571              
5572 6280 100         for(i=0 ; i < len; i++){
5573             /* we have to create a new instance of an objectptr.
5574             * and then place the current node into the new object.
5575             * afterwards we can push the object to the array!
5576             */
5577 6199           element = NULL;
5578 6199           tnode = nodelist->nodeTab[i];
5579 6199 100         if (tnode->type == XML_NAMESPACE_DECL) {
5580 3           xmlNsPtr newns = xmlCopyNamespace((xmlNsPtr)tnode);
5581 3 100         if ( newns != NULL ) {
5582 2           element = NEWSV(0,0);
5583 2           cls = PmmNodeTypeName( tnode );
5584 2           element = sv_setref_pv( element,
5585             (const char *)cls,
5586             newns
5587             );
5588             }
5589             else {
5590 3           continue;
5591             }
5592             }
5593             else {
5594 6196           element = PmmNodeToSv(tnode, owner);
5595             }
5596              
5597 6198 100         XPUSHs( sv_2mortal(element) );
5598             }
5599             }
5600 87           xmlXPathFreeNodeSet( nodelist );
5601             } else {
5602 8           REPORT_ERROR(0);
5603             }
5604              
5605             void
5606             getNamespaces( pnode )
5607             SV * pnode
5608             ALIAS:
5609             namespaces = 1
5610             PREINIT:
5611             xmlNodePtr node;
5612 37           xmlNsPtr ns = NULL;
5613 37           xmlNsPtr newns = NULL;
5614 37           SV* element = &PL_sv_undef;
5615 37           const char * class = "XML::LibXML::Namespace";
5616             INIT:
5617             PERL_UNUSED_VAR(ix);
5618 37           node = PmmSvNode(pnode);
5619 37 50         if ( node == NULL ) {
5620 0           croak( "lost node" );
5621             }
5622             PPCODE:
5623 37 50         if (node->type == XML_ELEMENT_NODE) {
5624 37           ns = node->nsDef;
5625 42 100         while ( ns != NULL ) {
5626 5 100         if (ns->prefix != NULL || ns->href != NULL) {
    50          
5627 5           newns = xmlCopyNamespace(ns);
5628 5 50         if ( newns != NULL ) {
5629 5           element = NEWSV(0,0);
5630 5           element = sv_setref_pv( element,
5631             (const char *)class,
5632             (void*)newns
5633             );
5634 5 50         XPUSHs( sv_2mortal(element) );
5635             }
5636             }
5637 5           ns = ns->next;
5638             }
5639             }
5640              
5641             SV *
5642             getNamespace( node )
5643             xmlNodePtr node
5644             ALIAS:
5645             localNamespace = 1
5646             localNS = 2
5647             PREINIT:
5648 1           xmlNsPtr ns = NULL;
5649 1           xmlNsPtr newns = NULL;
5650 1           const char * class = "XML::LibXML::Namespace";
5651             CODE:
5652             PERL_UNUSED_VAR(ix);
5653 1 50         if ( node->type == XML_ELEMENT_NODE
5654 0 0         || node->type == XML_ATTRIBUTE_NODE
5655 0 0         || node->type == XML_PI_NODE ) {
5656 1           ns = node->ns;
5657 2 50         if ( ns != NULL ) {
5658 1           newns = xmlCopyNamespace(ns);
5659 1 50         if ( newns != NULL ) {
5660 1           RETVAL = NEWSV(0,0);
5661 1           RETVAL = sv_setref_pv( RETVAL,
5662             (const char *)class,
5663             (void*)newns
5664             );
5665             } else {
5666 0           XSRETURN_UNDEF;
5667             }
5668             }
5669             else {
5670 0           XSRETURN_UNDEF;
5671             }
5672             } else {
5673 0           XSRETURN_UNDEF;
5674             }
5675             OUTPUT:
5676             RETVAL
5677              
5678              
5679             SV *
5680             nodePath( self )
5681             xmlNodePtr self
5682             PREINIT:
5683 3           xmlChar * path = NULL;
5684             CODE:
5685 3           path = xmlGetNodePath( self );
5686 3 50         if ( path == NULL ) {
5687 0           croak( "cannot calculate path for the given node" );
5688             }
5689 3           RETVAL = C2Sv( path, NULL );
5690 3           xmlFree(path);
5691             OUTPUT:
5692             RETVAL
5693              
5694             int
5695             line_number( self )
5696             xmlNodePtr self
5697             CODE:
5698 5           RETVAL = xmlGetLineNo( self );
5699             OUTPUT:
5700             RETVAL
5701              
5702             MODULE = XML::LibXML PACKAGE = XML::LibXML::Element
5703              
5704             SV*
5705             new(CLASS, name )
5706             char * name
5707             PREINIT:
5708             xmlNodePtr newNode;
5709 13           ProxyNodePtr docfrag = NULL;
5710             CODE:
5711 13           docfrag = PmmNewFragment(NULL);
5712 13           newNode = xmlNewNode( NULL, (const xmlChar*)name );
5713 13           newNode->doc = NULL;
5714 13           xmlAddChild(PmmNODE(docfrag), newNode);
5715 13           RETVAL = PmmNodeToSv(newNode, docfrag );
5716             OUTPUT:
5717             RETVAL
5718              
5719             int
5720             _setNamespace(self, namespaceURI, namespacePrefix = &PL_sv_undef, flag = 1 )
5721             SV * self
5722             SV * namespaceURI
5723             SV * namespacePrefix
5724             int flag
5725             PREINIT:
5726 33           xmlNodePtr node = PmmSvNode(self);
5727 33           xmlChar * nsURI = nodeSv2C(namespaceURI,node);
5728 33           xmlChar * nsPrefix = NULL;
5729 33           xmlNsPtr ns = NULL;
5730             INIT:
5731 33 50         if ( node == NULL ) {
5732 0           croak( "lost node" );
5733             }
5734             CODE:
5735             /* if ( !nsURI ){
5736             XSRETURN_UNDEF;
5737             } */
5738              
5739 33           nsPrefix = nodeSv2C(namespacePrefix, node);
5740 33 100         if ( xmlStrlen( nsPrefix ) == 0 ) {
5741 1           xmlFree(nsPrefix);
5742 1           nsPrefix = NULL;
5743             }
5744 33 100         if ( xmlStrlen( nsURI ) == 0 ) {
5745 1           xmlFree(nsURI);
5746 1           nsURI = NULL;
5747             }
5748 33 100         if ( nsPrefix == NULL && nsURI == NULL ) {
    50          
5749             /* special case: empty namespace */
5750 2 50         if ( (ns = xmlSearchNs(node->doc, node, NULL)) &&
    0          
5751 0 0         ( ns->href && xmlStrlen( ns->href ) != 0 ) ) {
5752             /* won't take it */
5753 0           RETVAL = 0;
5754 1 50         } else if ( flag ) {
5755             /* no namespace */
5756 1           xmlSetNs(node, NULL);
5757 1           RETVAL = 1;
5758             } else {
5759 0           RETVAL = 0;
5760             }
5761             }
5762 32 100         else if ( flag && (ns = xmlSearchNs(node->doc, node, nsPrefix)) ) {
    100          
5763             /* user just wants to set the namespace for the node */
5764             /* try to reuse an existing declaration for the prefix */
5765 2 50         if ( xmlStrEqual( ns->href, nsURI ) ) {
5766 1           RETVAL = 1;
5767             }
5768 0 0         else if ( (ns = xmlNewNs( node, nsURI, nsPrefix )) ) {
5769 0           RETVAL = 1;
5770             }
5771             else {
5772 0           RETVAL = 0;
5773             }
5774             }
5775 31 50         else if ( (ns = xmlNewNs( node, nsURI, nsPrefix )) )
5776 31           RETVAL = 1;
5777             else
5778 0           RETVAL = 0;
5779              
5780 33 100         if ( flag && ns ) {
    100          
5781 4           xmlSetNs(node, ns);
5782             }
5783 33 100         if ( nsPrefix ) xmlFree(nsPrefix);
5784 33 100         if ( nsURI ) xmlFree(nsURI);
5785             OUTPUT:
5786             RETVAL
5787              
5788             int
5789             setNamespaceDeclURI( self, svprefix, newURI )
5790             xmlNodePtr self
5791             SV * svprefix
5792             SV * newURI
5793             PREINIT:
5794 15           xmlChar * prefix = NULL;
5795 15           xmlChar * nsURI = NULL;
5796             xmlNsPtr ns;
5797             CODE:
5798 15           RETVAL = 0;
5799 15           prefix = nodeSv2C( svprefix , self );
5800 15           nsURI = nodeSv2C( newURI , self );
5801             /* null empty values */
5802 15 50         if ( prefix && xmlStrlen(prefix) == 0) {
    100          
5803 3           xmlFree( prefix );
5804 3           prefix = NULL;
5805             }
5806 15 100         if ( nsURI && xmlStrlen(nsURI) == 0) {
    50          
5807 0           xmlFree( nsURI );
5808 0           nsURI = NULL;
5809             }
5810 15           ns = self->nsDef;
5811 28 100         while ( ns ) {
5812 39 100         if ((ns->prefix || ns->href ) &&
5813 19           ( xmlStrcmp( ns->prefix, prefix ) == 0 )) {
5814 7 50         if (ns->href) xmlFree((char*)ns->href);
5815 7           ns->href = nsURI;
5816 7 100         if ( nsURI == NULL ) {
5817 3           domRemoveNsRefs( self, ns );
5818             } else
5819 4           nsURI = NULL; /* do not free it */
5820 7           RETVAL = 1;
5821 7           break;
5822             } else {
5823 13           ns = ns->next;
5824             }
5825             }
5826 15 100         if ( prefix ) xmlFree( prefix );
5827 15 100         if ( nsURI ) xmlFree( nsURI );
5828             OUTPUT:
5829             RETVAL
5830              
5831             int
5832             setNamespaceDeclPrefix( self, svprefix, newPrefix )
5833             xmlNodePtr self
5834             SV * svprefix
5835             SV * newPrefix
5836             PREINIT:
5837 6           xmlChar * prefix = NULL;
5838 6           xmlChar * nsPrefix = NULL;
5839             xmlNsPtr ns;
5840             CODE:
5841 6           RETVAL = 0;
5842 6           prefix = nodeSv2C( svprefix , self );
5843 6           nsPrefix = nodeSv2C( newPrefix , self );
5844             /* null empty values */
5845 6 50         if ( prefix != NULL && xmlStrlen(prefix) == 0) {
    100          
5846 1           xmlFree( prefix );
5847 1           prefix = NULL;
5848             }
5849 6 100         if ( nsPrefix != NULL && xmlStrlen(nsPrefix) == 0) {
    100          
5850 2           xmlFree( nsPrefix );
5851 2           nsPrefix = NULL;
5852             }
5853 6 50         if ( xmlStrcmp( prefix, nsPrefix ) == 0 ) {
5854 0           RETVAL = 1;
5855             } else {
5856             /* check that new prefix is not in scope */
5857 6           ns = xmlSearchNs( self->doc, self, nsPrefix );
5858 6 100         if ( ns != NULL ) {
5859 2 100         if (nsPrefix != NULL) xmlFree( nsPrefix );
5860 2 50         if (prefix != NULL) xmlFree( prefix );
5861 2           croak("setNamespaceDeclPrefix: prefix '%s' is in use", ns->prefix);
5862             }
5863             /* lookup the declaration */
5864 4           ns = self->nsDef;
5865 7 50         while ( ns != NULL ) {
5866 13 100         if ((ns->prefix != NULL || ns->href != NULL) &&
5867 6           xmlStrcmp( ns->prefix, prefix ) == 0 ) {
5868 4 100         if ( ns->href == NULL && nsPrefix != NULL ) {
    50          
5869             /* xmlns:foo="" - no go */
5870 0 0         if ( prefix != NULL) xmlFree(prefix);
5871 0           croak("setNamespaceDeclPrefix: cannot set non-empty prefix for empty namespace");
5872             }
5873 4 100         if ( ns->prefix != NULL )
5874 3           xmlFree( (xmlChar*)ns->prefix );
5875 4           ns->prefix = nsPrefix;
5876 4           nsPrefix = NULL; /* do not free it */
5877 4           RETVAL = 1;
5878 4           break;
5879             } else {
5880 3           ns = ns->next;
5881             }
5882             }
5883             }
5884 4 50         if ( nsPrefix != NULL ) xmlFree(nsPrefix);
5885 4 100         if ( prefix != NULL) xmlFree(prefix);
5886             OUTPUT:
5887             RETVAL
5888              
5889              
5890             SV*
5891             _getNamespaceDeclURI( self, ns_prefix )
5892             xmlNodePtr self
5893             SV * ns_prefix
5894             PREINIT:
5895             xmlChar * prefix;
5896             xmlNsPtr ns;
5897             CODE:
5898 22           prefix = nodeSv2C(ns_prefix, self );
5899 22 100         if ( prefix != NULL && xmlStrlen(prefix) == 0) {
    100          
5900 3           xmlFree( prefix );
5901 3           prefix = NULL;
5902             }
5903 22           RETVAL = &PL_sv_undef;
5904 22           ns = self->nsDef;
5905 33 100         while ( ns != NULL ) {
5906 48 100         if ( (ns->prefix != NULL || ns->href != NULL) &&
5907 24           xmlStrcmp( ns->prefix, prefix ) == 0 ) {
5908 13           RETVAL = C2Sv(ns->href, NULL);
5909 13           break;
5910             } else {
5911 11           ns = ns->next;
5912             }
5913             }
5914 22 100         if ( prefix != NULL ) {
5915 18           xmlFree( prefix );
5916             }
5917              
5918             OUTPUT:
5919             RETVAL
5920              
5921             int
5922             hasAttribute( self, attr_name )
5923             xmlNodePtr self
5924             SV * attr_name
5925             PREINIT:
5926             xmlChar * name;
5927             CODE:
5928 16           name = nodeSv2C(attr_name, self );
5929 16 50         if ( ! name ) {
5930 0           XSRETURN_UNDEF;
5931             }
5932 16 100         if ( domGetAttrNode( self, name ) ) {
5933 9           RETVAL = 1;
5934             }
5935             else {
5936 7           RETVAL = 0;
5937             }
5938 16           xmlFree(name);
5939             OUTPUT:
5940             RETVAL
5941              
5942             int
5943             hasAttributeNS( self, namespaceURI, attr_name )
5944             xmlNodePtr self
5945             SV * namespaceURI
5946             SV * attr_name
5947             PREINIT:
5948             xmlChar * name;
5949             xmlChar * nsURI;
5950             xmlNodePtr attr;
5951             CODE:
5952 16           name = nodeSv2C(attr_name, self );
5953 16           nsURI = nodeSv2C(namespaceURI, self );
5954              
5955 16 50         if ( name == NULL ) {
5956 0 0         if ( nsURI != NULL ) {
5957 0           xmlFree(nsURI);
5958             }
5959 0           XSRETURN_UNDEF;
5960             }
5961 16 100         if ( nsURI != NULL && xmlStrlen(nsURI) == 0 ){
    100          
5962 2           xmlFree(nsURI);
5963 2           nsURI = NULL;
5964             }
5965 16           attr = (xmlNodePtr) xmlHasNsProp( self, name, nsURI );
5966 16 100         if ( attr && attr->type == XML_ATTRIBUTE_NODE ) {
    100          
5967 8           RETVAL = 1;
5968             }
5969             else {
5970 8           RETVAL = 0;
5971             }
5972              
5973 16           xmlFree(name);
5974 16 100         if ( nsURI != NULL ){
5975 12           xmlFree(nsURI);
5976             }
5977             OUTPUT:
5978             RETVAL
5979              
5980             SV*
5981             _getAttribute( self, attr_name, useDomEncoding = 0 )
5982             xmlNodePtr self
5983             SV * attr_name
5984             int useDomEncoding
5985             PREINIT:
5986             xmlChar * name;
5987 46           xmlChar * prefix = NULL;
5988 46           xmlChar * localname = NULL;
5989 46           xmlChar * ret = NULL;
5990 46           xmlNsPtr ns = NULL;
5991             CODE:
5992 46           name = nodeSv2C(attr_name, self );
5993 46 50         if( !name ) {
5994 0           XSRETURN_UNDEF;
5995             }
5996              
5997 46           ret = xmlGetNoNsProp(self, name);
5998 46 100         if ( ret == NULL ) {
5999 7           localname = xmlSplitQName2(name, &prefix);
6000 7 50         if ( localname != NULL ) {
6001 7           ns = xmlSearchNs( self->doc, self, prefix );
6002 7 50         if ( ns != NULL ) {
6003 7           ret = xmlGetNsProp(self, localname, ns->href);
6004             }
6005 7 50         if ( prefix != NULL) {
6006 7           xmlFree( prefix );
6007             }
6008 7           xmlFree( localname );
6009             }
6010             }
6011 46           xmlFree(name);
6012 46 50         if ( ret ) {
6013 46 100         if ( useDomEncoding ) {
6014 9           RETVAL = nodeC2Sv(ret, self);
6015             }
6016             else {
6017 37           RETVAL = C2Sv(ret, NULL);
6018             }
6019 46           xmlFree( ret );
6020             }
6021             else {
6022 0           XSRETURN_UNDEF;
6023             }
6024              
6025             OUTPUT:
6026             RETVAL
6027              
6028             void
6029             _setAttribute( self, attr_name, attr_value )
6030             xmlNodePtr self
6031             SV * attr_name
6032             SV * attr_value
6033             PREINIT:
6034 28           xmlChar * name = NULL;
6035 28           xmlChar * value = NULL;
6036             #if LIBXML_VERSION < 20621
6037             xmlChar * prefix = NULL;
6038             xmlChar * localname = NULL;
6039             #endif
6040             CODE:
6041 28           name = nodeSv2C(attr_name, self );
6042              
6043 28 100         if ( !LibXML_test_node_name(name) ) {
6044 4           xmlFree(name);
6045 4           croak( "bad name" );
6046             }
6047 24           value = nodeSv2C(attr_value, self );
6048             #if LIBXML_VERSION >= 20621
6049             /*
6050             * For libxml2-2.6.21 and later we can use just xmlSetProp
6051             */
6052 24           xmlSetProp(self,name,value);
6053             #else
6054             /*
6055             * but xmlSetProp does not work correctly for older libxml2 versions
6056             * The following is copied from libxml2 source
6057             * with xmlSplitQName3 replaced by xmlSplitQName2 for compatibility
6058             * with older libxml2 versions
6059             */
6060             localname = xmlSplitQName2(name, &prefix);
6061             if (localname != NULL) {
6062             xmlNsPtr ns;
6063             ns = xmlSearchNs(self->doc, self, prefix);
6064             if (prefix != NULL)
6065             xmlFree(prefix);
6066             if (ns != NULL)
6067             xmlSetNsProp(self, ns, localname, value);
6068             else
6069             xmlSetNsProp(self, NULL, name, value);
6070             xmlFree(localname);
6071             } else {
6072             xmlSetNsProp(self, NULL, name, value);
6073             }
6074             #endif
6075 24           xmlFree(name);
6076 24           xmlFree(value);
6077              
6078              
6079             void
6080             removeAttribute( self, attr_name )
6081             xmlNodePtr self
6082             SV * attr_name
6083             PREINIT:
6084             xmlChar * name;
6085 4           xmlAttrPtr xattr = NULL;
6086             CODE:
6087 4           name = nodeSv2C(attr_name, self );
6088 4 50         if ( name ) {
6089 4           xattr = domGetAttrNode( self, name );
6090              
6091 4 50         if ( xattr ) {
6092 4           xmlUnlinkNode((xmlNodePtr)xattr);
6093 4 100         if ( xattr->_private ) {
6094 1           PmmFixOwner((ProxyNodePtr)xattr->_private, NULL);
6095             }
6096             else {
6097 3           xmlFreeProp(xattr);
6098             }
6099             }
6100 4           xmlFree(name);
6101             }
6102              
6103             SV*
6104             getAttributeNode( self, attr_name )
6105             xmlNodePtr self
6106             SV * attr_name
6107             PREINIT:
6108             xmlChar * name;
6109 45           xmlAttrPtr ret = NULL;
6110             CODE:
6111 45           name = nodeSv2C(attr_name, self );
6112 45 50         if ( !name ) {
6113 0           XSRETURN_UNDEF;
6114             }
6115              
6116 45           ret = domGetAttrNode( self, name );
6117 45           xmlFree(name);
6118 45 100         if ( ret ) {
6119 60 50         RETVAL = PmmNodeToSv( (xmlNodePtr)ret,
6120 30 50         PmmOWNERPO(PmmPROXYNODE(self)) );
6121             }
6122             else {
6123 15           XSRETURN_UNDEF;
6124             }
6125             OUTPUT:
6126             RETVAL
6127              
6128             SV *
6129             setAttributeNode( self, attr_node )
6130             xmlNodePtr self
6131             SV * attr_node
6132             PREINIT:
6133 1           xmlAttrPtr attr = (xmlAttrPtr)PmmSvNode( attr_node );
6134 1           xmlAttrPtr ret = NULL;
6135             INIT:
6136 1 50         if ( attr == NULL ) {
6137 0           croak( "lost attribute" );
6138             }
6139             CODE:
6140 1 50         if ( attr != NULL && attr->type != XML_ATTRIBUTE_NODE ) {
    50          
6141 0           XSRETURN_UNDEF;
6142             }
6143 1 50         if ( attr->doc != self->doc ) {
6144 0           domImportNode( self->doc, (xmlNodePtr)attr, 1, 1);
6145             }
6146 1           ret = domGetAttrNode( self, attr->name );
6147 1 50         if ( ret != NULL ) {
6148 0 0         if ( ret != attr ) {
6149 0           xmlReplaceNode( (xmlNodePtr)ret, (xmlNodePtr)attr );
6150             }
6151             else {
6152 0           XSRETURN_UNDEF;
6153             }
6154             }
6155             else {
6156 1           xmlAddChild( self, (xmlNodePtr)attr );
6157             }
6158              
6159 1 50         if ( attr->_private != NULL ) {
6160 1 50         PmmFixOwner( SvPROXYNODE(attr_node), PmmPROXYNODE(self) );
6161             }
6162              
6163 1 50         if ( ret == NULL ) {
6164 1           XSRETURN_UNDEF;
6165             }
6166              
6167 0           RETVAL = PmmNodeToSv( (xmlNodePtr)ret, NULL );
6168 0 0         PmmFixOwner( SvPROXYNODE(RETVAL), NULL );
6169             OUTPUT:
6170             RETVAL
6171              
6172             SV *
6173             _getAttributeNS( self, namespaceURI, attr_name, useDomEncoding = 0 )
6174             xmlNodePtr self
6175             SV * namespaceURI
6176             SV * attr_name
6177             int useDomEncoding
6178             PREINIT:
6179             xmlChar * name;
6180             xmlChar * nsURI;
6181 22           xmlChar * ret = NULL;
6182             CODE:
6183 22           name = nodeSv2C( attr_name, self );
6184 22           nsURI = nodeSv2C( namespaceURI, self );
6185 22 50         if ( !name ) {
6186 0           xmlFree(nsURI);
6187 0           XSRETURN_UNDEF;
6188             }
6189 22 100         if ( nsURI && xmlStrlen(nsURI) ) {
    100          
6190 20           ret = xmlGetNsProp( self, name, nsURI );
6191             }
6192             else {
6193 2           ret = xmlGetProp( self, name );
6194             }
6195              
6196 22           xmlFree( name );
6197 22 100         if ( nsURI ) {
6198 21           xmlFree( nsURI );
6199             }
6200 22 50         if ( ret ) {
6201 22 50         if (useDomEncoding) {
6202 0           RETVAL = nodeC2Sv( ret, self );
6203             } else {
6204 22           RETVAL = C2Sv( ret, NULL );
6205             }
6206 22           xmlFree( ret );
6207             }
6208             else {
6209 0           XSRETURN_UNDEF;
6210             }
6211             OUTPUT:
6212             RETVAL
6213              
6214             void
6215             _setAttributeNS( self, namespaceURI, attr_name, attr_value )
6216             xmlNodePtr self
6217             SV * namespaceURI
6218             SV * attr_name
6219             SV * attr_value
6220             PREINIT:
6221             xmlChar * nsURI;
6222 48           xmlChar * name = NULL;
6223 48           xmlChar * value = NULL;
6224 48           xmlNsPtr ns = NULL;
6225 48           xmlChar * localname = NULL;
6226 48           xmlChar * prefix = NULL;
6227 48           xmlNsPtr * all_ns = NULL;
6228             int i;
6229             INIT:
6230 48           name = nodeSv2C( attr_name, self );
6231              
6232 48 100         if ( !LibXML_test_node_name(name) ) {
6233 3           xmlFree(name);
6234 3           croak( "bad name" );
6235             }
6236              
6237 45           nsURI = nodeSv2C( namespaceURI, self );
6238 45           localname = xmlSplitQName2(name, &prefix);
6239 45 100         if ( localname ) {
6240 21           xmlFree( name );
6241 21           name = localname;
6242             }
6243             CODE:
6244 45           value = nodeSv2C( attr_value, self );
6245              
6246 45 100         if ( nsURI && xmlStrlen(nsURI) ) {
    100          
6247             xs_warn( "found uri" );
6248              
6249 24           ns = xmlSearchNsByHref( self->doc, self, nsURI );
6250              
6251             /*
6252             * check for any prefixed namespaces occluded by a default namespace
6253             * because xmlSearchNsByHref will return default namespaces unless
6254             * you are searching on an attribute node, which may not exist yet
6255             */
6256 24 100         if ( ns && !ns->prefix )
    100          
6257             {
6258 4           all_ns = xmlGetNsList(self->doc, self);
6259 4 50         if ( all_ns )
6260             {
6261 4           i = 0;
6262 4           ns = all_ns[i];
6263 14 100         while ( ns )
6264             {
6265 13 100         if ( ns->prefix && xmlStrEqual(ns->href, nsURI) )
    100          
6266             {
6267 3           break;
6268             }
6269 10           ns = all_ns[i++];
6270             }
6271 4           xmlFree(all_ns);
6272             }
6273             }
6274              
6275 24 100         if ( !ns ) {
6276             /* create new ns */
6277 5 50         if ( prefix && xmlStrlen( prefix ) ) {
    50          
6278 5           ns = xmlNewNs(self, nsURI , prefix);
6279             }
6280             else {
6281 0           ns = NULL;
6282             }
6283             }
6284             }
6285              
6286 45 100         if ( nsURI && xmlStrlen(nsURI) && !ns ) {
    100          
    50          
6287 0 0         if ( prefix ) xmlFree( prefix );
6288 0 0         if ( nsURI ) xmlFree( nsURI );
6289 0           xmlFree( name );
6290 0           xmlFree( value );
6291 0           croak( "bad ns attribute!" );
6292             }
6293             else {
6294             /* warn( "set attribute %s->%s", name, value ); */
6295 45           xmlSetNsProp( self, ns, name, value );
6296             }
6297              
6298 45 100         if ( prefix ) {
6299 21           xmlFree( prefix );
6300             }
6301 45 100         if ( nsURI ) {
6302 44           xmlFree( nsURI );
6303             }
6304 45           xmlFree( name );
6305 45           xmlFree( value );
6306              
6307             void
6308             removeAttributeNS( self, namespaceURI, attr_name )
6309             xmlNodePtr self
6310             SV * namespaceURI
6311             SV * attr_name
6312             PREINIT:
6313             xmlChar * nsURI;
6314 3           xmlChar * name = NULL;
6315 3           xmlAttrPtr xattr = NULL;
6316             CODE:
6317 3           nsURI = nodeSv2C( namespaceURI, self );
6318 3           name = nodeSv2C( attr_name, self );
6319 3 50         if ( ! name ) {
6320 0           xmlFree(nsURI);
6321 0           XSRETURN_UNDEF;
6322             }
6323              
6324 3 50         if ( nsURI && xmlStrlen(nsURI) ) {
    100          
6325 2           xattr = xmlHasNsProp( self, name, nsURI );
6326             }
6327             else {
6328 1           xattr = xmlHasNsProp( self, name, NULL );
6329             }
6330 3 50         if ( xattr && xattr->type == XML_ATTRIBUTE_NODE ) {
    50          
6331 3           xmlUnlinkNode((xmlNodePtr)xattr);
6332 3 100         if ( xattr->_private ) {
6333 2           PmmFixOwner((ProxyNodePtr)xattr->_private, NULL);
6334             }
6335             else {
6336 1           xmlFreeProp(xattr);
6337             }
6338             }
6339 3           xmlFree(nsURI);
6340 3           xmlFree( name );
6341              
6342              
6343             SV*
6344             getAttributeNodeNS( self,namespaceURI, attr_name )
6345             xmlNodePtr self
6346             SV * namespaceURI
6347             SV * attr_name
6348             PREINIT:
6349             xmlChar * nsURI;
6350             xmlChar * name;
6351 33           xmlAttrPtr ret = NULL;
6352             CODE:
6353 33           nsURI = nodeSv2C(namespaceURI, self );
6354 33           name = nodeSv2C(attr_name, self );
6355 33 50         if ( !name ) {
6356 0           xmlFree(nsURI);
6357 0           XSRETURN_UNDEF;
6358             }
6359 33 100         if ( nsURI && xmlStrlen(nsURI) ) {
    50          
6360 20           ret = xmlHasNsProp( self, name, nsURI );
6361             }
6362             else {
6363 13           ret = xmlHasNsProp( self, name, NULL );
6364             }
6365 33           xmlFree(name);
6366 33 100         if ( nsURI ) {
6367 20           xmlFree(nsURI);
6368             }
6369 33 100         if ( ret &&
    100          
6370 18           ret->type == XML_ATTRIBUTE_NODE /* we don't want fixed attribute decls */
6371             ) {
6372 24 50         RETVAL = PmmNodeToSv( (xmlNodePtr)ret,
6373 12 50         PmmOWNERPO(PmmPROXYNODE(self)) );
6374             }
6375             else {
6376             /* warn("no prop\n"); */
6377 21           XSRETURN_UNDEF;
6378             }
6379             OUTPUT:
6380             RETVAL
6381              
6382             SV *
6383             setAttributeNodeNS( self, attr_node )
6384             xmlNodePtr self
6385             SV * attr_node
6386             PREINIT:
6387 4           xmlAttrPtr attr = (xmlAttrPtr)PmmSvNode( attr_node );
6388 4           xmlNsPtr ns = NULL;
6389 4           xmlAttrPtr ret = NULL;
6390             INIT:
6391 4 50         if ( attr == NULL ) {
6392 0           croak( "lost attribute node" );
6393             }
6394             CODE:
6395 4 50         if ( attr->type != XML_ATTRIBUTE_NODE ) {
6396 0           XSRETURN_UNDEF;
6397             }
6398              
6399 4 100         if ( attr->doc != self->doc ) {
6400 1           domImportNode( self->doc, (xmlNodePtr)attr, 1,1);
6401             }
6402              
6403              
6404 4           ns = attr->ns;
6405 4 50         if ( ns != NULL ) {
6406 4           ret = xmlHasNsProp( self, ns->href, attr->name );
6407             }
6408             else {
6409 0           ret = xmlHasNsProp( self, NULL, attr->name );
6410             }
6411              
6412 4 50         if ( ret && ret->type == XML_ATTRIBUTE_NODE ) {
    0          
6413 0 0         if ( ret != attr ) {
6414 0           xmlReplaceNode( (xmlNodePtr)ret, (xmlNodePtr)attr );
6415             }
6416             else {
6417 0           XSRETURN_UNDEF;
6418             }
6419             }
6420             else {
6421 4           xmlAddChild( self, (xmlNodePtr)attr );
6422 4           xmlReconciliateNs(self->doc, self);
6423             }
6424 4 50         if ( attr->_private != NULL ) {
6425 4 50         PmmFixOwner( SvPROXYNODE(attr_node), PmmPROXYNODE(self) );
6426             }
6427 4 50         if ( ret != NULL && ret->type == XML_ATTRIBUTE_NODE ) {
    0          
6428 0           RETVAL = PmmNodeToSv( (xmlNodePtr)ret, NULL );
6429 0 0         PmmFixOwner( SvPROXYNODE(RETVAL), NULL );
6430             } else {
6431 4           XSRETURN_UNDEF;
6432             }
6433             OUTPUT:
6434             RETVAL
6435              
6436             SV *
6437             removeAttributeNode( self, attr_node )
6438             xmlNodePtr self
6439             SV * attr_node
6440             PREINIT:
6441 3           xmlAttrPtr attr = (xmlAttrPtr)PmmSvNode( attr_node );
6442             xmlAttrPtr ret;
6443             INIT:
6444 3 50         if ( attr == NULL ) {
6445 0           croak( "lost attribute node" );
6446             }
6447             CODE:
6448 3 50         if ( attr->type != XML_ATTRIBUTE_NODE ) {
6449 0           XSRETURN_UNDEF;
6450             }
6451 3 50         if ( attr->parent != self ) {
6452 0           XSRETURN_UNDEF;
6453             }
6454 3           ret = attr;
6455 3           xmlUnlinkNode( (xmlNodePtr)attr );
6456 3           RETVAL = PmmNodeToSv( (xmlNodePtr)ret, NULL );
6457 3 50         PmmFixOwner( SvPROXYNODE(RETVAL), NULL );
6458             OUTPUT:
6459             RETVAL
6460              
6461             void
6462             appendText( self, string )
6463             xmlNodePtr self
6464             SV * string
6465             ALIAS:
6466             appendTextNode = 1
6467             XML::LibXML::DocumentFragment::appendText = 2
6468             XML::LibXML::DocumentFragment::appendTextNode = 3
6469             PREINIT:
6470 88           xmlChar * content = NULL;
6471             INIT:
6472             PERL_UNUSED_VAR(ix);
6473 88           content = nodeSv2C( string, self );
6474 88 50         if ( content == NULL ) {
6475 0           XSRETURN_UNDEF;
6476             }
6477 88 50         if ( xmlStrlen(content) == 0 ) {
6478 0           xmlFree( content );
6479 0           XSRETURN_UNDEF;
6480             }
6481             CODE:
6482 88           xmlNodeAddContent( self, content );
6483 88           xmlFree(content);
6484              
6485              
6486             void
6487             appendTextChild( self, strname, strcontent=&PL_sv_undef, nsURI=&PL_sv_undef )
6488             xmlNodePtr self
6489             SV * strname
6490             SV * strcontent
6491             SV * nsURI
6492             PREINIT:
6493             xmlChar * name;
6494 3           xmlChar * content = NULL;
6495 3           xmlChar * encstr = NULL;
6496             INIT:
6497 3           name = nodeSv2C( strname, self );
6498 3 50         if ( xmlStrlen(name) == 0 ) {
6499 0           xmlFree(name);
6500 0           XSRETURN_UNDEF;
6501             }
6502             CODE:
6503 3           content = nodeSv2C(strcontent, self);
6504 3 100         if ( content && xmlStrlen( content ) == 0 ) {
    50          
6505 0           xmlFree(content);
6506 0           content=NULL;
6507             }
6508 3 100         else if ( content ) {
6509 2           encstr = xmlEncodeEntitiesReentrant( self->doc, content );
6510 2           xmlFree(content);
6511             }
6512              
6513 3           xmlNewChild( self, NULL, name, encstr );
6514              
6515 3 100         if ( encstr )
6516 2           xmlFree(encstr);
6517 3           xmlFree(name);
6518              
6519             SV *
6520             addNewChild( self, namespaceURI, nodename )
6521             xmlNodePtr self
6522             SV * namespaceURI
6523             SV * nodename
6524             ALIAS:
6525             XML::LibXML::DocumentFragment::addNewChild = 1
6526             PREINIT:
6527 72           xmlChar * nsURI = NULL;
6528 72           xmlChar * name = NULL;
6529 72           xmlChar * localname = NULL;
6530 72           xmlChar * prefix = NULL;
6531 72           xmlNodePtr newNode = NULL;
6532 72           xmlNodePtr prev = NULL;
6533 72           xmlNsPtr ns = NULL;
6534             CODE:
6535             PERL_UNUSED_VAR(ix);
6536 72           name = nodeSv2C(nodename, self);
6537 72 50         if ( name && xmlStrlen( name ) == 0 ) {
    50          
6538 0           xmlFree(name);
6539 0           XSRETURN_UNDEF;
6540             }
6541              
6542 72           nsURI = nodeSv2C(namespaceURI, self);
6543 72 50         if ( nsURI && xmlStrlen( nsURI ) == 0 ) {
    100          
6544 50           xmlFree(nsURI);
6545 50           nsURI=NULL;
6546             }
6547              
6548 72 100         if ( nsURI != NULL ) {
6549 22           localname = xmlSplitQName2(name, &prefix);
6550 22           ns = xmlSearchNsByHref(self->doc, self, nsURI);
6551              
6552 22 100         newNode = xmlNewDocNode(self->doc,
6553             ns,
6554             localname?localname:name,
6555             NULL);
6556 22 100         if ( ns == NULL ) {
6557 4           xmlSetNs(newNode,xmlNewNs(newNode, nsURI, prefix));
6558             }
6559              
6560 22           xmlFree(localname);
6561 22           xmlFree(prefix);
6562 22           xmlFree(nsURI);
6563             }
6564             else {
6565 50           newNode = xmlNewDocNode(self->doc,
6566             NULL,
6567             name,
6568             NULL);
6569             }
6570 72           xmlFree(name);
6571             /* add the node to the parent node */
6572 72           newNode->type = XML_ELEMENT_NODE;
6573 72           newNode->parent = self;
6574 72           newNode->doc = self->doc;
6575              
6576 72 100         if (self->children == NULL) {
6577 31           self->children = newNode;
6578 31           self->last = newNode;
6579             } else {
6580 41           prev = self->last;
6581 41           prev->next = newNode;
6582 41           newNode->prev = prev;
6583 41           self->last = newNode;
6584             }
6585 72 50         RETVAL = PmmNodeToSv(newNode, PmmOWNERPO(PmmPROXYNODE(self)) );
    100          
6586             OUTPUT:
6587             RETVAL
6588              
6589             MODULE = XML::LibXML PACKAGE = XML::LibXML::Text
6590              
6591             SV *
6592             new( CLASS, content )
6593             SV * content
6594             PREINIT:
6595             xmlChar * data;
6596             xmlNodePtr newNode;
6597 18           ProxyNodePtr docfrag = NULL;
6598             CODE:
6599 18           data = Sv2C(content, NULL);
6600 18           newNode = xmlNewText( data );
6601 18           xmlFree(data);
6602 18 50         if( newNode != NULL ) {
6603 18           docfrag = PmmNewFragment( NULL );
6604 18           xmlAddChild(PmmNODE(docfrag), newNode);
6605 18           RETVAL = PmmNodeToSv(newNode,docfrag);
6606             }
6607             else {
6608 0           XSRETURN_UNDEF;
6609             }
6610             OUTPUT:
6611             RETVAL
6612              
6613             SV *
6614             substringData( self, offset, length )
6615             xmlNodePtr self
6616             int offset
6617             int length
6618             PREINIT:
6619 4           xmlChar * data = NULL;
6620 4           xmlChar * substr = NULL;
6621             CODE:
6622 4 50         if ( offset >= 0 && length >= 0 ) {
    50          
6623 4           data = domGetNodeValue( self );
6624 8 50         if ( data != NULL ) {
6625 4           substr = xmlUTF8Strsub( data, offset, length );
6626 4           RETVAL = C2Sv( (const xmlChar*)substr, NULL );
6627 4           xmlFree( substr );
6628             }
6629             else {
6630 0           XSRETURN_UNDEF;
6631             }
6632             }
6633             else {
6634 0           XSRETURN_UNDEF;
6635             }
6636             OUTPUT:
6637             RETVAL
6638              
6639             void
6640             setData( self, value )
6641             xmlNodePtr self
6642             SV * value
6643             ALIAS:
6644             XML::LibXML::Attr::setValue = 1
6645             XML::LibXML::PI::_setData = 2
6646             PREINIT:
6647 45           xmlChar * encstr = NULL;
6648             CODE:
6649             PERL_UNUSED_VAR(ix);
6650 45           encstr = nodeSv2C(value,self);
6651 45           domSetNodeValue( self, encstr );
6652 45           xmlFree(encstr);
6653              
6654             void
6655             appendData( self, value )
6656             xmlNodePtr self
6657             SV * value
6658             PREINIT:
6659 2           xmlChar * encstring = NULL;
6660 2           int strlen = 0;
6661             CODE:
6662 2 50         encstring = Sv2C( value,
6663 4           self->doc!=NULL ? self->doc->encoding : NULL );
6664              
6665 2 50         if ( encstring != NULL ) {
6666 2           strlen = xmlStrlen( encstring );
6667 2           xmlTextConcat( self, encstring, strlen );
6668 2           xmlFree( encstring );
6669             }
6670              
6671             void
6672             insertData( self, offset, value )
6673             xmlNodePtr self
6674             int offset
6675             SV * value
6676             PREINIT:
6677 5           xmlChar * after= NULL;
6678 5           xmlChar * data = NULL;
6679 5           xmlChar * new = NULL;
6680 5           xmlChar * encstring = NULL;
6681 5           int dl = 0;
6682             CODE:
6683 5 50         if ( offset >= 0 ) {
6684 5 50         encstring = Sv2C( value,
6685 10           self->doc!=NULL ? self->doc->encoding : NULL );
6686 5 50         if ( encstring != NULL && xmlStrlen( encstring ) > 0 ) {
    100          
6687 4           data = domGetNodeValue(self);
6688 4 50         if ( data != NULL && xmlStrlen( data ) > 0 ) {
    50          
6689 4 50         if ( xmlUTF8Strlen( data ) < offset ) {
6690 0           data = xmlStrcat( data, encstring );
6691 0           domSetNodeValue( self, data );
6692             }
6693             else {
6694 4           dl = xmlUTF8Strlen( data ) - offset;
6695              
6696 4 50         if ( offset > 0 )
6697 4           new = xmlUTF8Strsub(data, 0, offset );
6698              
6699 4           after = xmlUTF8Strsub(data, offset, dl );
6700              
6701 4 50         if ( new != NULL ) {
6702 4           new = xmlStrcat(new, encstring );
6703             }
6704             else {
6705 0           new = xmlStrdup( encstring );
6706             }
6707              
6708 4 50         if ( after != NULL )
6709 4           new = xmlStrcat(new, after );
6710              
6711 4           domSetNodeValue( self, new );
6712              
6713 4           xmlFree( new );
6714 4           xmlFree( after );
6715             }
6716 4           xmlFree( data );
6717             }
6718             else {
6719 0           domSetNodeValue( self, encstring );
6720             }
6721 4           xmlFree(encstring);
6722             }
6723             }
6724              
6725             void
6726             deleteData( self, offset, length )
6727             xmlNodePtr self
6728             int offset
6729             int length
6730             PREINIT:
6731 9           xmlChar * data = NULL;
6732 9           xmlChar * after = NULL;
6733 9           xmlChar * new = NULL;
6734 9           int len = 0;
6735 9           int dl1 = 0;
6736 9           int dl2 = 0;
6737             CODE:
6738 9 100         if ( length > 0 && offset >= 0 ) {
    50          
6739 7           data = domGetNodeValue(self);
6740 7           len = xmlUTF8Strlen( data );
6741 7 50         if ( data != NULL
6742 7 50         && len > 0
6743 7 100         && len > offset ) {
6744 5           dl1 = offset + length;
6745 5 100         if ( offset > 0 )
6746 4           new = xmlUTF8Strsub( data, 0, offset );
6747              
6748 5 100         if ( len > dl1 ) {
6749 3           dl2 = len - dl1;
6750 3           after = xmlUTF8Strsub( data, dl1, dl2 );
6751 3 100         if ( new != NULL ) {
6752 2           new = xmlStrcat( new, after );
6753 2           xmlFree(after);
6754             }
6755             else {
6756 1           new = after;
6757             }
6758             }
6759              
6760 5           domSetNodeValue( self, new );
6761 5           xmlFree(new);
6762             }
6763             }
6764              
6765             void
6766             replaceData( self, offset,length, value )
6767             xmlNodePtr self
6768             int offset
6769             int length
6770             SV * value
6771             PREINIT:
6772 6           xmlChar * after= NULL;
6773 6           xmlChar * data = NULL;
6774 6           xmlChar * new = NULL;
6775 6           xmlChar * encstring = NULL;
6776 6           int len = 0;
6777 6           int dl1 = 0;
6778 6           int dl2 = 0;
6779             CODE:
6780 6 50         if ( offset >= 0 ) {
6781 6 50         encstring = Sv2C( value,
6782 12           self->doc!=NULL ? self->doc->encoding : NULL );
6783              
6784 6 50         if ( encstring != NULL && xmlStrlen( encstring ) > 0 ) {
    50          
6785 6           data = domGetNodeValue(self);
6786 6           len = xmlUTF8Strlen( data );
6787              
6788 6 50         if ( data != NULL
6789 6 50         && len > 0
6790 6 50         && len > offset ) {
6791              
6792 6           dl1 = offset + length;
6793 6 100         if ( dl1 < len ) {
6794 4           dl2 = xmlUTF8Strlen( data ) - dl1;
6795 4 50         if ( offset > 0 ) {
6796 4           new = xmlUTF8Strsub(data, 0, offset );
6797 4           new = xmlStrcat(new, encstring );
6798             }
6799             else {
6800 0           new = xmlStrdup( encstring );
6801             }
6802              
6803 4           after = xmlUTF8Strsub(data, dl1, dl2 );
6804 4           new = xmlStrcat(new, after );
6805              
6806 4           domSetNodeValue( self, new );
6807              
6808 4           xmlFree( new );
6809 4           xmlFree( after );
6810             }
6811             else {
6812             /* replace until end! */
6813 2 50         if ( offset > 0 ) {
6814 2           new = xmlUTF8Strsub(data, 0, offset );
6815 2           new = xmlStrcat(new, encstring );
6816             }
6817             else {
6818 0           new = xmlStrdup( encstring );
6819             }
6820 2           domSetNodeValue( self, new );
6821 2           xmlFree( new );
6822             }
6823 6           xmlFree( data );
6824             }
6825              
6826 6           xmlFree(encstring);
6827             }
6828             }
6829              
6830             MODULE = XML::LibXML PACKAGE = XML::LibXML::Comment
6831              
6832             SV *
6833             new( CLASS, content )
6834             SV * content
6835             PREINIT:
6836             xmlChar * encstring;
6837             xmlNodePtr newNode;
6838 7           ProxyNodePtr docfrag = NULL;
6839             CODE:
6840 7           encstring = Sv2C(content, NULL);
6841 7           newNode = xmlNewComment( encstring );
6842 7           xmlFree(encstring);
6843 7 50         if( newNode != NULL ) {
6844 7           docfrag = PmmNewFragment( NULL );
6845 7           xmlAddChild(PmmNODE(docfrag), newNode);
6846 7           RETVAL = PmmNodeToSv(newNode,docfrag);
6847             }
6848             else {
6849 0           XSRETURN_UNDEF;
6850             }
6851             OUTPUT:
6852             RETVAL
6853              
6854             MODULE = XML::LibXML PACKAGE = XML::LibXML::CDATASection
6855              
6856             SV *
6857             new( CLASS , content )
6858             SV * content
6859             PREINIT:
6860             xmlChar * encstring;
6861             xmlNodePtr newNode;
6862 7           ProxyNodePtr docfrag = NULL;
6863             CODE:
6864 7           encstring = Sv2C(content, NULL);
6865 7           newNode = xmlNewCDataBlock( NULL , encstring, xmlStrlen( encstring ) );
6866 7           xmlFree(encstring);
6867 7 50         if ( newNode != NULL ){
6868 7           docfrag = PmmNewFragment( NULL );
6869 7           xmlAddChild(PmmNODE(docfrag), newNode);
6870 7           RETVAL = PmmNodeToSv(newNode,docfrag);
6871             }
6872             else {
6873 0           XSRETURN_UNDEF;
6874             }
6875             OUTPUT:
6876             RETVAL
6877              
6878             MODULE = XML::LibXML PACKAGE = XML::LibXML::DocumentFragment
6879              
6880             SV*
6881             new( CLASS )
6882             PREINIT:
6883 29           xmlNodePtr real_doc=NULL;
6884             CODE:
6885 29           real_doc = xmlNewDocFragment( NULL );
6886 29           RETVAL = PmmNodeToSv( real_doc, NULL );
6887             OUTPUT:
6888             RETVAL
6889              
6890             MODULE = XML::LibXML PACKAGE = XML::LibXML::Attr
6891              
6892             SV*
6893             new( CLASS, pname, pvalue )
6894             SV * pname
6895             SV * pvalue
6896             PREINIT:
6897 0           xmlNodePtr attr = NULL;
6898             xmlChar * name;
6899             xmlChar * value;
6900             CODE:
6901 0           name = Sv2C(pname,NULL);
6902 0           value = Sv2C(pvalue,NULL);
6903 0 0         if ( name == NULL ) {
6904 0           XSRETURN_UNDEF;
6905             }
6906 0           attr = (xmlNodePtr)xmlNewProp( NULL, name, value );
6907 0           attr->doc = NULL;
6908 0           RETVAL = PmmNodeToSv(attr,NULL);
6909             OUTPUT:
6910             RETVAL
6911              
6912              
6913             SV*
6914             parentElement( self )
6915             ALIAS:
6916             XML::LibXML::Attr::getParentNode = 1
6917             XML::LibXML::Attr::getNextSibling = 2
6918             XML::LibXML::Attr::getPreviousSibling = 3
6919             XML::LibXML::Attr::nextSibling = 4
6920             XML::LibXML::Attr::previousSibling = 5
6921             CODE:
6922             /* override the original parentElement(), since this an attribute is
6923             * not part of the main tree
6924             */
6925              
6926             PERL_UNUSED_VAR(ix);
6927 0           XSRETURN_UNDEF;
6928             OUTPUT:
6929             RETVAL
6930              
6931             SV*
6932             serializeContent( self, useDomEncoding = &PL_sv_undef )
6933             SV * self
6934             SV * useDomEncoding
6935             PREINIT:
6936             xmlBufferPtr buffer;
6937 4           const xmlChar *ret = NULL;
6938 4           xmlAttrPtr node = (xmlAttrPtr)PmmSvNode(self);
6939             CODE:
6940 4           buffer = xmlBufferCreate();
6941 4           domAttrSerializeContent(buffer, node);
6942 4 50         if ( xmlBufferLength(buffer) > 0 ) {
6943 4           ret = xmlBufferContent( buffer );
6944             }
6945 4 50         if ( ret != NULL ) {
6946 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          
6947 0           RETVAL = nodeC2Sv((xmlChar*)ret, PmmNODE(PmmPROXYNODE(node))) ;
6948             }
6949             else {
6950 4           RETVAL = C2Sv((xmlChar*)ret, NULL) ;
6951             }
6952 4           xmlBufferFree( buffer );
6953             }
6954             else {
6955 0           xmlBufferFree( buffer );
6956             xs_warn("Failed to convert attribute to string");
6957 0           XSRETURN_UNDEF;
6958             }
6959             OUTPUT:
6960             RETVAL
6961              
6962             SV*
6963             toString(self , format=0, useDomEncoding = &PL_sv_undef )
6964             SV * self
6965             SV * useDomEncoding
6966             int format
6967             ALIAS:
6968             XML::LibXML::Attr::serialize = 1
6969             PREINIT:
6970 10           xmlAttrPtr node = (xmlAttrPtr)PmmSvNode(self);
6971             xmlBufferPtr buffer;
6972 10           const xmlChar *ret = NULL;
6973             CODE:
6974             /* we add an extra method for serializing attributes since
6975             XML::LibXML::Node::toString causes segmentation fault inside
6976             libxml2
6977             */
6978             PERL_UNUSED_VAR(ix);
6979 10           buffer = xmlBufferCreate();
6980 10           xmlBufferAdd(buffer, BAD_CAST " ", 1);
6981 10 100         if ((node->ns != NULL) && (node->ns->prefix != NULL)) {
    50          
6982 2           xmlBufferAdd(buffer, node->ns->prefix, xmlStrlen(node->ns->prefix));
6983 2           xmlBufferAdd(buffer, BAD_CAST ":", 1);
6984             }
6985 10           xmlBufferAdd(buffer, node->name, xmlStrlen(node->name));
6986 10           xmlBufferAdd(buffer, BAD_CAST "=\"", 2);
6987 10           domAttrSerializeContent(buffer, node);
6988 10           xmlBufferAdd(buffer, BAD_CAST "\"", 1);
6989              
6990 10 50         if ( xmlBufferLength(buffer) > 0 ) {
6991 10           ret = xmlBufferContent( buffer );
6992             }
6993 10 50         if ( ret != NULL ) {
6994 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          
6995 0           RETVAL = nodeC2Sv((xmlChar*)ret, PmmNODE(PmmPROXYNODE(node))) ;
6996             }
6997             else {
6998 10           RETVAL = C2Sv((xmlChar*)ret, NULL) ;
6999             }
7000 10           xmlBufferFree( buffer );
7001             }
7002             else {
7003 0           xmlBufferFree( buffer );
7004             xs_warn("Failed to convert attribute to string");
7005 0           XSRETURN_UNDEF;
7006             }
7007             OUTPUT:
7008             RETVAL
7009              
7010              
7011             int
7012             _setNamespace(self, namespaceURI, namespacePrefix = &PL_sv_undef )
7013             SV * self
7014             SV * namespaceURI
7015             SV * namespacePrefix
7016             PREINIT:
7017 2           xmlAttrPtr node = (xmlAttrPtr)PmmSvNode(self);
7018 2           xmlChar * nsURI = nodeSv2C(namespaceURI,(xmlNodePtr)node);
7019 2           xmlChar * nsPrefix = NULL;
7020 2           xmlNsPtr ns = NULL;
7021             INIT:
7022 2 50         if ( node == NULL ) {
7023 0           croak( "lost node" );
7024             }
7025             CODE:
7026 2 50         if ( !nsURI || xmlStrlen(nsURI)==0 ){
    100          
7027 1           xmlSetNs((xmlNodePtr)node, NULL);
7028 1           RETVAL = 1;
7029             }
7030 2 50         if ( !node->parent ) {
7031 0           XSRETURN_UNDEF;
7032             }
7033 2           nsPrefix = nodeSv2C(namespacePrefix, (xmlNodePtr)node);
7034 3           if ( (ns = xmlSearchNs(node->doc, node->parent, nsPrefix)) &&
7035 1           xmlStrEqual( ns->href, nsURI) ) {
7036             /* same uri and prefix */
7037 1           RETVAL = 1;
7038             }
7039 1 50         else if ( (ns = xmlSearchNsByHref(node->doc, node->parent, nsURI)) ) {
7040             /* set uri, but with a different prefix */
7041 0           RETVAL = 1;
7042             }
7043 1 50         else if (! RETVAL)
7044 0           RETVAL = 0;
7045              
7046 2 100         if ( ns ) {
7047 1 50         if ( ns->prefix ) {
7048 1           xmlSetNs((xmlNodePtr)node, ns);
7049             } else {
7050 0           RETVAL = 0;
7051             }
7052             }
7053 2           xmlFree(nsPrefix);
7054 2           xmlFree(nsURI);
7055             OUTPUT:
7056             RETVAL
7057              
7058             int
7059             isId( self )
7060             SV * self
7061             PREINIT:
7062 10           xmlAttrPtr attr = (xmlAttrPtr)PmmSvNode(self);
7063             xmlNodePtr elem;
7064             CODE:
7065 10 50         if ( attr == NULL ) {
7066 0           XSRETURN_UNDEF;
7067             }
7068 10           elem = attr->parent;
7069 10 50         if ( elem == NULL || elem->doc == NULL ) {
    50          
7070 0           XSRETURN_UNDEF;
7071             }
7072 10           RETVAL = xmlIsID( elem->doc, elem, attr );
7073             OUTPUT:
7074             RETVAL
7075              
7076             MODULE = XML::LibXML PACKAGE = XML::LibXML::Namespace
7077              
7078             SV*
7079             new(CLASS, namespaceURI, namespacePrefix=&PL_sv_undef)
7080             const char * CLASS
7081             SV * namespaceURI
7082             SV * namespacePrefix
7083             PREINIT:
7084 14           xmlNsPtr ns = NULL;
7085             xmlChar* nsURI;
7086             xmlChar* nsPrefix;
7087             CODE:
7088 14           RETVAL = &PL_sv_undef;
7089              
7090 14           nsURI = Sv2C(namespaceURI,NULL);
7091 14 50         if ( !nsURI ) {
7092 0           XSRETURN_UNDEF;
7093             }
7094 14           nsPrefix = Sv2C(namespacePrefix, NULL);
7095 14           ns = xmlNewNs(NULL, nsURI, nsPrefix);
7096 14 50         if ( ns ) {
7097 14           RETVAL = NEWSV(0,0);
7098 14           RETVAL = sv_setref_pv( RETVAL,
7099             CLASS,
7100             (void*)ns);
7101             }
7102 14           xmlFree(nsURI);
7103 14 100         if ( nsPrefix )
7104 9           xmlFree(nsPrefix);
7105             OUTPUT:
7106             RETVAL
7107              
7108             void
7109             DESTROY(self)
7110             SV * self
7111             PREINIT:
7112 36 50         xmlNsPtr ns = INT2PTR(xmlNsPtr,SvIV(SvRV(self)));
7113             CODE:
7114             xs_warn( "DESTROY NS" );
7115 36 50         if (ns) {
7116 36           xmlFreeNs(ns);
7117             }
7118              
7119             int
7120             nodeType(self)
7121             SV * self
7122             ALIAS:
7123             getType = 1
7124             PREINIT:
7125 3 50         xmlNsPtr ns = INT2PTR(xmlNsPtr,SvIV(SvRV(self)));
7126             CODE:
7127             PERL_UNUSED_VAR(ix);
7128 3           RETVAL = ns->type;
7129             OUTPUT:
7130             RETVAL
7131              
7132             SV*
7133             declaredURI(self)
7134             SV * self
7135             ALIAS:
7136             value = 1
7137             nodeValue = 2
7138             getData = 3
7139             getValue = 4
7140             value2 = 5
7141             href = 6
7142             PREINIT:
7143 12 50         xmlNsPtr ns = INT2PTR(xmlNsPtr,SvIV(SvRV(self)));
7144             xmlChar * href;
7145             CODE:
7146             PERL_UNUSED_VAR(ix);
7147 12           href = xmlStrdup(ns->href);
7148 12           RETVAL = C2Sv(href, NULL);
7149 12           xmlFree(href);
7150             OUTPUT:
7151             RETVAL
7152              
7153             SV*
7154             declaredPrefix(self)
7155             SV * self
7156             ALIAS:
7157             localname = 1
7158             getLocalName = 2
7159             PREINIT:
7160 20 50         xmlNsPtr ns = INT2PTR(xmlNsPtr,SvIV(SvRV(self)));
7161             xmlChar * prefix;
7162             CODE:
7163             PERL_UNUSED_VAR(ix);
7164 20           prefix = xmlStrdup(ns->prefix);
7165 20           RETVAL = C2Sv(prefix, NULL);
7166 20           xmlFree(prefix);
7167             OUTPUT:
7168             RETVAL
7169              
7170             SV*
7171             unique_key( self )
7172             SV * self
7173             PREINIT:
7174 10 50         xmlNsPtr ns = INT2PTR(xmlNsPtr,SvIV(SvRV(self)));
7175             xmlChar* key;
7176             CODE:
7177             /* Concatenate prefix and URI with vertical bar dividing*/
7178 10           key = xmlStrdup(ns->prefix);
7179 10           key = xmlStrcat(key, (const xmlChar*)"|");
7180 10           key = xmlStrcat(key, ns->href);
7181 10           RETVAL = C2Sv(key, NULL);
7182             OUTPUT:
7183             RETVAL
7184              
7185             int
7186             _isEqual(self, ref_node)
7187             SV * self
7188             SV * ref_node
7189             PREINIT:
7190 0 0         xmlNsPtr ns = INT2PTR(xmlNsPtr,SvIV(SvRV(self)));
7191 0 0         xmlNsPtr ons = INT2PTR(xmlNsPtr,SvIV(SvRV(ref_node)));
7192             CODE:
7193 0           RETVAL = 0;
7194 0 0         if ( ns == ons ) {
7195 0           RETVAL = 1;
7196             }
7197 0 0         else if ( xmlStrEqual(ns->href, ons->href)
7198 0 0         && xmlStrEqual(ns->prefix, ons->prefix) ) {
7199 0           RETVAL = 1;
7200             }
7201             OUTPUT:
7202             RETVAL
7203              
7204              
7205             MODULE = XML::LibXML PACKAGE = XML::LibXML::Dtd
7206              
7207             SV *
7208             new(CLASS, external, system)
7209             char * external
7210             char * system
7211             ALIAS:
7212             parse_uri = 1
7213             PREINIT:
7214 4           xmlDtdPtr dtd = NULL;
7215 4           PREINIT_SAVED_ERROR
7216             CODE:
7217             PERL_UNUSED_VAR(ix);
7218 4           INIT_ERROR_HANDLER;
7219 4           dtd = xmlParseDTD((const xmlChar*)external, (const xmlChar*)system);
7220 4 100         if ( dtd == NULL ) {
7221 2           CLEANUP_ERROR_HANDLER;
7222 2           REPORT_ERROR(0);
7223 1           XSRETURN_UNDEF;
7224             } else {
7225 2           xmlSetTreeDoc((xmlNodePtr)dtd, NULL);
7226 2           RETVAL = PmmNodeToSv( (xmlNodePtr) dtd, NULL );
7227 2           CLEANUP_ERROR_HANDLER;
7228 2           REPORT_ERROR(0);
7229             }
7230             OUTPUT:
7231             RETVAL
7232              
7233             SV*
7234             systemId( self )
7235             xmlDtdPtr self
7236             ALIAS:
7237             getSystemId = 1
7238             CODE:
7239             PERL_UNUSED_VAR(ix);
7240 3 100         if ( self->SystemID == NULL ) {
7241 1           XSRETURN_UNDEF;
7242             } else {
7243 2           RETVAL = C2Sv(self->SystemID,NULL);
7244             }
7245             OUTPUT:
7246             RETVAL
7247              
7248             SV*
7249             publicId( self )
7250             xmlDtdPtr self
7251             ALIAS:
7252             getPublicId = 1
7253             CODE:
7254             PERL_UNUSED_VAR(ix);
7255 3 100         if ( self->ExternalID == NULL ) {
7256 1           XSRETURN_UNDEF;
7257             } else {
7258 2           RETVAL = C2Sv(self->ExternalID,NULL);
7259             }
7260             OUTPUT:
7261             RETVAL
7262              
7263             SV *
7264             parse_string(CLASS, str, ...)
7265             char * str
7266             PREINIT:
7267             xmlDtdPtr res;
7268             SV * encoding_sv;
7269             xmlParserInputBufferPtr buffer;
7270 4           xmlCharEncoding enc = XML_CHAR_ENCODING_NONE;
7271             xmlChar * new_string;
7272 4           PREINIT_SAVED_ERROR
7273             CODE:
7274 4           INIT_ERROR_HANDLER;
7275 4 50         if (items > 2) {
7276 0           encoding_sv = ST(2);
7277 0 0         if (items > 3) {
7278 0           CLEANUP_ERROR_HANDLER;
7279 0           croak("parse_string: too many parameters");
7280             }
7281             /* warn("getting encoding...\n"); */
7282 0 0         enc = xmlParseCharEncoding(SvPV_nolen(encoding_sv));
7283 0 0         if (enc == XML_CHAR_ENCODING_ERROR) {
7284 0           CLEANUP_ERROR_HANDLER;
7285 0           REPORT_ERROR(1);
7286 0 0         croak("Parse of encoding %s failed", SvPV_nolen(encoding_sv));
7287             }
7288             }
7289 4           buffer = xmlAllocParserInputBuffer(enc);
7290             /* buffer = xmlParserInputBufferCreateMem(str, xmlStrlen(str), enc); */
7291 4 50         if ( !buffer) {
7292 0           CLEANUP_ERROR_HANDLER;
7293 0           REPORT_ERROR(1);
7294 0           croak("cannot create buffer!\n" );
7295             }
7296 4           new_string = xmlStrdup((const xmlChar*)str);
7297 4           xmlParserInputBufferPush(buffer, xmlStrlen(new_string), (const char*)new_string);
7298              
7299 4           res = xmlIOParseDTD(NULL, buffer, enc);
7300              
7301             /* NOTE: xmlIOParseDTD is documented to free its InputBuffer */
7302 4           xmlFree(new_string);
7303 4 100         if ( res && LibXML_will_die_ctx(saved_error, 0) )
    50          
7304 0           xmlFreeDtd( res );
7305 4           CLEANUP_ERROR_HANDLER;
7306 4           REPORT_ERROR(0);
7307 3 50         if (res == NULL) {
7308 0           croak("no DTD parsed!");
7309             }
7310 3           RETVAL = PmmNodeToSv((xmlNodePtr)res, NULL);
7311             OUTPUT:
7312             RETVAL
7313              
7314              
7315             #ifdef HAVE_SCHEMAS
7316              
7317             MODULE = XML::LibXML PACKAGE = XML::LibXML::RelaxNG
7318              
7319             void
7320             DESTROY( self )
7321             xmlRelaxNGPtr self
7322             CODE:
7323 6           xmlRelaxNGFree( self );
7324              
7325              
7326             xmlRelaxNGPtr
7327             parse_location( self, url, parser_options = 0, recover = FALSE )
7328             char * url
7329             int parser_options
7330             bool recover
7331             PREINIT:
7332 6           const char * CLASS = "XML::LibXML::RelaxNG";
7333 6           xmlRelaxNGParserCtxtPtr rngctxt = NULL;
7334 6           xmlExternalEntityLoader old_ext_ent_loader = NULL;
7335 6           PREINIT_SAVED_ERROR
7336             CODE:
7337 6           INIT_ERROR_HANDLER;
7338              
7339 6           rngctxt = xmlRelaxNGNewParserCtxt( url );
7340 6 50         if ( rngctxt == NULL ) {
7341 0           croak( "failed to initialize RelaxNG parser" );
7342             }
7343             #ifndef WITH_SERRORS
7344             /* Register Error callbacks */
7345             xmlRelaxNGSetParserErrors( rngctxt,
7346             (xmlRelaxNGValidityErrorFunc)LibXML_error_handler_ctx,
7347             (xmlRelaxNGValidityWarningFunc)LibXML_error_handler_ctx,
7348             saved_error );
7349             #endif
7350              
7351 6 50         if ( EXTERNAL_ENTITY_LOADER_FUNC == NULL && (parser_options & XML_PARSE_NONET) ) {
    100          
7352 1           old_ext_ent_loader = xmlGetExternalEntityLoader();
7353 1           xmlSetExternalEntityLoader( xmlNoNetExternalEntityLoader );
7354             }
7355              
7356 6           RETVAL = xmlRelaxNGParse( rngctxt );
7357              
7358 6 50         if ( EXTERNAL_ENTITY_LOADER_FUNC == NULL && (parser_options & XML_PARSE_NONET) )
    100          
7359 1           xmlSetExternalEntityLoader( (xmlExternalEntityLoader)old_ext_ent_loader );
7360              
7361 6           xmlRelaxNGFreeParserCtxt( rngctxt );
7362 6           CLEANUP_ERROR_HANDLER;
7363 6 100         REPORT_ERROR((RETVAL == NULL) ? 0 : recover);
7364             OUTPUT:
7365             RETVAL
7366              
7367              
7368             xmlRelaxNGPtr
7369             parse_buffer( self, perlstring, parser_options = 0, recover = FALSE )
7370             SV * perlstring
7371             int parser_options
7372             bool recover
7373             PREINIT:
7374 3           const char * CLASS = "XML::LibXML::RelaxNG";
7375 3           xmlRelaxNGParserCtxtPtr rngctxt = NULL;
7376 3           xmlExternalEntityLoader old_ext_ent_loader = NULL;
7377 3           char * string = NULL;
7378 3           STRLEN len = 0;
7379 3           PREINIT_SAVED_ERROR
7380             INIT:
7381 3 50         string = SvPV( perlstring, len );
7382 3 50         if ( string == NULL ) {
7383 0           croak( "cannot parse empty string" );
7384             }
7385             CODE:
7386 3           INIT_ERROR_HANDLER;
7387              
7388 3           rngctxt = xmlRelaxNGNewMemParserCtxt( string,len );
7389 3 50         if ( rngctxt == NULL ) {
7390 0           croak( "failed to initialize RelaxNG parser" );
7391             }
7392             #ifndef WITH_SERRORS
7393             /* Register Error callbacks */
7394             xmlRelaxNGSetParserErrors( rngctxt,
7395             (xmlRelaxNGValidityErrorFunc)LibXML_error_handler_ctx,
7396             (xmlRelaxNGValidityWarningFunc)LibXML_error_handler_ctx,
7397             saved_error );
7398             #endif
7399              
7400 3 50         if ( EXTERNAL_ENTITY_LOADER_FUNC == NULL && (parser_options & XML_PARSE_NONET) ) {
    100          
7401 1           old_ext_ent_loader = xmlGetExternalEntityLoader();
7402 1           xmlSetExternalEntityLoader( xmlNoNetExternalEntityLoader );
7403             }
7404              
7405 3           RETVAL = xmlRelaxNGParse( rngctxt );
7406              
7407 3 50         if ( EXTERNAL_ENTITY_LOADER_FUNC == NULL && (parser_options & XML_PARSE_NONET) )
    100          
7408 1           xmlSetExternalEntityLoader( (xmlExternalEntityLoader)old_ext_ent_loader );
7409              
7410 3           xmlRelaxNGFreeParserCtxt( rngctxt );
7411 3           CLEANUP_ERROR_HANDLER;
7412 3 100         REPORT_ERROR((RETVAL == NULL) ? 0 : recover);
7413             OUTPUT:
7414             RETVAL
7415              
7416              
7417             xmlRelaxNGPtr
7418             parse_document( self, doc, parser_options = 0, recover = FALSE )
7419             xmlDocPtr doc
7420             int parser_options
7421             bool recover
7422             PREINIT:
7423 2           const char * CLASS = "XML::LibXML::RelaxNG";
7424 2           xmlRelaxNGParserCtxtPtr rngctxt = NULL;
7425 2           xmlExternalEntityLoader old_ext_ent_loader = NULL;
7426 2           PREINIT_SAVED_ERROR
7427             CODE:
7428 2           INIT_ERROR_HANDLER;
7429              
7430 2           rngctxt = xmlRelaxNGNewDocParserCtxt( doc );
7431 2 50         if ( rngctxt == NULL ) {
7432 0           croak( "failed to initialize RelaxNG parser" );
7433             }
7434             #ifndef WITH_SERRORS
7435             /* Register Error callbacks */
7436             xmlRelaxNGSetParserErrors( rngctxt,
7437             (xmlRelaxNGValidityErrorFunc) LibXML_error_handler_ctx,
7438             (xmlRelaxNGValidityWarningFunc)LibXML_error_handler_ctx,
7439             saved_error );
7440             #endif
7441              
7442 2 50         if ( EXTERNAL_ENTITY_LOADER_FUNC == NULL && (parser_options & XML_PARSE_NONET) ) {
    50          
7443 0           old_ext_ent_loader = xmlGetExternalEntityLoader();
7444 0           xmlSetExternalEntityLoader( xmlNoNetExternalEntityLoader );
7445             }
7446              
7447 2           RETVAL = xmlRelaxNGParse( rngctxt );
7448              
7449 2 50         if ( EXTERNAL_ENTITY_LOADER_FUNC == NULL && (parser_options & XML_PARSE_NONET) )
    50          
7450 0           xmlSetExternalEntityLoader( (xmlExternalEntityLoader)old_ext_ent_loader );
7451              
7452 2           xmlRelaxNGFreeParserCtxt( rngctxt );
7453 2           CLEANUP_ERROR_HANDLER;
7454 2 100         REPORT_ERROR((RETVAL == NULL) ? 0 : recover);
7455             OUTPUT:
7456             RETVAL
7457              
7458             int
7459             validate( self, doc )
7460             xmlRelaxNGPtr self
7461             xmlDocPtr doc
7462             PREINIT:
7463 7           xmlRelaxNGValidCtxtPtr vctxt = NULL;
7464 7           PREINIT_SAVED_ERROR
7465             CODE:
7466 7           INIT_ERROR_HANDLER;
7467              
7468 7 50         if (doc) {
7469 7 50         PmmClearPSVI(doc);
    50          
    50          
    100          
7470 7 50         PmmInvalidatePSVI(doc);
    50          
7471             }
7472 7           vctxt = xmlRelaxNGNewValidCtxt( self );
7473 7 50         if ( vctxt == NULL ) {
7474 0           CLEANUP_ERROR_HANDLER;
7475 0           REPORT_ERROR(0);
7476 0           croak( "cannot initialize the validation context" );
7477             }
7478             #ifndef WITH_SERRORS
7479             /* Register Error callbacks */
7480             xmlRelaxNGSetValidErrors( vctxt,
7481             (xmlRelaxNGValidityErrorFunc)LibXML_error_handler_ctx,
7482             (xmlRelaxNGValidityWarningFunc)LibXML_error_handler_ctx,
7483             saved_error );
7484             #endif /* WITH_SERRORS */
7485             /* ** test only **
7486             xmlRelaxNGSetValidErrors( vctxt,
7487             (xmlRelaxNGValidityErrorFunc)fprintf,
7488             (xmlRelaxNGValidityWarningFunc)fprintf,
7489             stderr );
7490             */
7491 7           RETVAL = xmlRelaxNGValidateDoc( vctxt, doc );
7492 7           xmlRelaxNGFreeValidCtxt( vctxt );
7493 7           CLEANUP_ERROR_HANDLER;
7494 7           REPORT_ERROR(0);
7495 3 50         if ( RETVAL == 1 ) {
7496 0           XSRETURN_UNDEF;
7497             }
7498 3 50         if ( RETVAL == -1 ) {
7499 0           croak( "API Error" );
7500             XSRETURN_UNDEF;
7501             }
7502             OUTPUT:
7503             RETVAL
7504              
7505              
7506             MODULE = XML::LibXML PACKAGE = XML::LibXML::Schema
7507              
7508             void
7509             DESTROY( self )
7510             xmlSchemaPtr self
7511             CODE:
7512 5           xmlSchemaFree( self );
7513              
7514              
7515             xmlSchemaPtr
7516             parse_location( self, url, parser_options = 0, recover = FALSE )
7517             char * url
7518             int parser_options
7519             bool recover
7520             PREINIT:
7521 5           const char * CLASS = "XML::LibXML::Schema";
7522 5           xmlSchemaParserCtxtPtr rngctxt = NULL;
7523 5           xmlExternalEntityLoader old_ext_ent_loader = NULL;
7524 5           PREINIT_SAVED_ERROR
7525             CODE:
7526 5           INIT_ERROR_HANDLER;
7527              
7528 5           rngctxt = xmlSchemaNewParserCtxt( url );
7529 5 50         if ( rngctxt == NULL ) {
7530 0           CLEANUP_ERROR_HANDLER;
7531 0           REPORT_ERROR(0);
7532 0           croak( "failed to initialize Schema parser" );
7533             }
7534              
7535             /* Register Error callbacks */
7536 5           xmlSchemaSetParserErrors( rngctxt,
7537             (xmlSchemaValidityErrorFunc)LibXML_error_handler_ctx,
7538             (xmlSchemaValidityWarningFunc)LibXML_error_handler_ctx,
7539             saved_error );
7540              
7541 5 50         if ( EXTERNAL_ENTITY_LOADER_FUNC == NULL && (parser_options & XML_PARSE_NONET) ) {
    100          
7542 1           old_ext_ent_loader = xmlGetExternalEntityLoader();
7543 1           xmlSetExternalEntityLoader( xmlNoNetExternalEntityLoader );
7544             }
7545              
7546 5           RETVAL = xmlSchemaParse( rngctxt );
7547              
7548 5 50         if ( EXTERNAL_ENTITY_LOADER_FUNC == NULL && (parser_options & XML_PARSE_NONET) )
    100          
7549 1           xmlSetExternalEntityLoader( (xmlExternalEntityLoader)old_ext_ent_loader );
7550              
7551 5           xmlSchemaFreeParserCtxt( rngctxt );
7552 5           CLEANUP_ERROR_HANDLER;
7553 5 100         REPORT_ERROR((RETVAL == NULL) ? 0 : recover);
7554             OUTPUT:
7555             RETVAL
7556              
7557              
7558             xmlSchemaPtr
7559             parse_buffer( self, perlstring, parser_options = 0, recover = FALSE )
7560             SV * perlstring
7561             int parser_options
7562             bool recover
7563             PREINIT:
7564 4           const char * CLASS = "XML::LibXML::Schema";
7565 4           xmlSchemaParserCtxtPtr rngctxt = NULL;
7566 4           xmlExternalEntityLoader old_ext_ent_loader = NULL;
7567 4           char * string = NULL;
7568 4           STRLEN len = 0;
7569 4           PREINIT_SAVED_ERROR
7570             INIT:
7571 4 50         string = SvPV( perlstring, len );
7572 4 50         if ( string == NULL ) {
7573 0           croak( "cannot parse empty string" );
7574             }
7575             CODE:
7576 4           INIT_ERROR_HANDLER;
7577              
7578 4           rngctxt = xmlSchemaNewMemParserCtxt( string,len );
7579 4 50         if ( rngctxt == NULL ) {
7580 0           CLEANUP_ERROR_HANDLER;
7581 0           REPORT_ERROR(0);
7582 0           croak( "failed to initialize Schema parser" );
7583             }
7584              
7585             /* Register Error callbacks */
7586 4           xmlSchemaSetParserErrors( rngctxt,
7587             (xmlSchemaValidityErrorFunc)LibXML_error_handler_ctx,
7588             (xmlSchemaValidityWarningFunc)LibXML_error_handler_ctx,
7589             saved_error );
7590              
7591 4 50         if ( EXTERNAL_ENTITY_LOADER_FUNC == NULL && (parser_options & XML_PARSE_NONET) ) {
    100          
7592 1           old_ext_ent_loader = xmlGetExternalEntityLoader();
7593 1           xmlSetExternalEntityLoader( xmlNoNetExternalEntityLoader );
7594             }
7595              
7596 4           RETVAL = xmlSchemaParse( rngctxt );
7597              
7598 4 50         if ( EXTERNAL_ENTITY_LOADER_FUNC == NULL && (parser_options & XML_PARSE_NONET) )
    100          
7599 1           xmlSetExternalEntityLoader( (xmlExternalEntityLoader)old_ext_ent_loader );
7600              
7601 4           xmlSchemaFreeParserCtxt( rngctxt );
7602 4           CLEANUP_ERROR_HANDLER;
7603 4 100         REPORT_ERROR((RETVAL == NULL) ? 0 : recover);
7604             OUTPUT:
7605             RETVAL
7606              
7607              
7608             int
7609             validate( self, node )
7610             xmlSchemaPtr self
7611             xmlNodePtr node
7612             PREINIT:
7613 3           xmlSchemaValidCtxtPtr vctxt = NULL;
7614 3           PREINIT_SAVED_ERROR
7615             CODE:
7616 3           INIT_ERROR_HANDLER;
7617              
7618 3 100         if (node->type == XML_DOCUMENT_NODE) {
7619 2 50         PmmClearPSVI((xmlDocPtr)node);
    50          
    50          
    50          
7620 2 50         PmmInvalidatePSVI((xmlDocPtr)node);
    50          
7621             }
7622 3           vctxt = xmlSchemaNewValidCtxt( self );
7623 3 50         if ( vctxt == NULL ) {
7624 0           CLEANUP_ERROR_HANDLER;
7625 0           REPORT_ERROR(0);
7626 0           croak( "cannot initialize the validation context" );
7627             }
7628              
7629             /* Register Error callbacks */
7630 3           xmlSchemaSetValidErrors( vctxt,
7631             (xmlSchemaValidityErrorFunc)LibXML_error_handler_ctx,
7632             (xmlSchemaValidityWarningFunc)LibXML_error_handler_ctx,
7633             saved_error );
7634              
7635 3 100         if (node->type == XML_DOCUMENT_NODE) {
7636 2           RETVAL = xmlSchemaValidateDoc(vctxt, (xmlDocPtr)node);
7637             }
7638             else {
7639 1           RETVAL = xmlSchemaValidateOneElement(vctxt, node);
7640             }
7641              
7642 3           xmlSchemaFreeValidCtxt( vctxt );
7643              
7644 3           CLEANUP_ERROR_HANDLER;
7645 3           REPORT_ERROR(0);
7646 2 50         if ( RETVAL > 0 ) {
7647 0           XSRETURN_UNDEF;
7648             }
7649 2 50         if ( RETVAL == -1 ) {
7650 0           croak( "API Error" );
7651             XSRETURN_UNDEF;
7652             }
7653             OUTPUT:
7654             RETVAL
7655              
7656             #endif /* HAVE_SCHEMAS */
7657              
7658             MODULE = XML::LibXML::XPathContext PACKAGE = XML::LibXML::XPathContext
7659              
7660             # PROTOTYPES: DISABLE
7661              
7662             SV*
7663             new( CLASS, ... )
7664             const char * CLASS
7665             PREINIT:
7666 30           SV * pnode = &PL_sv_undef;
7667             INIT:
7668             xmlXPathContextPtr ctxt;
7669             CODE:
7670 30 100         if( items > 1 )
7671 26           pnode = ST(1);
7672              
7673 30           ctxt = xmlXPathNewContext( NULL );
7674 30           ctxt->namespaces = NULL;
7675              
7676 30           New(0, ctxt->user, sizeof(XPathContextData), XPathContextData);
7677 30 50         if (ctxt->user == NULL) {
7678 0           croak("XPathContext: failed to allocate proxy object\n");
7679             }
7680              
7681 30 100         if (SvOK(pnode)) {
    50          
    50          
7682 26           XPathContextDATA(ctxt)->node = newSVsv(pnode);
7683             } else {
7684 4           XPathContextDATA(ctxt)->node = &PL_sv_undef;
7685             }
7686              
7687 30           XPathContextDATA(ctxt)->pool = NULL;
7688 30           XPathContextDATA(ctxt)->varLookup = NULL;
7689 30           XPathContextDATA(ctxt)->varData = NULL;
7690              
7691 30           xmlXPathRegisterFunc(ctxt,
7692             (const xmlChar *) "document",
7693             perlDocumentFunction);
7694              
7695 30           RETVAL = NEWSV(0,0),
7696 30           RETVAL = sv_setref_pv( RETVAL,
7697             CLASS,
7698             (void*)ctxt );
7699             OUTPUT:
7700             RETVAL
7701              
7702             void
7703             DESTROY( self )
7704             SV * self
7705             INIT:
7706 30 50         xmlXPathContextPtr ctxt = INT2PTR(xmlXPathContextPtr,SvIV(SvRV(self)));
7707             CODE:
7708             xs_warn( "DESTROY XPATH CONTEXT" );
7709 30 50         if (ctxt) {
7710 30 50         if (XPathContextDATA(ctxt) != NULL) {
7711 30 100         if (XPathContextDATA(ctxt)->node != NULL &&
    100          
7712 1 50         SvOK(XPathContextDATA(ctxt)->node)) {
    50          
7713 27           SvREFCNT_dec(XPathContextDATA(ctxt)->node);
7714             }
7715 30 100         if (XPathContextDATA(ctxt)->varLookup != NULL &&
    50          
7716 0 0         SvOK(XPathContextDATA(ctxt)->varLookup)) {
    0          
7717 2           SvREFCNT_dec(XPathContextDATA(ctxt)->varLookup);
7718             }
7719 30 100         if (XPathContextDATA(ctxt)->varData != NULL &&
    50          
7720 0 0         SvOK(XPathContextDATA(ctxt)->varData)) {
    0          
7721 1           SvREFCNT_dec(XPathContextDATA(ctxt)->varData);
7722             }
7723 30 50         if (XPathContextDATA(ctxt)->pool != NULL &&
    0          
7724 0 0         SvOK(XPathContextDATA(ctxt)->pool)) {
    0          
7725 0           SvREFCNT_dec((SV *)XPathContextDATA(ctxt)->pool);
7726             }
7727 30           Safefree(XPathContextDATA(ctxt));
7728             }
7729              
7730 30 100         if (ctxt->namespaces != NULL) {
7731 4           xmlFree( ctxt->namespaces );
7732             }
7733 30 100         if (ctxt->funcLookupData != NULL && SvROK((SV*)ctxt->funcLookupData)
    50          
7734 1 50         && SvTYPE(SvRV((SV *)ctxt->funcLookupData)) == SVt_PVHV) {
7735 1           SvREFCNT_dec((SV *)ctxt->funcLookupData);
7736             }
7737              
7738 30           xmlXPathFreeContext(ctxt);
7739             }
7740              
7741             SV*
7742             getContextNode( self )
7743             SV * self
7744             INIT:
7745 27 50         xmlXPathContextPtr ctxt = INT2PTR(xmlXPathContextPtr,SvIV(SvRV(self)));
7746 27 50         if ( ctxt == NULL ) {
7747 0           croak("XPathContext: missing xpath context\n");
7748             }
7749             CODE:
7750 27 100         if(XPathContextDATA(ctxt)->node != NULL) {
7751 14           RETVAL = newSVsv(XPathContextDATA(ctxt)->node);
7752             } else {
7753 13           RETVAL = &PL_sv_undef;
7754             }
7755             OUTPUT:
7756             RETVAL
7757              
7758             int
7759             getContextPosition( self )
7760             SV * self
7761             INIT:
7762 4 50         xmlXPathContextPtr ctxt = INT2PTR(xmlXPathContextPtr,SvIV(SvRV(self)));
7763 4 50         if ( ctxt == NULL ) {
7764 0           croak("XPathContext: missing xpath context\n");
7765             }
7766             CODE:
7767 4           RETVAL = ctxt->proximityPosition;
7768             OUTPUT:
7769             RETVAL
7770              
7771             int
7772             getContextSize( self )
7773             SV * self
7774             INIT:
7775 5 50         xmlXPathContextPtr ctxt = INT2PTR(xmlXPathContextPtr,SvIV(SvRV(self)));
7776 5 50         if ( ctxt == NULL ) {
7777 0           croak("XPathContext: missing xpath context\n");
7778             }
7779             CODE:
7780 5           RETVAL = ctxt->contextSize;
7781             OUTPUT:
7782             RETVAL
7783              
7784             void
7785             setContextNode( self , pnode )
7786             SV * self
7787             SV * pnode
7788             INIT:
7789 40 50         xmlXPathContextPtr ctxt = INT2PTR(xmlXPathContextPtr,SvIV(SvRV(self)));
7790 40 50         if ( ctxt == NULL ) {
7791 0           croak("XPathContext: missing xpath context\n");
7792             }
7793             PPCODE:
7794 40 100         if (XPathContextDATA(ctxt)->node != NULL) {
7795 27           SvREFCNT_dec(XPathContextDATA(ctxt)->node);
7796             }
7797 40 100         if (SvOK(pnode)) {
    50          
    50          
7798 25           XPathContextDATA(ctxt)->node = newSVsv(pnode);
7799             } else {
7800 15           XPathContextDATA(ctxt)->node = NULL;
7801             }
7802              
7803             void
7804             setContextPosition( self , position )
7805             SV * self
7806             int position
7807             INIT:
7808 4 50         xmlXPathContextPtr ctxt = INT2PTR(xmlXPathContextPtr,SvIV(SvRV(self)));
7809 4 50         if ( ctxt == NULL )
7810 0           croak("XPathContext: missing xpath context\n");
7811 4 100         if ( position < -1 || position > ctxt->contextSize )
    100          
7812 3           croak("XPathContext: invalid position\n");
7813             PPCODE:
7814 1           ctxt->proximityPosition = position;
7815              
7816             void
7817             setContextSize( self , size )
7818             SV * self
7819             int size
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 ( size < -1 )
7825 1           croak("XPathContext: invalid size\n");
7826             PPCODE:
7827 3           ctxt->contextSize = size;
7828 3 100         if ( size == 0 )
7829 1           ctxt->proximityPosition = 0;
7830 2 100         else if ( size > 0 )
7831 1           ctxt->proximityPosition = 1;
7832             else
7833 1           ctxt->proximityPosition = -1;
7834              
7835             void
7836             registerNs( pxpath_context, prefix, ns_uri )
7837             SV * pxpath_context
7838             SV * prefix
7839             SV * ns_uri
7840             PREINIT:
7841 11           xmlXPathContextPtr ctxt = NULL;
7842             INIT:
7843 11 50         ctxt = INT2PTR(xmlXPathContextPtr,SvIV(SvRV(pxpath_context)));
7844 11 50         if ( ctxt == NULL ) {
7845 0           croak("XPathContext: missing xpath context\n");
7846             }
7847 11           LibXML_configure_xpathcontext(ctxt);
7848             PPCODE:
7849 11 100         if(SvOK(ns_uri)) {
    50          
    50          
7850 8 50         if(xmlXPathRegisterNs(ctxt, (xmlChar *) SvPV_nolen(prefix),
    50          
    50          
7851 8           (xmlChar *) SvPV_nolen(ns_uri)) == -1) {
7852 0           croak("XPathContext: cannot register namespace\n");
7853             }
7854             } else {
7855 3 50         if(xmlXPathRegisterNs(ctxt, (xmlChar *) SvPV_nolen(prefix), NULL) == -1) {
    50          
7856 0           croak("XPathContext: cannot unregister namespace\n");
7857             }
7858             }
7859              
7860             SV*
7861             lookupNs( pxpath_context, prefix )
7862             SV * pxpath_context
7863             SV * prefix
7864             PREINIT:
7865 3           xmlXPathContextPtr ctxt = NULL;
7866             INIT:
7867 3 50         ctxt = INT2PTR(xmlXPathContextPtr,SvIV(SvRV(pxpath_context)));
7868 3 50         if ( ctxt == NULL ) {
7869 0           croak("XPathContext: missing xpath context\n");
7870             }
7871 3           LibXML_configure_xpathcontext(ctxt);
7872             CODE:
7873 3 50         RETVAL = C2Sv(xmlXPathNsLookup(ctxt, (xmlChar *) SvPV_nolen(prefix)), NULL);
7874             OUTPUT:
7875             RETVAL
7876              
7877             SV*
7878             getVarLookupData( self )
7879             SV * self
7880             INIT:
7881 6 50         xmlXPathContextPtr ctxt = INT2PTR(xmlXPathContextPtr,SvIV(SvRV(self)));
7882 6 50         if ( ctxt == NULL ) {
7883 0           croak("XPathContext: missing xpath context\n");
7884             }
7885             CODE:
7886 6 100         if(XPathContextDATA(ctxt)->varData != NULL) {
7887 5           RETVAL = newSVsv(XPathContextDATA(ctxt)->varData);
7888             } else {
7889 1           RETVAL = &PL_sv_undef;
7890             }
7891             OUTPUT:
7892             RETVAL
7893              
7894             SV*
7895             getVarLookupFunc( self )
7896             SV * self
7897             INIT:
7898 2 50         xmlXPathContextPtr ctxt = INT2PTR(xmlXPathContextPtr,SvIV(SvRV(self)));
7899 2 50         if ( ctxt == NULL ) {
7900 0           croak("XPathContext: missing xpath context\n");
7901             }
7902             CODE:
7903 2 100         if(XPathContextDATA(ctxt)->varData != NULL) {
7904 1           RETVAL = newSVsv(XPathContextDATA(ctxt)->varLookup);
7905             } else {
7906 1           RETVAL = &PL_sv_undef;
7907             }
7908             OUTPUT:
7909             RETVAL
7910              
7911             void
7912             registerVarLookupFunc( pxpath_context, lookup_func, lookup_data )
7913             SV * pxpath_context
7914             SV * lookup_func
7915             SV * lookup_data
7916             PREINIT:
7917 4           xmlXPathContextPtr ctxt = NULL;
7918 4           XPathContextDataPtr data = NULL;
7919             INIT:
7920 4 50         ctxt = INT2PTR(xmlXPathContextPtr,SvIV(SvRV(pxpath_context)));
7921 4 50         if ( ctxt == NULL )
7922 0           croak("XPathContext: missing xpath context\n");
7923 4           data = XPathContextDATA(ctxt);
7924 4 50         if ( data == NULL )
7925 0           croak("XPathContext: missing xpath context private data\n");
7926 4           LibXML_configure_xpathcontext(ctxt);
7927             /* free previous lookup function and data */
7928 4 100         if (data->varLookup && SvOK(data->varLookup))
    50          
    0          
    0          
7929 1           SvREFCNT_dec(data->varLookup);
7930 4 100         if (data->varData && SvOK(data->varData))
    50          
    0          
    0          
7931 1           SvREFCNT_dec(data->varData);
7932 4           data->varLookup=NULL;
7933 4           data->varData=NULL;
7934             PPCODE:
7935 4 100         if (SvOK(lookup_func)) {
    50          
    50          
7936 6 50         if ( SvROK(lookup_func) && SvTYPE(SvRV(lookup_func)) == SVt_PVCV ) {
    50          
7937 3           data->varLookup = newSVsv(lookup_func);
7938 3 100         if (SvOK(lookup_data))
    50          
    50          
7939 2           data->varData = newSVsv(lookup_data);
7940 3           xmlXPathRegisterVariableLookup(ctxt,
7941             LibXML_generic_variable_lookup, ctxt);
7942 3 50         if (ctxt->varLookupData==NULL || ctxt->varLookupData != ctxt) {
    50          
7943 0           croak( "XPathContext: registration failure\n" );
7944             }
7945             } else {
7946 0           croak("XPathContext: 1st argument is not a CODE reference\n");
7947             }
7948             } else {
7949             /* unregister */
7950 1           xmlXPathRegisterVariableLookup(ctxt, NULL, NULL);
7951             }
7952              
7953             void
7954             registerFunctionNS( pxpath_context, name, uri, func)
7955             SV * pxpath_context
7956             char * name
7957             SV * uri
7958             SV * func
7959             PREINIT:
7960 14           xmlXPathContextPtr ctxt = NULL;
7961             SV * pfdr;
7962             SV * key;
7963             STRLEN len;
7964             char *strkey;
7965              
7966             INIT:
7967 14 50         ctxt = INT2PTR(xmlXPathContextPtr,SvIV(SvRV(pxpath_context)));
7968 14 50         if ( ctxt == NULL ) {
7969 0           croak("XPathContext: missing xpath context\n");
7970             }
7971 14           LibXML_configure_xpathcontext(ctxt);
7972 14 100         if ( !SvOK(func) ||
    50          
    50          
    50          
7973 11 0         (SvOK(func) && ((SvROK(func) && SvTYPE(SvRV(func)) == SVt_PVCV )
    0          
    100          
    50          
7974 1 50         || SvPOK(func)))) {
7975 14 100         if (ctxt->funcLookupData == NULL) {
7976 1 50         if (SvOK(func)) {
    0          
    0          
7977 1           pfdr = newRV_noinc((SV*) newHV());
7978 1           ctxt->funcLookupData = pfdr;
7979             } else {
7980             /* looks like no perl function was never registered, */
7981             /* nothing to unregister */
7982 0           warn("XPathContext: nothing to unregister\n");
7983 0           return;
7984             }
7985             } else {
7986 13 50         if (SvTYPE(SvRV((SV *)ctxt->funcLookupData)) == SVt_PVHV) {
7987             /* good, it's a HV */
7988 13           pfdr = (SV *)ctxt->funcLookupData;
7989             } else {
7990 0           croak ("XPathContext: cannot register: funcLookupData structure occupied\n");
7991             }
7992             }
7993 14           key = newSVpvn("",0);
7994 14 100         if (SvOK(uri)) {
    50          
    50          
7995 2           sv_catpv(key, "{");
7996 2           sv_catsv(key, uri);
7997 2           sv_catpv(key, "}");
7998             }
7999 14           sv_catpv(key, (const char*)name);
8000 14 50         strkey = SvPV(key, len);
8001             /* warn("Trying to store function '%s' in %d\n", strkey, pfdr); */
8002 14 100         if (SvOK(func)) {
    50          
    50          
8003 11           (void) hv_store((HV *)SvRV(pfdr),strkey, len, newSVsv(func), 0);
8004             } else {
8005             /* unregister */
8006 3           (void) hv_delete((HV *)SvRV(pfdr),strkey, len, G_DISCARD);
8007             }
8008 14           SvREFCNT_dec(key);
8009             } else {
8010 0           croak("XPathContext: 3rd argument is not a CODE reference or function name\n");
8011             }
8012             PPCODE:
8013 14 100         if (SvOK(uri)) {
    50          
    50          
8014 3 100         xmlXPathRegisterFuncNS(ctxt, (xmlChar *) name,
    50          
8015 4           (xmlChar *) SvPV(uri, len),
8016 1 50         (SvOK(func) ?
    50          
8017             LibXML_generic_extension_function : NULL));
8018             } else {
8019 14 100         xmlXPathRegisterFunc(ctxt, (xmlChar *) name,
8020 2 50         (SvOK(func) ?
    50          
8021             LibXML_generic_extension_function : NULL));
8022             }
8023              
8024             void
8025             _free_node_pool( pxpath_context )
8026             SV * pxpath_context
8027             PREINIT:
8028 130           xmlXPathContextPtr ctxt = NULL;
8029             INIT:
8030 130 50         ctxt = INT2PTR(xmlXPathContextPtr,SvIV(SvRV(pxpath_context)));
8031 130 50         if ( ctxt == NULL ) {
8032 0           croak("XPathContext: missing xpath context\n");
8033             }
8034             PPCODE:
8035 130 100         if (XPathContextDATA(ctxt)->pool != NULL) {
8036 20           SvREFCNT_dec((SV *)XPathContextDATA(ctxt)->pool);
8037 20           XPathContextDATA(ctxt)->pool = NULL;
8038             }
8039              
8040             void
8041             _findnodes( pxpath_context, perl_xpath )
8042             SV * pxpath_context
8043             SV * perl_xpath
8044             PREINIT:
8045 61           xmlXPathContextPtr ctxt = NULL;
8046 61           ProxyNodePtr owner = NULL;
8047 61           xmlXPathObjectPtr found = NULL;
8048 61           xmlNodeSetPtr nodelist = NULL;
8049 61           SV * element = NULL ;
8050 61           xmlChar * xpath = NULL;
8051 61           xmlXPathCompExprPtr comp = NULL;
8052 61           PREINIT_SAVED_ERROR
8053             INIT:
8054 61 50         ctxt = INT2PTR(xmlXPathContextPtr,SvIV(SvRV(pxpath_context)));
8055 61 50         if ( ctxt == NULL ) {
8056 0           croak("XPathContext: missing xpath context\n");
8057             }
8058 61           LibXML_configure_xpathcontext(ctxt);
8059 61 50         if ( ctxt->node == NULL ) {
8060 0           croak("XPathContext: lost current node\n");
8061             }
8062 61 100         if (sv_isobject(perl_xpath) && sv_isa(perl_xpath,"XML::LibXML::XPathExpression")) {
    50          
8063 4 50         comp = INT2PTR(xmlXPathCompExprPtr,SvIV((SV*)SvRV( perl_xpath )));
8064 4 50         if (!comp) XSRETURN_UNDEF;
8065             } else {
8066 57           xpath = nodeSv2C(perl_xpath, ctxt->node);
8067 57 50         if ( !(xpath && xmlStrlen(xpath)) ) {
    50          
8068 0 0         if ( xpath )
8069 0           xmlFree(xpath);
8070 0           croak("XPathContext: empty XPath found\n");
8071             XSRETURN_UNDEF;
8072             }
8073             }
8074             PPCODE:
8075 61           INIT_ERROR_HANDLER;
8076              
8077 61           PUTBACK ;
8078 61 100         if (comp) {
8079 4           found = domXPathCompFindCtxt( ctxt, comp, 0 );
8080             } else {
8081 57           found = domXPathFindCtxt( ctxt, xpath, 0 );
8082 57           xmlFree(xpath);
8083             }
8084 61           SPAGAIN ;
8085              
8086 61 100         if (found != NULL) {
8087 59           nodelist = found->nodesetval;
8088             } else {
8089 2           nodelist = NULL;
8090             }
8091 61           CLEANUP_ERROR_HANDLER;
8092 61 100         if ( nodelist ) {
8093 59           REPORT_ERROR(1);
8094 59 50         if ( nodelist->nodeNr > 0 ) {
8095             int i;
8096 59           const char * cls = "XML::LibXML::Node";
8097             xmlNodePtr tnode;
8098 59           int l = nodelist->nodeNr;
8099 3135 100         for( i = 0 ; i < l; i++){
8100             /* we have to create a new instance of an objectptr.
8101             * and then place the current node into the new object.
8102             * afterwards we can push the object to the array!
8103             */
8104 3076           element = NULL;
8105 3076           tnode = nodelist->nodeTab[i];
8106 3076 50         if (tnode->type == XML_NAMESPACE_DECL) {
8107 0           xmlNsPtr newns = xmlCopyNamespace((xmlNsPtr)tnode);
8108 0 0         if ( newns != NULL ) {
8109 0           element = NEWSV(0,0);
8110 0           cls = PmmNodeTypeName( tnode );
8111 0           element = sv_setref_pv( element,
8112             (const char *)cls,
8113             newns
8114             );
8115             }
8116             else {
8117 0           continue;
8118             }
8119             }
8120             else {
8121 3076 100         if (tnode->doc) {
8122 3073 50         owner = PmmOWNERPO(PmmNewNode((xmlNodePtr) tnode->doc));
    50          
8123             } else {
8124             /* we try to find a known node on the ancestor axis */
8125 3           xmlNodePtr n = tnode;
8126 5 50         while (n && n->_private == NULL) n = n->parent;
    100          
8127 3 50         if (n) owner = PmmOWNERPO(((ProxyNodePtr)n->_private));
    50          
    50          
8128 0           else owner = NULL; /* self contained node */
8129             }
8130 3076           element = PmmNodeToSv(tnode, owner);
8131             }
8132 3076 50         XPUSHs( sv_2mortal(element) );
8133             }
8134             }
8135             /* prevent libxml2 from freeing the actual nodes */
8136 59 50         if (found->boolval) found->boolval=0;
8137 59           xmlXPathFreeObject(found);
8138             }
8139             else {
8140 2           xmlXPathFreeObject(found);
8141 2           REPORT_ERROR(0);
8142             }
8143              
8144             void
8145             _find( pxpath_context, pxpath, to_bool )
8146             SV * pxpath_context
8147             SV * pxpath
8148             int to_bool
8149             PREINIT:
8150 69           xmlXPathContextPtr ctxt = NULL;
8151 69           ProxyNodePtr owner = NULL;
8152 69           xmlXPathObjectPtr found = NULL;
8153 69           xmlNodeSetPtr nodelist = NULL;
8154 69           xmlChar * xpath = NULL;
8155 69           xmlXPathCompExprPtr comp = NULL;
8156 69           PREINIT_SAVED_ERROR
8157             INIT:
8158 69 50         ctxt = INT2PTR(xmlXPathContextPtr,SvIV(SvRV(pxpath_context)));
8159 69 50         if ( ctxt == NULL ) {
8160 0           croak("XPathContext: missing xpath context\n");
8161             }
8162 69           LibXML_configure_xpathcontext(ctxt);
8163 69 100         if ( ctxt->node == NULL ) {
8164 1           croak("XPathContext: lost current node\n");
8165             }
8166 68 100         if (sv_isobject(pxpath) && sv_isa(pxpath,"XML::LibXML::XPathExpression")) {
    50          
8167 3 50         comp = INT2PTR(xmlXPathCompExprPtr,SvIV((SV*)SvRV( pxpath )));
8168 3 50         if (!comp) XSRETURN_UNDEF;
8169             } else {
8170 65           xpath = nodeSv2C(pxpath, ctxt->node);
8171 65 50         if ( !(xpath && xmlStrlen(xpath)) ) {
    50          
8172 0 0         if ( xpath )
8173 0           xmlFree(xpath);
8174 0           croak("XPathContext: empty XPath found\n");
8175             XSRETURN_UNDEF;
8176             }
8177             }
8178             PPCODE:
8179 68           INIT_ERROR_HANDLER;
8180 68           PUTBACK ;
8181 68 100         if (comp) {
8182 3           found = domXPathCompFindCtxt( ctxt, comp, to_bool );
8183             } else {
8184 65           found = domXPathFindCtxt( ctxt, xpath, to_bool );
8185 64           xmlFree(xpath);
8186             }
8187 67           SPAGAIN ;
8188 67           CLEANUP_ERROR_HANDLER;
8189 67 100         if (found) {
8190 59           REPORT_ERROR(1);
8191 59           switch (found->type) {
8192             case XPATH_NODESET:
8193             /* return as a NodeList */
8194             /* access ->nodesetval */
8195 10 50         XPUSHs(sv_2mortal(newSVpv("XML::LibXML::NodeList", 0)));
8196 10           nodelist = found->nodesetval;
8197 10 50         if ( nodelist ) {
8198 10 50         if ( nodelist->nodeNr > 0 ) {
8199             int i;
8200 10           const char * cls = "XML::LibXML::Node";
8201             xmlNodePtr tnode;
8202             SV * element;
8203 10           int l = nodelist->nodeNr;
8204              
8205 6021 100         for( i = 0 ; i < l; i++){
8206             /* we have to create a new instance of an
8207             * objectptr. and then
8208             * place the current node into the new
8209             * object. afterwards we can
8210             * push the object to the array!
8211             */
8212 6011           tnode = nodelist->nodeTab[i];
8213              
8214             /* let's be paranoid */
8215 6011 50         if (tnode->type == XML_NAMESPACE_DECL) {
8216 0           xmlNsPtr newns = xmlCopyNamespace((xmlNsPtr)tnode);
8217 0 0         if ( newns != NULL ) {
8218 0           element = NEWSV(0,0);
8219 0           cls = PmmNodeTypeName( tnode );
8220 0           element = sv_setref_pv( element,
8221             (const char *)cls,
8222             (void*)newns
8223             );
8224             }
8225             else {
8226 0           continue;
8227             }
8228             }
8229             else {
8230 6011 50         if (tnode->doc) {
8231 6011 50         owner = PmmOWNERPO(PmmNewNode((xmlNodePtr) tnode->doc));
    50          
8232             } else {
8233             /* we try to find a known node on the ancestor axis */
8234 0           xmlNodePtr n = tnode;
8235 0 0         while (n && n->_private == NULL) n = n->parent;
    0          
8236 0 0         if (n) owner = PmmOWNERPO(((ProxyNodePtr)n->_private));
    0          
    0          
8237 0           else owner = NULL; /* self contained node */
8238             }
8239 6011           element = PmmNodeToSv(tnode, owner);
8240             }
8241 6011 50         XPUSHs( sv_2mortal(element) );
8242             }
8243             }
8244             }
8245             /* prevent libxml2 from freeing the actual nodes */
8246 10 50         if (found->boolval) found->boolval=0;
8247 10           break;
8248             case XPATH_BOOLEAN:
8249             /* return as a Boolean */
8250             /* access ->boolval */
8251 14 50         XPUSHs(sv_2mortal(newSVpv("XML::LibXML::Boolean", 0)));
8252 14 50         XPUSHs(sv_2mortal(newSViv(found->boolval)));
8253 14           break;
8254             case XPATH_NUMBER:
8255             /* return as a Number */
8256             /* access ->floatval */
8257 24 50         XPUSHs(sv_2mortal(newSVpv("XML::LibXML::Number", 0)));
8258 24 50         XPUSHs(sv_2mortal(newSVnv(found->floatval)));
8259 24           break;
8260             case XPATH_STRING:
8261             /* access ->stringval */
8262             /* return as a Literal */
8263 11 50         XPUSHs(sv_2mortal(newSVpv("XML::LibXML::Literal", 0)));
8264 11 50         XPUSHs(sv_2mortal(C2Sv(found->stringval, NULL)));
8265 11           break;
8266             default:
8267 0           croak("Unknown XPath return type");
8268             }
8269 59           xmlXPathFreeObject(found);
8270             }
8271             else {
8272 8           REPORT_ERROR(0);
8273             }
8274              
8275             MODULE = XML::LibXML PACKAGE = XML::LibXML::InputCallback
8276              
8277             void
8278             lib_cleanup_callbacks( self )
8279             CODE:
8280 677           xmlCleanupInputCallbacks();
8281 677           xmlRegisterDefaultInputCallbacks();
8282              
8283             void
8284             lib_init_callbacks( self )
8285             CODE:
8286 677           xmlRegisterDefaultInputCallbacks(); /* important */
8287 677           xmlRegisterInputCallbacks((xmlInputMatchCallback) LibXML_input_match,
8288             (xmlInputOpenCallback) LibXML_input_open,
8289             (xmlInputReadCallback) LibXML_input_read,
8290             (xmlInputCloseCallback) LibXML_input_close);
8291              
8292             #ifdef HAVE_READER_SUPPORT
8293              
8294             MODULE = XML::LibXML PACKAGE = XML::LibXML::Reader
8295              
8296             xmlTextReaderPtr
8297             _newForFile(CLASS, filename, encoding, options)
8298             const char* CLASS
8299             const char* filename
8300             const char * encoding = SvOK($arg) ? SvPV_nolen($arg) : NULL;
8301             int options = SvOK($arg) ? SvIV($arg) : 0;
8302             CODE:
8303 9           RETVAL = xmlReaderForFile(filename, encoding, options);
8304             INIT_READER_ERROR_HANDLER(RETVAL);
8305             OUTPUT:
8306             RETVAL
8307              
8308             xmlTextReaderPtr
8309             _newForIO(CLASS, fh, url, encoding, options)
8310             const char* CLASS
8311             SV * fh
8312             const char * url = SvOK($arg) ? SvPV_nolen($arg) : NULL;
8313             const char * encoding = SvOK($arg) ? SvPV_nolen($arg) : NULL;
8314             int options = SvOK($arg) ? SvIV($arg) : 0;
8315             CODE:
8316 1           (void)SvREFCNT_inc(fh); /* _dec'd by LibXML_close_perl */
8317 1           RETVAL = xmlReaderForIO((xmlInputReadCallback) LibXML_read_perl,
8318             (xmlInputCloseCallback) LibXML_close_perl,
8319             (void *) fh, url, encoding, options);
8320             INIT_READER_ERROR_HANDLER(RETVAL)
8321             OUTPUT:
8322             RETVAL
8323              
8324             xmlTextReaderPtr
8325             _newForString(CLASS, string, url, encoding, options)
8326             const char* CLASS
8327             SV * string
8328             const char * url = SvOK($arg) ? SvPV_nolen($arg) : NULL;
8329             const char * encoding = SvOK($arg) ? SvPV_nolen($arg) : NULL;
8330             int options = SvOK($arg) ? SvIV($arg) : 0;
8331             CODE:
8332 8 50         if (encoding == NULL && SvUTF8( string )) {
    100          
8333 2           encoding = "UTF-8";
8334             }
8335 8 50         RETVAL = xmlReaderForDoc((xmlChar* )SvPV_nolen(string), url, encoding, options);
8336             INIT_READER_ERROR_HANDLER(RETVAL)
8337             OUTPUT:
8338             RETVAL
8339              
8340             xmlTextReaderPtr
8341             _newForFd(CLASS, fd, url, encoding, options)
8342             const char* CLASS
8343             int fd
8344             const char * url = SvOK($arg) ? SvPV_nolen($arg) : NULL;
8345             const char * encoding = SvOK($arg) ? SvPV_nolen($arg) : NULL;
8346             int options = SvOK($arg) ? SvIV($arg) : 0;
8347             CODE:
8348 1           RETVAL = xmlReaderForFd(fd, url, encoding, options);
8349             INIT_READER_ERROR_HANDLER(RETVAL)
8350             OUTPUT:
8351             RETVAL
8352              
8353             xmlTextReaderPtr
8354             _newForDOM(CLASS, perl_doc)
8355             const char* CLASS
8356             SV * perl_doc
8357             CODE:
8358 1 50         PmmREFCNT_inc(SvPROXYNODE(perl_doc)); /* _dec in DESTROY */
8359 1           RETVAL = xmlReaderWalker((xmlDocPtr) PmmSvNode(perl_doc));
8360             OUTPUT:
8361             RETVAL
8362              
8363             int
8364             attributeCount(reader)
8365             xmlTextReaderPtr reader
8366             CODE:
8367 1           RETVAL = xmlTextReaderAttributeCount(reader);
8368             OUTPUT:
8369             RETVAL
8370              
8371             SV *
8372             baseURI(reader)
8373             xmlTextReaderPtr reader
8374             PREINIT:
8375 1           const xmlChar *result = NULL;
8376             CODE:
8377 1           result = xmlTextReaderConstBaseUri(reader);
8378 1           RETVAL = C2Sv(result, NULL);
8379             OUTPUT:
8380             RETVAL
8381              
8382             long
8383             byteConsumed(reader)
8384             xmlTextReaderPtr reader
8385             CODE:
8386 1           RETVAL = xmlTextReaderByteConsumed(reader);
8387             OUTPUT:
8388             RETVAL
8389              
8390             int
8391             _close(reader)
8392             xmlTextReaderPtr reader
8393             CODE:
8394 1           RETVAL = xmlTextReaderClose(reader);
8395             OUTPUT:
8396             RETVAL
8397              
8398             SV *
8399             encoding(reader)
8400             xmlTextReaderPtr reader
8401             PREINIT:
8402 1           const xmlChar *result = NULL;
8403             CODE:
8404 1           result = xmlTextReaderConstEncoding(reader);
8405 1           RETVAL = C2Sv(result, NULL);
8406             OUTPUT:
8407             RETVAL
8408              
8409             SV *
8410             localName(reader)
8411             xmlTextReaderPtr reader
8412             PREINIT:
8413 2           const xmlChar *result = NULL;
8414             CODE:
8415 2           result = xmlTextReaderConstLocalName(reader);
8416 2           RETVAL = C2Sv(result, NULL);
8417             OUTPUT:
8418             RETVAL
8419              
8420             SV *
8421             name(reader)
8422             xmlTextReaderPtr reader
8423             PREINIT:
8424 46           const xmlChar *result = NULL;
8425             CODE:
8426 46           result = xmlTextReaderConstName(reader);
8427 46           RETVAL = C2Sv(result, NULL);
8428             OUTPUT:
8429             RETVAL
8430              
8431             SV *
8432             namespaceURI(reader)
8433             xmlTextReaderPtr reader
8434             PREINIT:
8435 36           const xmlChar *result = NULL;
8436             CODE:
8437 36           result = xmlTextReaderConstNamespaceUri(reader);
8438 36           RETVAL = C2Sv(result, NULL);
8439             OUTPUT:
8440             RETVAL
8441              
8442             SV *
8443             prefix(reader)
8444             xmlTextReaderPtr reader
8445             PREINIT:
8446 2           const xmlChar *result = NULL;
8447             CODE:
8448 2           result = xmlTextReaderConstPrefix(reader);
8449 2           RETVAL = C2Sv(result, NULL);
8450             OUTPUT:
8451             RETVAL
8452              
8453             SV *
8454             value(reader)
8455             xmlTextReaderPtr reader
8456             PREINIT:
8457 29           const xmlChar *result = NULL;
8458             CODE:
8459 29           result = xmlTextReaderConstValue(reader);
8460 29           RETVAL = C2Sv(result, NULL);
8461             OUTPUT:
8462             RETVAL
8463              
8464             SV *
8465             xmlLang(reader)
8466             xmlTextReaderPtr reader
8467             PREINIT:
8468 2           const xmlChar *result = NULL;
8469             CODE:
8470 2           result = xmlTextReaderConstXmlLang(reader);
8471 2           RETVAL = C2Sv(result, NULL);
8472             OUTPUT:
8473             RETVAL
8474              
8475              
8476             SV *
8477             xmlVersion(reader)
8478             xmlTextReaderPtr reader
8479             PREINIT:
8480 1           const xmlChar *result = NULL;
8481             CODE:
8482 1           result = xmlTextReaderConstXmlVersion(reader);
8483 1           RETVAL = C2Sv(result, NULL);
8484             OUTPUT:
8485             RETVAL
8486              
8487              
8488             int
8489             depth(reader)
8490             xmlTextReaderPtr reader
8491             CODE:
8492 1           RETVAL = xmlTextReaderDepth(reader);
8493             OUTPUT:
8494             RETVAL
8495              
8496              
8497             SV *
8498             getAttribute(reader, name)
8499             xmlTextReaderPtr reader
8500             char * name
8501             PREINIT:
8502 1           xmlChar *result = NULL;
8503             CODE:
8504 1           result = xmlTextReaderGetAttribute(reader, (xmlChar*) name);
8505 1           RETVAL = C2Sv(result, NULL);
8506 1           xmlFree(result);
8507             OUTPUT:
8508             RETVAL
8509              
8510             SV *
8511             getAttributeNo(reader, no)
8512             xmlTextReaderPtr reader
8513             int no
8514             PREINIT:
8515 1           xmlChar *result = NULL;
8516             CODE:
8517 1           result = xmlTextReaderGetAttributeNo(reader, no);
8518 1           RETVAL = C2Sv(result, NULL);
8519 1           xmlFree(result);
8520             OUTPUT:
8521             RETVAL
8522              
8523             SV *
8524             getAttributeNs(reader, localName, namespaceURI)
8525             xmlTextReaderPtr reader
8526             char * localName
8527             char * namespaceURI = SvOK($arg) ? SvPV_nolen($arg) : NULL;
8528             PREINIT:
8529 1           xmlChar *result = NULL;
8530             CODE:
8531 1           result = xmlTextReaderGetAttributeNs(reader, (xmlChar*) localName,
8532             (xmlChar*) namespaceURI);
8533 1           RETVAL = C2Sv(result, NULL);
8534 1           xmlFree(result);
8535             OUTPUT:
8536             RETVAL
8537              
8538             int
8539             columnNumber(reader)
8540             xmlTextReaderPtr reader
8541             CODE:
8542 1           RETVAL = xmlTextReaderGetParserColumnNumber(reader);
8543             OUTPUT:
8544             RETVAL
8545              
8546             int
8547             lineNumber(reader)
8548             xmlTextReaderPtr reader
8549             CODE:
8550 1           RETVAL = xmlTextReaderGetParserLineNumber(reader);
8551             OUTPUT:
8552             RETVAL
8553              
8554             int
8555             _getParserProp(reader, prop)
8556             xmlTextReaderPtr reader
8557             int prop
8558             CODE:
8559 1           RETVAL = xmlTextReaderGetParserProp(reader, prop);
8560             OUTPUT:
8561             RETVAL
8562              
8563             int
8564             hasAttributes(reader)
8565             xmlTextReaderPtr reader
8566             CODE:
8567 1           RETVAL = xmlTextReaderHasAttributes(reader);
8568             OUTPUT:
8569             RETVAL
8570              
8571             int
8572             hasValue(reader)
8573             xmlTextReaderPtr reader
8574             CODE:
8575 1           RETVAL = xmlTextReaderHasValue(reader);
8576             OUTPUT:
8577             RETVAL
8578              
8579             SV*
8580             getAttributeHash(reader)
8581             xmlTextReaderPtr reader
8582             PREINIT:
8583             HV* hv;
8584             SV* sv;
8585             const xmlChar* name;
8586 0           PREINIT_SAVED_ERROR
8587             CODE:
8588 0           INIT_ERROR_HANDLER;
8589 0           hv=newHV();
8590 0 0         if (xmlTextReaderHasAttributes(reader) && xmlTextReaderMoveToFirstAttribute(reader)==1) {
    0          
8591             do {
8592 0           name = xmlTextReaderConstName(reader);
8593 0           sv=C2Sv((xmlTextReaderConstValue(reader)),NULL);
8594 0 0         if (sv && hv_store(hv, (const char*) name, xmlStrlen(name), sv, 0)==NULL) {
    0          
8595 0           SvREFCNT_dec(sv); /* free if not needed by hv_stores */
8596             }
8597 0 0         } while (xmlTextReaderMoveToNextAttribute(reader)==1);
8598 0           xmlTextReaderMoveToElement(reader);
8599             }
8600 0           RETVAL=newRV_noinc((SV*)hv);
8601 0           CLEANUP_ERROR_HANDLER;
8602 0           REPORT_ERROR(0);
8603             OUTPUT:
8604             RETVAL
8605              
8606             int
8607             isDefault(reader)
8608             xmlTextReaderPtr reader
8609             CODE:
8610 1           RETVAL = xmlTextReaderIsDefault(reader);
8611             OUTPUT:
8612             RETVAL
8613              
8614             int
8615             isEmptyElement(reader)
8616             xmlTextReaderPtr reader
8617             CODE:
8618 1           RETVAL = xmlTextReaderIsEmptyElement(reader);
8619             OUTPUT:
8620             RETVAL
8621              
8622             int
8623             isNamespaceDecl(reader)
8624             xmlTextReaderPtr reader
8625             CODE:
8626 1           RETVAL = xmlTextReaderIsNamespaceDecl(reader);
8627             OUTPUT:
8628             RETVAL
8629              
8630             int
8631             isValid(reader)
8632             xmlTextReaderPtr reader
8633             CODE:
8634 1           RETVAL = xmlTextReaderIsValid(reader);
8635             OUTPUT:
8636             RETVAL
8637              
8638             SV *
8639             lookupNamespace(reader, prefix)
8640             xmlTextReaderPtr reader
8641             char * prefix = SvOK($arg) ? SvPV_nolen($arg) : NULL;
8642             PREINIT:
8643 1           xmlChar *result = NULL;
8644             CODE:
8645 1           result = xmlTextReaderLookupNamespace(reader, (xmlChar*) prefix);
8646 1           RETVAL = C2Sv(result, NULL);
8647 1           xmlFree(result);
8648             OUTPUT:
8649             RETVAL
8650              
8651              
8652             int
8653             moveToAttribute(reader, name)
8654             xmlTextReaderPtr reader
8655             char * name
8656             CODE:
8657 1           RETVAL = xmlTextReaderMoveToAttribute(reader, (xmlChar*) name);
8658             OUTPUT:
8659             RETVAL
8660              
8661             int
8662             moveToAttributeNo(reader, no)
8663             xmlTextReaderPtr reader
8664             int no
8665             CODE:
8666 1           RETVAL = xmlTextReaderMoveToAttributeNo(reader, no);
8667             OUTPUT:
8668             RETVAL
8669              
8670             int
8671             moveToAttributeNs(reader, localName, namespaceURI)
8672             xmlTextReaderPtr reader
8673             char * localName
8674             char * namespaceURI = SvOK($arg) ? SvPV_nolen($arg) : NULL;
8675             CODE:
8676 1           RETVAL = xmlTextReaderMoveToAttributeNs(reader,
8677             (xmlChar*) localName, (xmlChar*) namespaceURI);
8678             OUTPUT:
8679             RETVAL
8680              
8681             int
8682             moveToElement(reader)
8683             xmlTextReaderPtr reader
8684             CODE:
8685 2           RETVAL = xmlTextReaderMoveToElement(reader);
8686             OUTPUT:
8687             RETVAL
8688              
8689             int
8690             moveToFirstAttribute(reader)
8691             xmlTextReaderPtr reader
8692             CODE:
8693 1           RETVAL = xmlTextReaderMoveToFirstAttribute(reader);
8694             OUTPUT:
8695             RETVAL
8696              
8697             int
8698             moveToNextAttribute(reader)
8699             xmlTextReaderPtr reader
8700             CODE:
8701 1           RETVAL = xmlTextReaderMoveToNextAttribute(reader);
8702             OUTPUT:
8703             RETVAL
8704              
8705             int
8706             next(reader)
8707             xmlTextReaderPtr reader
8708             PREINIT:
8709 1           PREINIT_SAVED_ERROR
8710             CODE:
8711 1           INIT_ERROR_HANDLER;
8712 1           RETVAL = xmlTextReaderNext(reader);
8713 1           CLEANUP_ERROR_HANDLER;
8714 1           REPORT_ERROR(0);
8715             OUTPUT:
8716             RETVAL
8717              
8718             #define LIBXML_READER_NEXT_SIBLING(ret,reader) \
8719             ret = xmlTextReaderNextSibling(reader); \
8720             if (ret == -1) \
8721             { \
8722             int depth; \
8723             depth = xmlTextReaderDepth(reader); \
8724             ret = xmlTextReaderRead(reader); \
8725             while (ret == 1 && xmlTextReaderDepth(reader) > depth) { \
8726             ret = xmlTextReaderNext(reader); \
8727             } \
8728             if (ret == 1) { \
8729             if (xmlTextReaderDepth(reader) != depth) { \
8730             ret = 0; \
8731             } else if (xmlTextReaderNodeType(reader) == XML_READER_TYPE_END_ELEMENT) { \
8732             ret = xmlTextReaderRead(reader); \
8733             } \
8734             } \
8735             }
8736              
8737             int
8738             nextSibling(reader)
8739             xmlTextReaderPtr reader
8740             PREINIT:
8741 2           PREINIT_SAVED_ERROR
8742             CODE:
8743 2           INIT_ERROR_HANDLER;
8744 10 50         LIBXML_READER_NEXT_SIBLING(RETVAL,reader)
    50          
    100          
    50          
    50          
    50          
8745 2           CLEANUP_ERROR_HANDLER;
8746 2           REPORT_ERROR(0);
8747             OUTPUT:
8748             RETVAL
8749              
8750             int
8751             nextSiblingElement(reader, name = NULL, nsURI = NULL)
8752             xmlTextReaderPtr reader
8753             const char * name
8754             const char * nsURI
8755             PREINIT:
8756 1           PREINIT_SAVED_ERROR
8757             CODE:
8758 1           INIT_ERROR_HANDLER;
8759             do {
8760 10 50         LIBXML_READER_NEXT_SIBLING(RETVAL,reader)
    50          
    100          
    50          
    50          
    100          
8761 6 100         if (LIBXML_READER_TEST_ELEMENT(reader,name,nsURI)) {
    50          
    0          
    50          
    0          
    50          
    100          
    50          
    50          
8762             break;
8763             }
8764 5 50         } while (RETVAL == 1);
8765 1           CLEANUP_ERROR_HANDLER;
8766 1           REPORT_ERROR(0);
8767             OUTPUT:
8768             RETVAL
8769              
8770             int
8771             nextElement(reader, name = NULL, nsURI = NULL)
8772             xmlTextReaderPtr reader
8773             const char * name
8774             const char * nsURI
8775             PREINIT:
8776 6           PREINIT_SAVED_ERROR
8777             CODE:
8778 6           INIT_ERROR_HANDLER;
8779             do {
8780 10           RETVAL = xmlTextReaderRead(reader);
8781 10 100         if (LIBXML_READER_TEST_ELEMENT(reader,name,nsURI)) {
    50          
    100          
    50          
    50          
    0          
    0          
    0          
    0          
8782             break;
8783             }
8784 4 50         } while (RETVAL == 1);
8785 6           CLEANUP_ERROR_HANDLER;
8786 6           REPORT_ERROR(0);
8787             OUTPUT:
8788             RETVAL
8789              
8790             int
8791             nextPatternMatch(reader, compiled)
8792             xmlTextReaderPtr reader
8793             xmlPatternPtr compiled
8794             PREINIT:
8795 5           PREINIT_SAVED_ERROR
8796 5           xmlNodePtr node = NULL;
8797             CODE:
8798 5 50         if ( compiled == NULL )
8799 0           croak("Usage: $reader->nextPatternMatch( a-XML::LibXML::Pattern-object )");
8800             do {
8801 42           RETVAL = xmlTextReaderRead(reader);
8802 42           node = xmlTextReaderCurrentNode(reader);
8803 42 100         if (node && xmlPatternMatch(compiled, node)) {
    100          
8804 4           break;
8805             }
8806 38 100         } while (RETVAL == 1);
8807 5           CLEANUP_ERROR_HANDLER;
8808 5           REPORT_ERROR(0);
8809             OUTPUT:
8810             RETVAL
8811              
8812             int
8813             skipSiblings(reader)
8814             xmlTextReaderPtr reader
8815             PREINIT:
8816             int depth;
8817             PREINIT:
8818 1           PREINIT_SAVED_ERROR
8819             CODE:
8820 1           INIT_ERROR_HANDLER;
8821 1           depth = xmlTextReaderDepth(reader);
8822 1           RETVAL = -1;
8823 1 50         if (depth > 0) {
8824             do {
8825 3           RETVAL = xmlTextReaderNext(reader);
8826 3 50         } while (RETVAL == 1 && xmlTextReaderDepth(reader) >= depth);
    100          
8827 1 50         if (xmlTextReaderNodeType(reader) != XML_READER_TYPE_END_ELEMENT) {
8828 0           RETVAL = -1;
8829             }
8830             }
8831 1           CLEANUP_ERROR_HANDLER;
8832 1           REPORT_ERROR(0);
8833             OUTPUT:
8834             RETVAL
8835              
8836             int
8837             nodeType(reader)
8838             xmlTextReaderPtr reader
8839             CODE:
8840 179           RETVAL = xmlTextReaderNodeType(reader);
8841             OUTPUT:
8842             RETVAL
8843              
8844             SV*
8845             quoteChar(reader)
8846             xmlTextReaderPtr reader
8847             PREINIT:
8848             int ret;
8849             CODE:
8850 0           ret = xmlTextReaderQuoteChar(reader);
8851 0 0         if (ret == -1) XSRETURN_UNDEF;
8852 0           RETVAL = newSVpvf("%c",ret);
8853             OUTPUT:
8854             RETVAL
8855              
8856             int
8857             read(reader)
8858             xmlTextReaderPtr reader
8859             PREINIT:
8860 199           PREINIT_SAVED_ERROR
8861             CODE:
8862 199           INIT_ERROR_HANDLER;
8863 199           RETVAL = xmlTextReaderRead(reader);
8864 199           CLEANUP_ERROR_HANDLER;
8865 199           REPORT_ERROR(0);
8866             OUTPUT:
8867             RETVAL
8868              
8869             int
8870             readAttributeValue(reader)
8871             xmlTextReaderPtr reader
8872             PREINIT:
8873 1           PREINIT_SAVED_ERROR
8874             CODE:
8875 1           INIT_ERROR_HANDLER;
8876 1           RETVAL = xmlTextReaderReadAttributeValue(reader);
8877 1           CLEANUP_ERROR_HANDLER;
8878 1           REPORT_ERROR(0);
8879             OUTPUT:
8880             RETVAL
8881              
8882              
8883             SV *
8884             readInnerXml(reader)
8885             xmlTextReaderPtr reader
8886             PREINIT:
8887 1           xmlChar *result = NULL;
8888             PREINIT:
8889 1           PREINIT_SAVED_ERROR
8890             CODE:
8891 1           INIT_ERROR_HANDLER;
8892 1           result = xmlTextReaderReadInnerXml(reader);
8893 1           CLEANUP_ERROR_HANDLER;
8894 1           REPORT_ERROR(0);
8895 1 50         if (!result) XSRETURN_UNDEF;
8896 1           RETVAL = C2Sv(result, NULL);
8897 1           xmlFree(result);
8898             OUTPUT:
8899             RETVAL
8900              
8901             SV *
8902             readOuterXml(reader)
8903             xmlTextReaderPtr reader
8904             PREINIT:
8905 3           xmlChar *result = NULL;
8906             PREINIT:
8907 3           PREINIT_SAVED_ERROR
8908             CODE:
8909 3           INIT_ERROR_HANDLER;
8910 3           result = xmlTextReaderReadOuterXml(reader);
8911 3           CLEANUP_ERROR_HANDLER;
8912 3           REPORT_ERROR(0);
8913 3 50         if (result) {
8914 3           RETVAL = C2Sv(result, NULL);
8915 3           xmlFree(result);
8916             } else {
8917 0           XSRETURN_UNDEF;
8918             }
8919             OUTPUT:
8920             RETVAL
8921              
8922             int
8923             readState(reader)
8924             xmlTextReaderPtr reader
8925             CODE:
8926 1           RETVAL = xmlTextReaderReadState(reader);
8927             OUTPUT:
8928             RETVAL
8929              
8930             int
8931             _setParserProp(reader, prop, value)
8932             xmlTextReaderPtr reader
8933             int prop
8934             int value
8935             CODE:
8936 0           RETVAL = xmlTextReaderSetParserProp(reader, prop, value);
8937             OUTPUT:
8938             RETVAL
8939              
8940             int
8941             standalone(reader)
8942             xmlTextReaderPtr reader
8943             CODE:
8944 1           RETVAL = xmlTextReaderStandalone(reader);
8945             OUTPUT:
8946             RETVAL
8947              
8948             SV *
8949             _nodePath(reader)
8950             xmlTextReaderPtr reader
8951             PREINIT:
8952 8           xmlNodePtr node = NULL;
8953 8           xmlChar * path = NULL;
8954             CODE:
8955 8           node = xmlTextReaderCurrentNode(reader);
8956 8 50         if ( node ==NULL ) {
8957 0           XSRETURN_UNDEF;
8958             }
8959 8           path = xmlGetNodePath( node );
8960 8 50         if ( path == NULL ) {
8961 0           XSRETURN_UNDEF;
8962             }
8963 8           RETVAL = C2Sv(path,NULL);
8964 8           xmlFree(path);
8965             OUTPUT:
8966             RETVAL
8967              
8968             #ifdef LIBXML_PATTERN_ENABLED
8969              
8970             int
8971             matchesPattern(reader, compiled)
8972             xmlTextReaderPtr reader
8973             xmlPatternPtr compiled
8974             PREINIT:
8975 41           xmlNodePtr node = NULL;
8976             CODE:
8977 41 50         if ( compiled == NULL )
8978 0           XSRETURN_UNDEF;
8979 41           node = xmlTextReaderCurrentNode(reader);
8980 41 50         if ( node ==NULL ) {
8981 0           XSRETURN_UNDEF;
8982             }
8983 41           RETVAL = xmlPatternMatch(compiled, node);
8984             OUTPUT:
8985             RETVAL
8986              
8987             #endif /* LIBXML_PATTERN_ENABLED */
8988              
8989             SV *
8990             copyCurrentNode(reader,expand = 0)
8991             xmlTextReaderPtr reader
8992             int expand
8993             PREINIT:
8994 2           xmlNodePtr node = NULL;
8995             xmlNodePtr copy;
8996 2           xmlDocPtr doc = NULL;
8997             ProxyNodePtr proxy;
8998             PREINIT:
8999 2           PREINIT_SAVED_ERROR
9000             CODE:
9001 2           INIT_ERROR_HANDLER;
9002 2 100         if (expand) {
9003 1           node = xmlTextReaderExpand(reader);
9004             }
9005             else {
9006 1           node = xmlTextReaderCurrentNode(reader);
9007             }
9008 2 50         if (node) {
9009 2           doc = xmlTextReaderCurrentDoc(reader);
9010             }
9011 2 50         if (!doc) {
9012 0           CLEANUP_ERROR_HANDLER;
9013 0           REPORT_ERROR(0);
9014 0           XSRETURN_UNDEF;
9015             }
9016 2 50         if (xmlTextReaderGetParserProp(reader,XML_PARSER_VALIDATE))
9017 0 0         PmmInvalidatePSVI(doc); /* the document may have psvi info */
    0          
9018              
9019 2           copy = PmmCloneNode( node, expand );
9020 2 50         if ( copy == NULL ) {
9021 0           CLEANUP_ERROR_HANDLER;
9022 0           REPORT_ERROR(0);
9023 0           XSRETURN_UNDEF;
9024             }
9025 2 50         if ( copy->type == XML_DTD_NODE ) {
9026 0           RETVAL = PmmNodeToSv(copy, NULL);
9027             }
9028             else {
9029 2           ProxyNodePtr docfrag = NULL;
9030              
9031 2 50         if ( doc != NULL ) {
9032 2           xmlSetTreeDoc(copy, doc);
9033             }
9034 2           proxy = PmmNewNode((xmlNodePtr)doc);
9035 2 100         if (PmmREFCNT(proxy) == 0) {
9036 1           PmmREFCNT_inc(proxy);
9037             }
9038 2           LibXML_set_reader_preserve_flag(reader);
9039              
9040 2           docfrag = PmmNewFragment( doc );
9041 2           xmlAddChild( PmmNODE(docfrag), copy );
9042 2           RETVAL = PmmNodeToSv(copy, docfrag);
9043             }
9044 2           CLEANUP_ERROR_HANDLER;
9045 2           REPORT_ERROR(0);
9046             OUTPUT:
9047             RETVAL
9048              
9049             SV *
9050             document(reader)
9051             xmlTextReaderPtr reader
9052             PREINIT:
9053 3           xmlDocPtr doc = NULL;
9054             CODE:
9055 3           doc = xmlTextReaderCurrentDoc(reader);
9056 3 50         if (!doc) XSRETURN_UNDEF;
9057 3           RETVAL = PmmNodeToSv((xmlNodePtr)doc, NULL);
9058             /* FIXME: taint the document with PmmInvalidatePSVI if the reader did validation */
9059 3 50         if ( PmmREFCNT(SvPROXYNODE(RETVAL))==1 ) {
    50          
9060             /* will be decremented in Reader destructor */
9061 0 0         PmmREFCNT_inc(SvPROXYNODE(RETVAL));
9062             }
9063 3 100         if (xmlTextReaderGetParserProp(reader,XML_PARSER_VALIDATE))
9064 2 50         PmmInvalidatePSVI(doc); /* the document may have psvi info */
    50          
9065              
9066 3           LibXML_set_reader_preserve_flag(reader);
9067              
9068             OUTPUT:
9069             RETVAL
9070              
9071             int
9072             _preservePattern(reader,pattern,ns_map=NULL)
9073             xmlTextReaderPtr reader
9074             char * pattern
9075             AV * ns_map
9076             PREINIT:
9077 2           xmlChar** namespaces = NULL;
9078             SV** aux;
9079             int last,i;
9080             CODE:
9081 2 100         if (ns_map) {
9082 1           last = av_len(ns_map);
9083 1 50         New(0,namespaces, last+2, xmlChar*);
9084 3 100         for( i = 0; i <= last ; i++ ) {
9085 2           aux = av_fetch(ns_map,i,0);
9086 2 50         namespaces[i]=(xmlChar*) SvPV_nolen(*aux);
9087             }
9088 1           namespaces[i]=0;
9089             }
9090 2           RETVAL = xmlTextReaderPreservePattern(reader,(const xmlChar*) pattern,
9091             (const xmlChar**)namespaces);
9092 2           Safefree(namespaces);
9093             OUTPUT:
9094             RETVAL
9095              
9096             SV *
9097             preserveNode(reader)
9098             xmlTextReaderPtr reader
9099             PREINIT:
9100             xmlNodePtr node;
9101             xmlDocPtr doc;
9102             ProxyNodePtr proxy;
9103 1           PREINIT_SAVED_ERROR
9104             CODE:
9105 1           INIT_ERROR_HANDLER;
9106 1           doc = xmlTextReaderCurrentDoc(reader);
9107 1 50         if (!doc) {
9108 0           CLEANUP_ERROR_HANDLER;
9109 0           REPORT_ERROR(0);
9110 0           XSRETURN_UNDEF;
9111             }
9112 1           proxy = PmmNewNode((xmlNodePtr)doc);
9113 1 50         if ( PmmREFCNT(proxy) == 0 ) {
9114             /* new proxy node */
9115 0           PmmREFCNT_inc(proxy);
9116             }
9117 1           LibXML_set_reader_preserve_flag(reader);
9118              
9119 1           node = xmlTextReaderPreserve(reader);
9120 1           CLEANUP_ERROR_HANDLER;
9121 1           REPORT_ERROR(0);
9122 1 50         if (node) {
9123 1           RETVAL = PmmNodeToSv(node, proxy);
9124             } else {
9125 0           XSRETURN_UNDEF;
9126             }
9127             OUTPUT:
9128             RETVAL
9129              
9130             int
9131             finish(reader)
9132             xmlTextReaderPtr reader
9133             PREINIT:
9134 10           PREINIT_SAVED_ERROR
9135             CODE:
9136 10           INIT_ERROR_HANDLER;
9137             while (1) {
9138 102           RETVAL = xmlTextReaderRead(reader);
9139 102 100         if (RETVAL!=1) break;
9140 92           }
9141 10           CLEANUP_ERROR_HANDLER;
9142 10           REPORT_ERROR(0);
9143 5           RETVAL++; /* we want 0 - fail, 1- success */
9144             OUTPUT:
9145             RETVAL
9146              
9147             #ifdef HAVE_SCHEMAS
9148              
9149             int
9150             _setRelaxNGFile(reader,rng)
9151             xmlTextReaderPtr reader
9152             char* rng
9153             CODE:
9154 2           RETVAL = xmlTextReaderRelaxNGValidate(reader,rng);
9155             OUTPUT:
9156             RETVAL
9157              
9158             int
9159             _setRelaxNG(reader,rng_doc)
9160             xmlTextReaderPtr reader
9161             xmlRelaxNGPtr rng_doc
9162             CODE:
9163 2           RETVAL = xmlTextReaderRelaxNGSetSchema(reader,rng_doc);
9164             OUTPUT:
9165             RETVAL
9166              
9167             int
9168             _setXSDFile(reader,xsd)
9169             xmlTextReaderPtr reader
9170             char* xsd
9171             CODE:
9172 2           RETVAL = xmlTextReaderSchemaValidate(reader,xsd);
9173             OUTPUT:
9174             RETVAL
9175              
9176             int
9177             _setXSD(reader,xsd_doc)
9178             xmlTextReaderPtr reader
9179             xmlSchemaPtr xsd_doc
9180             CODE:
9181 2           RETVAL = xmlTextReaderSetSchema(reader,xsd_doc);
9182             OUTPUT:
9183             RETVAL
9184              
9185             #endif /* HAVE_SCHEMAS */
9186              
9187             void
9188             _DESTROY(reader)
9189             xmlTextReaderPtr reader
9190             PREINIT:
9191             xmlDocPtr doc;
9192             ProxyNodePtr proxy;
9193             /* SV * error_sv = NULL;
9194             xmlTextReaderErrorFunc f = NULL; */
9195             CODE:
9196              
9197 20 100         if ( LibXML_get_reader_preserve_flag(reader) ) {
9198 2           doc = xmlTextReaderCurrentDoc(reader);
9199 2 50         if (doc) {
9200 2           proxy = PmmNewNode((xmlNodePtr)doc);
9201 2 50         if ( PmmREFCNT(proxy) == 0 ) {
9202 0           PmmREFCNT_inc(proxy);
9203             }
9204 2           PmmREFCNT_dec(proxy);
9205             }
9206             }
9207 20 100         if (xmlTextReaderReadState(reader) != XML_TEXTREADER_MODE_CLOSED) {
9208 19           xmlTextReaderClose(reader);
9209             }
9210             /* xmlTextReaderGetErrorHandler(reader, &f, (void **) &error_sv);
9211             if (error_sv) {
9212             sv_2mortal(error_sv);
9213             } */
9214 20           xmlFreeTextReader(reader);
9215              
9216             #endif /* HAVE_READER_SUPPORT */
9217              
9218             #ifdef WITH_SERRORS
9219              
9220             MODULE = XML::LibXML PACKAGE = XML::LibXML::LibError
9221              
9222             int
9223             domain( self )
9224             xmlErrorPtr self
9225             CODE:
9226 461           RETVAL = self->domain;
9227             OUTPUT:
9228             RETVAL
9229              
9230             int
9231             code( self )
9232             xmlErrorPtr self
9233             CODE:
9234 461           RETVAL = self->code;
9235             OUTPUT:
9236             RETVAL
9237              
9238             int
9239             line( self )
9240             xmlErrorPtr self
9241             CODE:
9242 461           RETVAL = self->line;
9243             OUTPUT:
9244             RETVAL
9245              
9246             int
9247             num1( self )
9248             xmlErrorPtr self
9249             ALIAS:
9250             int1 = 1
9251             CODE:
9252             PERL_UNUSED_VAR(ix);
9253 461           RETVAL = self->int1;
9254             OUTPUT:
9255             RETVAL
9256              
9257             int
9258             num2( self )
9259             xmlErrorPtr self
9260             ALIAS:
9261             int2 = 1
9262             CODE:
9263             PERL_UNUSED_VAR(ix);
9264 461           RETVAL = self->int2;
9265             OUTPUT:
9266             RETVAL
9267              
9268             int
9269             level( self )
9270             xmlErrorPtr self
9271             CODE:
9272 461           RETVAL = (int)self->level;
9273             OUTPUT:
9274             RETVAL
9275              
9276             char *
9277             message( self )
9278             xmlErrorPtr self
9279             CODE:
9280 461           RETVAL = self->message;
9281             OUTPUT:
9282             RETVAL
9283              
9284             char *
9285             file( self )
9286             xmlErrorPtr self
9287             CODE:
9288 461           RETVAL = (char*)self->file;
9289             OUTPUT:
9290             RETVAL
9291              
9292             char *
9293             str1( self )
9294             xmlErrorPtr self
9295             CODE:
9296 461           RETVAL = (char*)self->str1;
9297             OUTPUT:
9298             RETVAL
9299              
9300             char *
9301             str2( self )
9302             xmlErrorPtr self
9303             CODE:
9304 461           RETVAL = (char*)self->str2;
9305             OUTPUT:
9306             RETVAL
9307              
9308             char *
9309             str3( self )
9310             xmlErrorPtr self
9311             CODE:
9312 461           RETVAL = (char*)self->str3;
9313             OUTPUT:
9314             RETVAL
9315              
9316             void
9317             context_and_column( self )
9318             xmlErrorPtr self
9319             PREINIT:
9320             xmlParserInputPtr input;
9321             const xmlChar *cur, *base, *col_cur;
9322             unsigned int n, col; /* GCC warns if signed, because compared with sizeof() */
9323             xmlChar content[81]; /* space for 80 chars + line terminator */
9324             xmlChar *ctnt;
9325             int domain;
9326 461           xmlParserCtxtPtr ctxt = NULL;
9327             PPCODE:
9328 461           domain = self->domain;
9329 461 100         if ((domain == XML_FROM_PARSER) || (domain == XML_FROM_HTML) ||
    100          
    100          
9330 76 100         (domain == XML_FROM_DTD) || (domain == XML_FROM_NAMESPACE) ||
    100          
9331 69 100         (domain == XML_FROM_IO) || (domain == XML_FROM_VALID)) {
9332 402           ctxt = (xmlParserCtxtPtr) self->ctxt;
9333             }
9334 461 100         if (ctxt == NULL) XSRETURN_EMPTY;
9335 396           input = ctxt->input;
9336 396 100         if ((input != NULL) && (input->filename == NULL) &&
    100          
    50          
9337 128           (ctxt->inputNr > 1)) {
9338 0           input = ctxt->inputTab[ctxt->inputNr - 2];
9339             }
9340 396 100         if (input == NULL) XSRETURN_EMPTY;
9341 394           cur = input->cur;
9342 394           base = input->base;
9343             /* skip backwards over any end-of-lines */
9344 404 100         while ((cur > base) && ((*(cur) == '\n') || (*(cur) == '\r'))) {
    100          
    50          
9345 10           cur--;
9346             }
9347 394           n = 0;
9348             /* search backwards for beginning-of-line (to max buff size) */
9349 17471 100         while ((n++ < (sizeof(content)-1)) && (cur > base) &&
    100          
    100          
9350 17077 50         (*(cur) != '\n') && (*(cur) != '\r'))
9351 17077           cur--;
9352             /* search backwards for beginning-of-line for calculating the
9353             * column. */
9354 394           col_cur = cur;
9355 29212 100         while ((col_cur > base) && (*(col_cur) != '\n') && (*(col_cur) != '\r'))
    100          
    50          
9356 28818           col_cur--;
9357 394 100         if ((*(cur) == '\n') || (*(cur) == '\r')) cur++;
    50          
9358 394 100         if ((*(col_cur) == '\n') || (*(col_cur) == '\r')) col_cur++;
    50          
9359             /* calculate the error position in terms of the current position */
9360 394           col = input->cur - col_cur;
9361             /* search forward for end-of-line (to max buff size) */
9362 394           n = 0;
9363 394           ctnt = content;
9364             /* copy selected text to our buffer */
9365 21811 100         while ((*cur != 0) && (*(cur) != '\n') &&
    100          
    50          
9366 21612 100         (*(cur) != '\r') && (n < sizeof(content)-1)) {
9367 21417           *ctnt++ = *cur++;
9368 21417           n++;
9369             }
9370 394           *ctnt = 0;
9371 394 50         EXTEND(SP,2);
9372 394           PUSHs(sv_2mortal(C2Sv(content, NULL)));
9373 394           PUSHs(sv_2mortal(newSViv(col)));
9374              
9375             #endif /* WITH_SERRORS */
9376              
9377              
9378             #ifdef LIBXML_PATTERN_ENABLED
9379              
9380             MODULE = XML::LibXML PACKAGE = XML::LibXML::Pattern
9381              
9382             xmlPatternPtr
9383             _compilePattern(CLASS, ppattern, pattern_type, ns_map=NULL)
9384             SV * ppattern
9385             AV * ns_map
9386             int pattern_type
9387             PREINIT:
9388 1           xmlChar * pattern = Sv2C(ppattern, NULL);
9389 1           xmlChar** namespaces = NULL;
9390             SV** aux;
9391             int last,i;
9392 1           PREINIT_SAVED_ERROR
9393             CODE:
9394 1 50         if ( pattern == NULL )
9395 0           XSRETURN_UNDEF;
9396 1 50         if (ns_map) {
9397 1           last = av_len(ns_map);
9398 1 50         New(0,namespaces, last+2, xmlChar*);
9399 3 100         for( i = 0; i <= last ; i++ ) {
9400 2           aux = av_fetch(ns_map,i,0);
9401 2 50         namespaces[i]=(xmlChar*) SvPV_nolen(*aux);
9402             }
9403 1           namespaces[i]=0;
9404             }
9405 1           INIT_ERROR_HANDLER;
9406 1           RETVAL = xmlPatterncompile(pattern, NULL, pattern_type, (const xmlChar **) namespaces);
9407 1           Safefree(namespaces);
9408 1           xmlFree( pattern );
9409 1           CLEANUP_ERROR_HANDLER;
9410 1           REPORT_ERROR(0);
9411 1 50         if ( RETVAL == NULL ) {
9412 0           croak("Compilation of pattern failed");
9413             }
9414             OUTPUT:
9415             RETVAL
9416              
9417             int
9418             matchesNode(self, node)
9419             xmlPatternPtr self
9420             xmlNodePtr node
9421             CODE:
9422 34 50         if ( node ==NULL ) {
9423 0           XSRETURN_UNDEF;
9424             }
9425 34           RETVAL = xmlPatternMatch(self, node);
9426             OUTPUT:
9427             RETVAL
9428              
9429             void
9430             DESTROY( self )
9431             xmlPatternPtr self
9432             CODE:
9433             xs_warn( "DESTROY PATTERN OBJECT" );
9434 1           xmlFreePattern(self);
9435              
9436             #endif /* LIBXML_PATTERN_ENABLED */
9437              
9438             #ifdef LIBXML_REGEXP_ENABLED
9439              
9440             MODULE = XML::LibXML PACKAGE = XML::LibXML::RegExp
9441              
9442             xmlRegexpPtr
9443             _compile(CLASS, pregexp)
9444             SV * pregexp
9445             PREINIT:
9446 3           xmlChar * regexp = Sv2C(pregexp, NULL);
9447 3           PREINIT_SAVED_ERROR
9448             CODE:
9449 3 50         if ( regexp == NULL )
9450 0           XSRETURN_UNDEF;
9451 3           INIT_ERROR_HANDLER;
9452 3           RETVAL = xmlRegexpCompile(regexp);
9453 3           xmlFree( regexp );
9454 3           CLEANUP_ERROR_HANDLER;
9455 3           REPORT_ERROR(0);
9456 2 50         if ( RETVAL == NULL ) {
9457 0           croak("Compilation of regexp failed");
9458             }
9459             OUTPUT:
9460             RETVAL
9461              
9462             int
9463             matches(self, pvalue)
9464             xmlRegexpPtr self
9465             SV* pvalue
9466             PREINIT:
9467 8           xmlChar * value = Sv2C(pvalue, NULL);
9468             CODE:
9469 8 50         if ( value == NULL )
9470 0           XSRETURN_UNDEF;
9471 8           RETVAL = xmlRegexpExec(self,value);
9472 8           xmlFree( value );
9473             OUTPUT:
9474             RETVAL
9475              
9476             int
9477             isDeterministic(self)
9478             xmlRegexpPtr self
9479             CODE:
9480 2           RETVAL = xmlRegexpIsDeterminist(self);
9481             OUTPUT:
9482             RETVAL
9483              
9484             void
9485             DESTROY( self )
9486             xmlRegexpPtr self
9487             CODE:
9488             xs_warn( "DESTROY REGEXP OBJECT" );
9489 2           xmlRegFreeRegexp(self);
9490              
9491             #endif /* LIBXML_REGEXP_ENABLED */
9492              
9493              
9494             MODULE = XML::LibXML PACKAGE = XML::LibXML::XPathExpression
9495              
9496             xmlXPathCompExprPtr
9497             new(CLASS, pxpath)
9498             SV * pxpath
9499             PREINIT:
9500 10           xmlChar * xpath = Sv2C(pxpath, NULL);
9501 10           PREINIT_SAVED_ERROR
9502             CODE:
9503 10 50         if ( pxpath == NULL )
9504 0           XSRETURN_UNDEF;
9505 10           INIT_ERROR_HANDLER;
9506 10           RETVAL = xmlXPathCompile( xpath );
9507 10           xmlFree( xpath );
9508 10           CLEANUP_ERROR_HANDLER;
9509 10           REPORT_ERROR(0);
9510 10 50         if ( RETVAL == NULL ) {
9511 0           croak("Compilation of XPath expression failed!");
9512             }
9513             OUTPUT:
9514             RETVAL
9515              
9516             void
9517             DESTROY( self )
9518             xmlXPathCompExprPtr self
9519             CODE:
9520             xs_warn( "DESTROY COMPILED XPATH OBJECT" );
9521 10           xmlXPathFreeCompExpr(self);
9522              
9523             MODULE = XML::LibXML PACKAGE = XML::LibXML::Common
9524              
9525             PROTOTYPES: DISABLE
9526              
9527             SV*
9528             encodeToUTF8( encoding, string )
9529             const char * encoding
9530             SV * string
9531             PREINIT:
9532 17           xmlChar * realstring = NULL;
9533 17           xmlChar * tstr = NULL;
9534 17           xmlCharEncoding enc = 0;
9535 17           STRLEN len = 0;
9536 17           xmlBufferPtr in = NULL, out = NULL;
9537 17           xmlCharEncodingHandlerPtr coder = NULL;
9538 17           PREINIT_SAVED_ERROR
9539             CODE:
9540 17 100         if (!SvOK(string)) {
    50          
    50          
9541 2           XSRETURN_UNDEF;
9542 16 100         } else if (!SvCUR(string)) {
9543 1           XSRETURN_PV("");
9544             }
9545 15 50         realstring = (xmlChar*) SvPV(string, len);
9546 15 50         if ( realstring != NULL ) {
9547             /* warn("encode %s", realstring ); */
9548             #ifdef HAVE_UTF8
9549 15 50         if ( !DO_UTF8(string) && encoding != NULL ) {
    0          
    50          
9550             #else
9551             if ( encoding != NULL ) {
9552             #endif
9553 15           enc = xmlParseCharEncoding( encoding );
9554              
9555 15 50         if ( enc == 0 ) {
9556             /* this happens if the encoding is "" or NULL */
9557 0           enc = XML_CHAR_ENCODING_UTF8;
9558             }
9559              
9560 29 100         if ( enc == XML_CHAR_ENCODING_UTF8 ) {
9561             /* copy the string */
9562             /* warn( "simply copy the string" ); */
9563 4           tstr = xmlStrndup( realstring, len );
9564             }
9565             else {
9566 11           INIT_ERROR_HANDLER;
9567 11 100         if ( enc > 1 ) {
9568 10           coder= xmlGetCharEncodingHandler( enc );
9569             }
9570 1 50         else if ( enc == XML_CHAR_ENCODING_ERROR ){
9571 1           coder =xmlFindCharEncodingHandler( encoding );
9572             }
9573             else {
9574 0           croak("no encoder found\n");
9575             }
9576 11 100         if ( coder == NULL ) {
9577 1           croak( "cannot encode string" );
9578             }
9579 10           in = xmlBufferCreateStatic((void*)realstring, len );
9580 10           out = xmlBufferCreate();
9581 10 50         if ( xmlCharEncInFunc( coder, out, in ) >= 0 ) {
9582 10           tstr = xmlStrdup( out->content );
9583             }
9584              
9585 10           xmlBufferFree( in );
9586 10           xmlBufferFree( out );
9587 10           xmlCharEncCloseFunc( coder );
9588              
9589 10           CLEANUP_ERROR_HANDLER;
9590 10           REPORT_ERROR(0);
9591             }
9592             }
9593             else {
9594 0           tstr = xmlStrndup( realstring, len );
9595             }
9596              
9597 14 50         if ( !tstr ) {
9598 0           croak( "return value missing!" );
9599             }
9600              
9601 14           len = xmlStrlen( tstr );
9602 14           RETVAL = newSVpvn( (const char *)tstr, len );
9603             #ifdef HAVE_UTF8
9604 14           SvUTF8_on(RETVAL);
9605             #endif
9606 14           xmlFree(tstr);
9607             }
9608             else {
9609 0           XSRETURN_UNDEF;
9610             }
9611             OUTPUT:
9612             RETVAL
9613              
9614             SV*
9615             decodeFromUTF8( encoding, string )
9616             const char * encoding
9617             SV* string
9618             PREINIT:
9619 9           xmlChar * tstr = NULL;
9620 9           xmlChar * realstring = NULL;
9621 9           xmlCharEncoding enc = 0;
9622 9           STRLEN len = 0;
9623 9           xmlBufferPtr in = NULL, out = NULL;
9624 9           xmlCharEncodingHandlerPtr coder = NULL;
9625 9           PREINIT_SAVED_ERROR
9626             CODE:
9627             #ifdef HAVE_UTF8
9628 9 100         if ( !SvOK(string) ) {
    50          
    50          
9629 2           XSRETURN_UNDEF;
9630 8 100         } else if (!SvCUR(string)) {
9631 1           XSRETURN_PV("");
9632 7 50         } else if ( !SvUTF8(string) ) {
9633 0           croak("string is not utf8!!");
9634             } else {
9635             #endif
9636 7 50         realstring = (xmlChar*) SvPV(string, len);
9637 7 50         if ( realstring != NULL ) {
9638             /* warn("decode %s", realstring ); */
9639 7           enc = xmlParseCharEncoding( encoding );
9640 7 50         if ( enc == 0 ) {
9641             /* this happens if the encoding is "" or NULL */
9642 0           enc = XML_CHAR_ENCODING_UTF8;
9643             }
9644              
9645 7 100         if ( enc == XML_CHAR_ENCODING_UTF8 ) {
9646             /* copy the string */
9647             /* warn( "simply copy the string" ); */
9648 1           tstr = xmlStrdup( realstring );
9649 1           len = xmlStrlen( tstr );
9650             }
9651             else {
9652 6           INIT_ERROR_HANDLER;
9653 6 100         if ( enc > 1 ) {
9654 4           coder= xmlGetCharEncodingHandler( enc );
9655             }
9656 2 50         else if ( enc == XML_CHAR_ENCODING_ERROR ){
9657 2           coder = xmlFindCharEncodingHandler( encoding );
9658             }
9659             else {
9660 0           croak("no encoder found\n");
9661             }
9662              
9663 6 50         if ( coder == NULL ) {
9664 0           croak( "cannot encode string" );
9665             }
9666              
9667 6           in = xmlBufferCreate();
9668 6           out = xmlBufferCreate();
9669 6           xmlBufferCCat( in, (char*) realstring );
9670 6 50         if ( xmlCharEncOutFunc( coder, out, in ) >= 0 ) {
9671 6           len = xmlBufferLength( out );
9672 6           tstr = xmlCharStrndup( (char*) xmlBufferContent( out ), len );
9673             }
9674              
9675 6           xmlBufferFree( in );
9676 6           xmlBufferFree( out );
9677 6           xmlCharEncCloseFunc( coder );
9678 6           CLEANUP_ERROR_HANDLER;
9679 6           REPORT_ERROR(0);
9680 6 50         if ( !tstr ) {
9681 0           croak( "return value missing!" );
9682             }
9683             }
9684              
9685 7           RETVAL = newSVpvn( (const char *)tstr, len );
9686 7           xmlFree( tstr );
9687             #ifdef HAVE_UTF8
9688 7 100         if ( enc == XML_CHAR_ENCODING_UTF8 ) {
9689 7           SvUTF8_on(RETVAL);
9690             }
9691             #endif
9692             }
9693             else {
9694 0           XSRETURN_UNDEF;
9695             }
9696             #ifdef HAVE_UTF8
9697             }
9698             #endif
9699             OUTPUT:
9700             RETVAL