1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175
|
(**
* section: InputOutput
* synopsis: Example of custom Input/Output
* purpose: Demonstrate the use of xmlRegisterInputCallbacks
* to build a custom I/O layer, this is used in an
* XInclude method context to show how dynamic document can
* be built in a clean way.
* usage: io1
* test: io1 > io1.tmp ; diff io1.tmp io1.res ; rm -f io1.tmp
* author: Daniel Veillard
* copy: see Copyright for the status of this software.
*)
program io1;
{$mode objfpc}
uses
ctypes,
xml2,
exutils,
SysUtils;
const
include: pchar =
'<?xml version=''1.0''?>'#10+
'<document xmlns:xi="http://www.w3.org/2003/XInclude">'#10+
'<p>List of people:</p>'#10+
'<xi:include href="sql:select_name_from_people"/>'#10+
'</document>'#10;
var
res: pchar = '<list><people>a</people><people>b</people></list>';
cur: pchar = nil;
rlen: cint = 0;
(**
* sqlMatch:
* @URI: an URI to test
*
* Check for an sql: query
*
* Returns 1 if yes and 0 if another Input module should be used
*)
function sqlMatch(URI: pchar): cint; cdecl;
begin
if assigned(URI) and (strlcomp(URI, 'sql:', 4) = 0) then
result := 1
else
result := 0;
end;
(**
* sqlOpen:
* @URI: an URI to test
*
* Return a pointer to the sql: query handler, in this example simply
* the current pointer...
*
* Returns an Input context or NULL in case or error
*)
function sqlOpen(URI: pchar): pointer; cdecl;
begin
if not assigned(URI) or (strlcomp(URI, 'sql:', 4) <> 0) then
exit(nil);
cur := res;
rlen := strlen(res);
result := pointer(cur);
end;
(**
* sqlClose:
* @context: the read context
*
* Close the sql: query handler
*
* Returns 0 or -1 in case of error
*)
function sqlClose(context: pointer): cint; cdecl;
begin
if not assigned(context) then
exit(-1);
cur := nil;
rlen := 0;
result := 0;
end;
(**
* sqlRead:
* @context: the read context
* @buffer: where to store data
* @len: number of bytes to read
*
* Implement an sql: query read.
*
* Returns the number of bytes read or -1 in case of error
*)
function sqlRead(context: pointer; buffer: pchar; len: cint): cint; cdecl;
var
ptr: pchar;
begin
if not assigned(context) or not assigned(buffer) or (len < 0) then
exit(-1);
ptr := context;
if len > rlen then
len := rlen;
move(ptr^, buffer^, len);
rlen := rlen - len;
result := len;
end;
var
doc: xmlDocPtr;
begin
(*
* this initialize the library and check potential ABI mismatches
* between the version it was compiled for and the actual shared
* library used.
*)
LIBXML_TEST_VERSION;
(*
* register the new I/O handlers
*)
if xmlRegisterInputCallbacks(@sqlMatch, @sqlOpen, @sqlRead, @sqlClose) < 0 then
begin
printfn('failed to register SQL handler');
halt(1);
end;
(*
* parse include into a document
*)
doc := xmlReadMemory(include, strlen(include), 'include.xml', nil, 0);
if doc = nil then
begin
printfn('failed to parse the including file');
halt(1);
end;
(*
* apply the XInclude process, this should trigger the I/O just
* registered.
*)
if xmlXIncludeProcess(doc) <= 0 then
begin
printfn('XInclude processing failed');
halt(1);
end;
(*
* save the output for checking to stdout
*)
// xmlDocDump(stdout, doc);
(*
* Free the document
*)
//xmlDumpDoc(doc);
docdump(doc);
(*
* Cleanup function for the XML library.
*)
xmlCleanupParser();
end.
|