Annotation of parser3/src/classes/xdoc.C, revision 1.108.2.19.2.6
1.1 parser 1: /** @file
1.2 parser 2: Parser: @b xdoc parser class.
1.1 parser 3:
1.108.2.2 paf 4: Copyright (c) 2001-2003 ArtLebedev Group (http://www.artlebedev.com)
1.85 paf 5: Author: Alexandr Petrosian <paf@design.ru> (http://paf.design.ru)
1.96 paf 6: */
1.1 parser 7:
1.80 paf 8: #include "classes.h"
1.1 parser 9: #ifdef XML
1.96 paf 10:
1.108.2.19.2. (paf 11:): static const char* IDENT_XDOC_C="$Date: 2003/03/20 14:19:08 $";
1.108.2.4 paf 12:
13: #include "pa_vmethod_frame.h"
1.1 parser 14:
1.82 paf 15: #include "pa_stylesheet_connection.h"
16: #include "pa_request.h"
17: #include "pa_vxdoc.h"
18: #include "pa_charset.h"
19: #include "pa_vfile.h"
20: #include "xnode.h"
21:
1.69 paf 22: #include "gdome.h"
23: #include "libxml/tree.h"
24: extern "C" {
25: #include "gdomecore/gdome-xml-node.h"
26: #include "gdomecore/gdome-xml-document.h"
27: };
28: #include "libxslt/xsltInternals.h"
29: #include "libxslt/transform.h"
30: #include "libxslt/xsltutils.h"
1.90 paf 31: #include "libxslt/variables.h"
1.59 paf 32:
1.1 parser 33: // defines
34:
35: #define XDOC_CLASS_NAME "xdoc"
36:
37: #define XDOC_OUTPUT_METHOD_OPTION_NAME "method"
38: #define XDOC_OUTPUT_METHOD_OPTION_VALUE_XML "xml"
39: #define XDOC_OUTPUT_METHOD_OPTION_VALUE_HTML "html"
40: #define XDOC_OUTPUT_METHOD_OPTION_VALUE_TEXT "text"
41:
42: // class
43:
1.108.2.9 paf 44: class MXdoc: public MXnode {
1.1 parser 45: public: // VStateless_class
1.108.2.19.2. (paf 46:): Value* create_new_value() { return Value*(new VXdoc(0, 0, 0)); }
1.1 parser 47:
48: public:
1.108.2.13 paf 49: MXdoc();
1.1 parser 50:
51: public: // Methoded
1.5 parser 52: void configure_admin(Request& r);
1.1 parser 53: };
54:
1.108.2.7 paf 55: // global variable
56:
1.108.2.12 paf 57: DECLARE_CLASS_VAR(xdoc, new MXdoc, 0);
1.108.2.7 paf 58:
1.61 paf 59: // helper classes
60:
61: class xmlOutputBuffer_auto_ptr {
62: public:
1.67 paf 63: explicit xmlOutputBuffer_auto_ptr(xmlOutputBuffer *_APtr = 0)
64: : _Owns(_APtr != 0), _Ptr(_APtr) {}
1.61 paf 65: xmlOutputBuffer_auto_ptr(const xmlOutputBuffer_auto_ptr& _Y)
66: : _Owns(_Y._Owns), _Ptr(_Y.release()) {}
67: xmlOutputBuffer_auto_ptr& operator=(const xmlOutputBuffer_auto_ptr& _Y)
68: {if (this != &_Y)
69: {if (_Ptr != _Y.get())
70: {if (_Owns && _Ptr)
71: xmlOutputBufferClose(_Ptr);
72: _Owns = _Y._Owns; }
73: else if (_Y._Owns)
74: _Owns = true;
75: _Ptr = _Y.release(); }
76: return (*this); }
77: ~xmlOutputBuffer_auto_ptr()
78: {if (_Owns && _Ptr)
79: xmlOutputBufferClose(_Ptr); }
80: xmlOutputBuffer& operator*() const
81: {return (*get()); }
82: xmlOutputBuffer *operator->() const
83: {return (get()); }
84: xmlOutputBuffer *get() const
85: {return (_Ptr); }
86: xmlOutputBuffer *release() const
87: {((xmlOutputBuffer_auto_ptr *)this)->_Owns = false;
88: return (_Ptr); }
89: private:
90: bool _Owns;
91: xmlOutputBuffer *_Ptr;
92: };
93:
1.65 paf 94: class xsltTransformContext_auto_ptr {
95: public:
1.67 paf 96: explicit xsltTransformContext_auto_ptr(xsltTransformContext *_APtr = 0)
97: : _Owns(_APtr != 0), _Ptr(_APtr) {}
1.65 paf 98: xsltTransformContext_auto_ptr(const xsltTransformContext_auto_ptr& _Y)
99: : _Owns(_Y._Owns), _Ptr(_Y.release()) {}
100: xsltTransformContext_auto_ptr& operator=(const xsltTransformContext_auto_ptr& _Y)
101: {if (this != &_Y)
102: {if (_Ptr != _Y.get())
103: {if (_Owns && _Ptr)
104: xsltFreeTransformContext(_Ptr);
105: _Owns = _Y._Owns; }
106: else if (_Y._Owns)
107: _Owns = true;
108: _Ptr = _Y.release(); }
109: return (*this); }
110: ~xsltTransformContext_auto_ptr()
111: {if (_Owns && _Ptr)
112: xsltFreeTransformContext(_Ptr); }
113: xsltTransformContext& operator*() const
114: {return (*get()); }
115: xsltTransformContext *operator->() const
116: {return (get()); }
117: xsltTransformContext *get() const
118: {return (_Ptr); }
119: xsltTransformContext *release() const
120: {((xsltTransformContext_auto_ptr *)this)->_Owns = false;
121: return (_Ptr); }
122: private:
123: bool _Owns;
124: xsltTransformContext *_Ptr;
125: };
1.61 paf 126:
1.65 paf 127: class xsltStylesheet_auto_ptr {
128: public:
1.67 paf 129: explicit xsltStylesheet_auto_ptr(xsltStylesheet *_APtr = 0)
130: : _Owns(_APtr != 0), _Ptr(_APtr) {}
1.65 paf 131: xsltStylesheet_auto_ptr(const xsltStylesheet_auto_ptr& _Y)
132: : _Owns(_Y._Owns), _Ptr(_Y.release()) {}
133: xsltStylesheet_auto_ptr& operator=(const xsltStylesheet_auto_ptr& _Y)
134: {if (this != &_Y)
135: {if (_Ptr != _Y.get())
136: {if (_Owns && _Ptr)
137: xsltFreeStylesheet(_Ptr);
138: _Owns = _Y._Owns; }
139: else if (_Y._Owns)
140: _Owns = true;
141: _Ptr = _Y.release(); }
142: return (*this); }
143: ~xsltStylesheet_auto_ptr()
144: {if (_Owns && _Ptr)
145: xsltFreeStylesheet(_Ptr); }
146: xsltStylesheet& operator*() const
147: {return (*get()); }
148: xsltStylesheet *operator->() const
149: {return (get()); }
150: xsltStylesheet *get() const
151: {return (_Ptr); }
152: xsltStylesheet *release() const
153: {((xsltStylesheet_auto_ptr *)this)->_Owns = false;
154: return (_Ptr); }
155: private:
156: bool _Owns;
157: xsltStylesheet *_Ptr;
158: };
1.61 paf 159:
1.1 parser 160: // methods
161:
1.108.2.19.2. (paf 162:): static void writeNode(Request& r, const String& method_name, GdomeNode *node,
1.54 paf 163: GdomeException exc) {
164: if(!node || exc)
1.87 paf 165: throw Exception(
1.108.2.5 paf 166: method_name,
1.54 paf 167: exc);
168:
169: // write out result
1.108.2.19.2. (paf 170:): r.write_no_lang(Value*(new VXnode(&&r.charsets, node)));
1.54 paf 171: }
172:
1.16 parser 173: // Element createElement(in DOMString tagName) raises(DOMException);
1.108.2.19.2. (paf 174:): static void _createElement(Request& r, const String& method_name, MethodParams* params) {
1.108.2.13 paf 175: VXdoc& vdoc=GET_SELF(r, VXdoc);
1.16 parser 176:
1.108.2.19.2. (paf 177:): const String& tagName=params->as_string(0, "tagName must be string");
1.16 parser 178:
1.54 paf 179: GdomeException exc;
180: GdomeNode *node=
1.108.2.13 paf 181: (GdomeNode *)gdome_doc_createElement(vdoc.get_document(method_name),
182: r.transcode(tagName).get(),
1.54 paf 183: &exc);
184: writeNode(r, method_name, node, exc);
1.16 parser 185: }
186:
187: // DocumentFragment createDocumentFragment()
1.108.2.19.2. (paf 188:): static void _createDocumentFragment(Request& r, const String& method_name, MethodParams* ) {
1.108.2.13 paf 189: VXdoc& vdoc=GET_SELF(r, VXdoc);
1.16 parser 190:
1.54 paf 191: GdomeException exc;
192: GdomeNode *node=
193: (GdomeNode *)gdome_doc_createDocumentFragment(
1.108.2.13 paf 194: vdoc.get_document(method_name),
1.54 paf 195: &exc);
196: writeNode(r, method_name, node, exc);
1.16 parser 197: }
198:
199: // Text createTextNode(in DOMString data);
1.108.2.19.2. (paf 200:): static void _createTextNode(Request& r, const String& method_name, MethodParams* params) {
1.108.2.13 paf 201: VXdoc& vdoc=GET_SELF(r, VXdoc);
1.16 parser 202:
1.108.2.19.2. (paf 203:): const String& data=params->as_string(0, "data must be string");
1.16 parser 204:
1.54 paf 205: GdomeException exc;
206: GdomeNode *node=(GdomeNode *)gdome_doc_createTextNode(
1.108.2.13 paf 207: vdoc.get_document(method_name),
208: r.transcode(data).get(),
1.54 paf 209: &exc);
210: writeNode(r, method_name, node, exc);
1.16 parser 211: }
212:
213: // Comment createComment(in DOMString data)
1.108.2.19.2. (paf 214:): static void _createComment(Request& r, const String& method_name, MethodParams* params) {
1.108.2.13 paf 215: VXdoc& vdoc=GET_SELF(r, VXdoc);
1.16 parser 216:
1.108.2.19.2. (paf 217:): const String& data=params->as_string(0, "data must be string");
1.16 parser 218:
1.54 paf 219: GdomeException exc;
220: GdomeNode *node=(GdomeNode *)gdome_doc_createComment(
1.108.2.13 paf 221: vdoc.get_document(method_name),
222: r.transcode(data).get(),
1.54 paf 223: &exc);
224: writeNode(r, method_name, node, exc);
1.16 parser 225: }
226:
227: // CDATASection createCDATASection(in DOMString data) raises(DOMException);
1.108.2.19.2. (paf 228:): static void _createCDATASection(Request& r, const String& method_name, MethodParams* params) {
1.108.2.13 paf 229: VXdoc& vdoc=GET_SELF(r, VXdoc);
1.16 parser 230:
1.108.2.19.2. (paf 231:): const String& data=params->as_string(0, "data must be string");
1.16 parser 232:
1.54 paf 233: GdomeException exc;
234: GdomeNode *node=(GdomeNode *)gdome_doc_createCDATASection(
1.108.2.13 paf 235: vdoc.get_document(method_name),
236: r.transcode(data).get(),
1.54 paf 237: &exc);
238: writeNode(r, method_name, node, exc);
1.16 parser 239: }
240:
241: // ProcessingInstruction createProcessingInstruction(in DOMString target,in DOMString data) raises(DOMException);
1.108.2.19.2. (paf 242:): static void _createProcessingInstruction(Request& r, const String& method_name, MethodParams* params) {
1.108.2.13 paf 243: VXdoc& vdoc=GET_SELF(r, VXdoc);
1.16 parser 244:
1.108.2.19.2. (paf 245:): const String& target=params->as_string(0, "data must be string");
246:): const String& data=params->as_string(1, "data must be string");
1.16 parser 247:
1.54 paf 248: GdomeException exc;
249: GdomeNode *node=(GdomeNode *)gdome_doc_createProcessingInstruction(
1.108.2.13 paf 250: vdoc.get_document(method_name),
251: r.transcode(target).get(),
252: r.transcode(data).get(),
1.54 paf 253: &exc);
254: writeNode(r, method_name, node, exc);
1.16 parser 255: }
256:
257: // Attr createAttribute(in DOMString name) raises(DOMException);
1.108.2.19.2. (paf 258:): static void _createAttribute(Request& r, const String& method_name, MethodParams* params) {
1.108.2.13 paf 259: VXdoc& vdoc=GET_SELF(r, VXdoc);
1.16 parser 260:
1.108.2.19.2. (paf 261:): const String& name=params->as_string(0, "name must be string");
1.16 parser 262:
1.54 paf 263: GdomeException exc;
264: GdomeNode *node=(GdomeNode *)gdome_doc_createAttribute(
1.108.2.13 paf 265: vdoc.get_document(method_name),
266: r.transcode(name).get(),
1.54 paf 267: &exc);
268: writeNode(r, method_name, node, exc);
1.16 parser 269: }
270: // EntityReference createEntityReference(in DOMString name) raises(DOMException);
1.108.2.19.2. (paf 271:): static void _createEntityReference(Request& r, const String& method_name, MethodParams* params) {
1.108.2.13 paf 272: VXdoc& vdoc=GET_SELF(r, VXdoc);
1.16 parser 273:
1.108.2.19.2. (paf 274:): const String& name=params->as_string(0, "name must be string");
1.16 parser 275:
1.54 paf 276: GdomeException exc;
277: GdomeNode *node=(GdomeNode *)gdome_doc_createEntityReference(
1.108.2.13 paf 278: vdoc.get_document(method_name),
279: r.transcode(name).get(),
1.54 paf 280: &exc);
281: writeNode(r, method_name, node, exc);
1.16 parser 282: }
283:
1.99 paf 284: // NodeList getElementsByTagName(in DOMString name);
1.108.2.19.2. (paf 285:): static void _getElementsByTagName(Request& r, const String& method_name, MethodParams* params) {
1.108.2.13 paf 286: VXdoc& vdoc=GET_SELF(r, VXdoc);
1.99 paf 287:
1.108.2.19.2. (paf 288:): const String& name=params->as_string(0, "name must be string");
1.99 paf 289:
1.108.2.19.2. (paf 290:): VHash* result(new VHash);
1.99 paf 291: GdomeException exc;
292: if(GdomeNodeList *nodes=
293: gdome_doc_getElementsByTagName(
1.108.2.13 paf 294: vdoc.get_document(method_name),
295: r.transcode(name).get(),
1.99 paf 296: &exc)) {
297: gulong length=gdome_nl_length(nodes, &exc);
298: for(gulong i=0; i<length; i++) {
1.108.2.19.2. (paf 299:): const String& skey(new String);
1.108.2.13 paf 300: *skey << pool.format_integer(i);
1.99 paf 301:
1.108.2.19.2. (paf 302:): result->hash(0).put(
1.108.2.13 paf 303: skey,
1.108.2.19.2. (paf 304:): Value*(new VXnode(&&r.charsets, gdome_nl_item(nodes, i, &exc))));
1.99 paf 305: }
306: } else if(exc)
307: throw Exception(
1.108.2.5 paf 308: method_name,
1.99 paf 309: exc);
310:
311: // write out result
312: r.write_no_lang(result);
313: }
314:
1.108.2.19.2. (paf 315:): static void _getElementsByTagNameNS(Request& r, const String& method_name, MethodParams* params) {
1.108.2.13 paf 316: VXdoc& vdoc=GET_SELF(r, VXdoc);
1.99 paf 317:
318: // namespaceURI;localName
1.108.2.19.2. (paf 319:): const String& namespaceURI=params->as_string(0, "namespaceURI must be string");
320:): const String& localName=params->as_string(1, "localName must be string");
1.99 paf 321:
322: GdomeException exc;
1.108.2.19.2. (paf 323:): VHash* result(new VHash);
1.99 paf 324: if(GdomeNodeList *nodes=
325: gdome_doc_getElementsByTagNameNS(
1.108.2.13 paf 326: vdoc.get_document(method_name),
327: r.transcode(namespaceURI).get(),
328: r.transcode(localName).get(),
1.99 paf 329: &exc)) {
330: gulong length=gdome_nl_length(nodes, &exc);
331: for(gulong i=0; i<length; i++) {
1.108.2.19.2. (paf 332:): const String& skey(new String);
1.108.2.13 paf 333: *skey << pool.format_integer(i);
1.99 paf 334:
1.108.2.19.2. (paf 335:): result->hash(0).put(
1.108.2.13 paf 336: skey,
1.108.2.19.2. (paf 337:): Value*(new VXnode(&&r.charsets, gdome_nl_item(nodes, i, &exc))));
1.99 paf 338: }
339: }
340:
341: // write out result
342: r.write_no_lang(result);
343: }
344:
1.108.2.19.2. (paf 345:): static void _getElementById(Request& r, const String& method_name, MethodParams* params) {
1.108.2.13 paf 346: VXdoc& vdoc=GET_SELF(r, VXdoc);
1.16 parser 347:
1.54 paf 348: // elementId
1.108.2.19.2. (paf 349:): const String& elementId=params->as_string(0, "elementID must be string");
1.1 parser 350:
1.54 paf 351: GdomeException exc;
352: if(GdomeNode *node=(GdomeNode *)gdome_doc_getElementById(
1.108.2.13 paf 353: vdoc.get_document(method_name),
354: r.transcode(elementId).get(),
1.54 paf 355: &exc)) {
356: // write out result
1.108.2.19.2. (paf 357:): r.write_no_lang(Value*(new VXnode(&&r.charsets, node)));
1.66 paf 358: } else if(exc || xmlHaveGenericErrors())
1.87 paf 359: throw Exception(
1.108.2.5 paf 360: method_name,
1.54 paf 361: exc);
362: }
1.79 paf 363:
1.108.2.19.2. (paf 364:): static void _importNode(Request& r, const String& method_name, MethodParams* params) {
1.108.2.13 paf 365: VXdoc& vdoc=GET_SELF(r, VXdoc);
1.79 paf 366:
367: GdomeNode *importedNode=
1.88 paf 368: as_node(method_name, params, 0, "importedNode must be node");
1.79 paf 369: bool deep=
1.108.2.10 paf 370: params->as_bool(1, "deep must be bool", r);
1.79 paf 371:
372: GdomeException exc;
1.108.2.13 paf 373: GdomeNode *outputNode=gdome_doc_importNode(vdoc.get_document(method_name),
1.79 paf 374: importedNode,
375: deep, &exc);
376: if(exc)
1.87 paf 377: throw Exception(
1.108.2.5 paf 378: method_name,
1.79 paf 379: exc);
380:
381: // write out result
1.108.2.19.2. (paf 382:): r.write_no_lang(Value*(new VXnode(&&r.charsets, outputNode)));
1.79 paf 383: }
1.54 paf 384: /*
385: GdomeElement *gdome_doc_createElementNS (GdomeDocument *self, GdomeDOMString *namespaceURI, GdomeDOMString *qualifiedName, GdomeException *exc);
386: GdomeAttr *gdome_doc_createAttributeNS (GdomeDocument *self, GdomeDOMString *namespaceURI, GdomeDOMString *qualifiedName, GdomeException *exc);
387: */
1.1 parser 388:
1.108.2.19.2. (paf 389:): static void _create(Request& r, const String& method_name, MethodParams* params) {
1.108.2.13 paf 390: Charset& source_charset=r.charsets.source();
391: VXdoc& vdoc=GET_SELF(r, VXdoc);
1.1 parser 392:
1.108.2.19.2. (paf 393:): Value* param=(*params)[params->count()-1];
1.83 paf 394: GdomeDocument *document;
1.108.2.13 paf 395: if(param->get_junction()) { // {<?xml?>...}
1.108.2.19.2. (paf 396:): Temp_lang temp_lang(r, String::L_XML);
397:): const String& xml=r.process_to_string(param);
1.83 paf 398:
1.108.2.19.2. (paf 399:): const char* cstr=xml->cstr(String::L_UNSPECIFIED);
1.83 paf 400: document=(GdomeDocument *)
401: gdome_xml_n_mkref((xmlNode *)xmlParseMemory(
402: cstr, strlen(cstr)
403: ));
404: if(!document || xmlHaveGenericErrors()) {
405: GdomeException exc=0;
1.87 paf 406: throw Exception(
1.108.2.5 paf 407: method_name,
1.83 paf 408: exc);
409: }
410: } else { // [name]
1.108.2.19.2. (paf 411:): const String& qualifiedName=param->as_string();
1.1 parser 412:
1.83 paf 413: GdomeException exc;
414: /*
415: GdomeDocumentType *documentType=gdome_di_createDocumentType (
416: docimpl,
1.108.2.13 paf 417: r.transcode(qualifiedName),
1.83 paf 418: 0/*publicId* /,
419: 0/*systemId* /,
420: &exc);
421: if(!documentType || exc || xmlHaveGenericErrors())
1.87 paf 422: throw Exception(
1.108.2.5 paf 423: method_name,
1.83 paf 424: exc);
425: */
426: document=gdome_di_createDocument (domimpl,
427: 0/*namespaceURI*/,
1.108.2.13 paf 428: r.transcode(qualifiedName).get(),
1.83 paf 429: 0/*doctype*/,
430: &exc);
431: if(!document || exc || xmlHaveGenericErrors())
1.87 paf 432: throw Exception(
1.108.2.5 paf 433: method_name,
1.83 paf 434: exc);
1.103 paf 435:
436: xmlDoc *doc=gdome_xml_doc_get_xmlDoc(document);
1.108.2.19.2. (paf 437:): const char* source_charset_name=source_charset.name()->cstr();
1.108.2.13 paf 438: doc->encoding=source_charset.transcode_buf2xchar(source_charset_name, strlen(source_charset_name));
1.9 parser 439:
1.83 paf 440: /// +xalan createXMLDecl ?
1.73 paf 441: }
1.95 paf 442:
443: // URI
1.108.2.2 paf 444: const char* URI_cstr;
1.108.2.19.2. (paf 445:): const char* URI_cstr_ptr;
1.108.2.10 paf 446: if(params->count()>1) { // absolute(param)
1.108.2.19.2. (paf 447:): const String& URI=params->as_string(0, "URI must be string");
1.108.2.13 paf 448: URI_cstr=URI_cstr_ptr=r.absolute(URI)->cstr();
1.95 paf 449: } else // default = disk path to requested document
1.108.2.13 paf 450: URI_cstr=r.request_info.path_translated;
1.95 paf 451: xmlDoc *doc=gdome_xml_doc_get_xmlDoc(document);
452: if(URI_cstr)
1.108.2.13 paf 453: doc->URL=source_charset.transcode_buf2xchar(URI_cstr, strlen(URI_cstr));
1.95 paf 454:
1.54 paf 455: // replace any previous parsed source
1.108.2.19.2. (paf 456:): vdoc.set_document(&&r.charsets, document);
1.9 parser 457: }
458:
1.108.2.19.2. (paf 459:): static void _load(Request& r, const String& method_name, MethodParams* params) {
1.108.2.13 paf 460: Charset& source_charset=r.charsets.source();
461: VXdoc& vdoc=GET_SELF(r, VXdoc);
1.9 parser 462:
1.54 paf 463: // filespec
1.108.2.19.2. (paf 464:): const String& file_name=params->as_string(0, "uri must be string");
465:): const String& uri=r.absolute(file_name);
1.105 paf 466:
467: void *data; size_t size;
1.108.2.19.2. (paf 468:): File_read_result file=file_read(source_charset, uri, false/*not text*/,
1.108.2.13 paf 469: params->count()>1?params->as_no_junction(1, "additional params must be hash")
470: ->get_hash(method_name)
1.105 paf 471: :0);
472:
1.73 paf 473: GdomeDocument *document=(GdomeDocument *)
1.108.2.19.2. (paf 474:): gdome_xml_n_mkref((xmlNode *)xmlParseMemory(file.data, file.length));
1.73 paf 475: if(!document || xmlHaveGenericErrors()) {
476: GdomeException exc=0;
1.108.2.13 paf 477: throw Exception(uri, exc);
1.73 paf 478: }
1.108.2.19.2. (paf 479:): const char* URI_cstr=uri->cstr();
1.107 paf 480: xmlDoc *doc=gdome_xml_doc_get_xmlDoc(document);
481: if(URI_cstr)
1.108.2.13 paf 482: doc->URL=source_charset.transcode_buf2xchar(URI_cstr, strlen(URI_cstr));
1.9 parser 483:
1.54 paf 484: // replace any previous parsed source
1.108.2.19.2. (paf 485:): vdoc.set_document(&&r.charsets, document);
1.9 parser 486: }
487:
1.108.2.19.2. (paf 488:): static void param_option_over_output_option
1.108.2.14 paf 489: HashStringValue& param_options, const char* option_name,
1.108.2.19.2. (paf 490:): String* & output_option) {
491:): if(Value* value=param_options.get(String* (new String(option_name))))
492:): output_option=value->as_string();
1.46 paf 493: }
1.108.2.19.2. (paf 494:): static void param_option_over_output_option
1.108.2.14 paf 495: HashStringValue& param_options, const char* option_name,
1.46 paf 496: bool& output_option) {
1.108.2.19.2. (paf 497:): if(Value* value=param_options.get(String* (new String(option_name)))) {
498:): const String& s=value->as_string();
1.108.2.14 paf 499: if(*s=="yes")
1.46 paf 500: output_option=true;
1.108.2.14 paf 501: else if(*s=="no")
1.46 paf 502: output_option=false;
503: else
1.87 paf 504: throw Exception("parser.runtime",
1.108.2.14 paf 505: s,
1.46 paf 506: "%s must be either 'yes' or 'no'", option_name);
507: }
508: }
509:
1.100 paf 510: /// @test valid_options check
1.108.2.14 paf 511: static void prepare_output_options(Request& r,
1.108.2.19.2. (paf 512:): const String& method_name, MethodParams* params, int index,
1.61 paf 513: VXdoc::Output_options& oo) {
1.46 paf 514: /*
515: <xsl:output
516: !method = "xml" | "html" | "text" | qname-but-not-ncname
517: !version = nmtoken
518: !encoding = string
519: !omit-xml-declaration = "yes" | "no"
520: !standalone = "yes" | "no"
521: !doctype-public = string
522: !doctype-system = string
523: cdata-section-elements = qnames
524: !indent = "yes" | "no"
525: !media-type = string />
1.61 paf 526: */
1.1 parser 527:
1.46 paf 528: // configuring with options from parameter...
1.108.2.10 paf 529: if(params->count()>index) {
1.108.2.19.2. (paf 530:): Value* voptions=params->as_no_junction(index, "options must be string");
1.108.2.14 paf 531: if(voptions->is_defined()) {
532: if(HashStringValue *options=voptions->get_hash(method_name)) {
1.1 parser 533: // $.method[xml|html|text]
1.108.2.19.2. (paf 534:): if(Value* vmethod=options->get(String* (new String(XDOC_OUTPUT_METHOD_OPTION_NAME))))
535:): oo.method=vmethod->as_string();
1.1 parser 536:
1.46 paf 537: // $.version[1.0]
1.108.2.19.2. (paf 538:): param_option_over_output_option(*options, "version", oo.version);
1.1 parser 539: // $.encoding[windows-1251|...]
1.108.2.19.2. (paf 540:): param_option_over_output_option(*options, "encoding", oo.encoding);
1.46 paf 541: // $.omit-xml-declaration[yes|no]
1.108.2.19.2. (paf 542:): param_option_over_output_option(*options, "omit-xml-declaration", oo.omitXmlDeclaration);
1.46 paf 543: // $.standalone[yes|no]
1.108.2.19.2. (paf 544:): param_option_over_output_option(*options, "standalone", oo.standalone);
1.46 paf 545: // $.doctype-public[?]
1.108.2.19.2. (paf 546:): param_option_over_output_option(*options, "doctype-public", oo.doctypePublic);
1.46 paf 547: // $.doctype-system[?]
1.108.2.19.2. (paf 548:): param_option_over_output_option(*options, "doctype-system", oo.doctypeSystem);
1.46 paf 549: // $.indent[yes|no]
1.108.2.19.2. (paf 550:): param_option_over_output_option(*options, "indent", oo.indent);
1.46 paf 551: // $.media-type[text/{html|xml|plain}]
1.108.2.19.2. (paf 552:): param_option_over_output_option(*options, "media-type", oo.mediaType);
1.19 parser 553: }
1.1 parser 554: }
555: }
556:
1.46 paf 557: // default encoding from pool
1.61 paf 558: if(!oo.encoding)
1.108.2.14 paf 559: oo.encoding=r.charsets.source().name();
1.46 paf 560: // default method=xml
561: if(!oo.method)
1.108.2.19.2. (paf 562:): oo.method=String* (new String(XDOC_OUTPUT_METHOD_OPTION_VALUE_XML));
1.61 paf 563: // default mediaType = depending on method
564: if(!oo.mediaType) {
565: if(*oo.method==XDOC_OUTPUT_METHOD_OPTION_VALUE_XML)
1.108.2.19.2. (paf 566:): oo.mediaType=String* (new String("text/xml"));
1.61 paf 567: else if(*oo.method==XDOC_OUTPUT_METHOD_OPTION_VALUE_HTML)
1.108.2.19.2. (paf 568:): oo.mediaType=String* (new String("text/html"));
1.61 paf 569: else // XDOC_OUTPUT_METHOD_OPTION_VALUE_TEXT & all others
1.108.2.19.2. (paf 570:): oo.mediaType=String* (new String("text/plain"));
1.61 paf 571: }
572: }
1.46 paf 573:
1.108.2.14 paf 574: struct Xdoc2buf_result {
575: char* ptr;
576: size_t size;
577: };
578: static Xdoc2buf_result xdoc2buf(Request& r, VXdoc& vdoc,
1.108.2.19.2. (paf 579:): const String& method_name, MethodParams* params, int index,
1.63 paf 580: VXdoc::Output_options& oo,
1.108.2.19.2. (paf 581:): const String& file_spec) {
1.108.2.14 paf 582: Xdoc2buf_result result;
583: prepare_output_options(r, method_name, params, index,
1.61 paf 584: oo);
585:
1.108.2.19.2. (paf 586:): const char* encoding_cstr=oo.encoding->cstr();
1.63 paf 587: xmlCharEncodingHandler *encoder=xmlFindCharEncodingHandler(encoding_cstr);
588: if(!encoder)
1.87 paf 589: throw Exception("parser.runtime",
1.108.2.5 paf 590: method_name,
1.108.2.14 paf 591: "encoding '%s' not supported", encoding_cstr.get());
1.61 paf 592: // UTF-8 encoder contains empty input/output converters,
593: // which is wrong for xmlOutputBufferCreateIO
594: // while zero encoder goes perfectly
595: if(encoder && strcmp(encoder->name, "UTF-8")==0)
596: encoder=0;
597:
1.62 paf 598: xmlOutputBuffer_auto_ptr outputBuffer(xmlAllocOutputBuffer(encoder));
1.61 paf 599:
1.65 paf 600: xsltStylesheet_auto_ptr stylesheet(xsltNewStylesheet());
601: if(!stylesheet.get())
1.87 paf 602: throw Exception(0,
1.108.2.5 paf 603: method_name,
1.61 paf 604: "xsltNewStylesheet failed");
605:
1.62 paf 606: #define OOS2STYLE(name) \
1.108.2.14 paf 607: stylesheet->name=oo.name?BAD_CAST g_strdup(r.transcode(oo.name)->str):0
1.62 paf 608: #define OOE2STYLE(name) \
609: stylesheet->name=oo.name
1.61 paf 610:
1.62 paf 611: OOS2STYLE(method);
612: OOS2STYLE(encoding);
613: OOS2STYLE(mediaType);
614: OOS2STYLE(doctypeSystem);
615: OOS2STYLE(doctypePublic);
616: OOE2STYLE(indent);
617: OOS2STYLE(version);
618: OOE2STYLE(standalone);
619: OOE2STYLE(omitXmlDeclaration);
1.61 paf 620:
1.108.2.13 paf 621: xmlDoc *document=gdome_xml_doc_get_xmlDoc(vdoc.get_document(method_name));
1.81 paf 622: if(xsltSaveResultTo(outputBuffer.get(), document, stylesheet.get())<0) {
1.75 paf 623: GdomeException exc=0;
1.87 paf 624: throw Exception(
1.108.2.5 paf 625: method_name,
1.75 paf 626: exc);
627: }
1.61 paf 628:
1.54 paf 629: // write out result
1.63 paf 630: char *gnome_buf; size_t gnome_size;
631: if(outputBuffer->conv) {
632: gnome_size=outputBuffer->conv->use;
1.62 paf 633: gnome_buf=(char *)outputBuffer->conv->content;
1.63 paf 634: } else {
635: gnome_size=outputBuffer->buffer->use;
1.62 paf 636: gnome_buf=(char *)outputBuffer->buffer->content;
1.63 paf 637: }
638: if(file_spec)
1.108.2.14 paf 639: file_write(file_spec,
1.63 paf 640: gnome_buf, gnome_size,
641: true/*as_text*/);
1.108.2.14 paf 642: else if(result.size=gnome_size) {
643: result.ptr=pool.copy(gnome_buf, gnome_size);
1.74 paf 644: } else
1.108.2.14 paf 645: result.ptr=0;
646:
647: return result;
1.1 parser 648: }
649:
1.108.2.19.2. (paf 650:): static void _file(Request& r, const String& method_name, MethodParams* params) {
1.108.2.13 paf 651: VXdoc& vdoc=GET_SELF(r, VXdoc);
1.63 paf 652: VXdoc::Output_options oo(vdoc.output_options);
1.108.2.14 paf 653: Xdoc2buf_result buf=xdoc2buf(r, vdoc, method_name, params, 0,
1.63 paf 654: oo,
1.108.2.19.2. (paf 655:): 0/*not to file, to memory*/);
1.63 paf 656: // write out result
1.108.2.19.2. (paf 657:): r.write_no_lang(String(buf.ptr, buf.length));
1.1 parser 658:
1.58 paf 659: // write out result
1.108.2.19.2. (paf 660:): VFile* vfile(new VFile);
661:): Value* vcontent_type;
662:): VHash* vhcontent_type(new VHash);
1.108.2.14 paf 663: vhcontent_type->hash(method_name).put(
664: value_name,
1.108.2.19.2. (paf 665:): Value*(new VString(oo.mediaType)));
1.108.2.14 paf 666: vhcontent_type->hash(method_name).put(
1.108.2.19.2. (paf 667:): String* (new String("charset")),
668:): Value*(new VString(oo.encoding)));
1.58 paf 669: vcontent_type=vhcontent_type;
1.108.2.14 paf 670:
1.108.2.19.2. (paf 671:): vfile->set(false/*tainted*/, buf.ptr?buf.ptr:""/*to distinguish from stat-ed file*/, buf.size,
1.102 paf 672: 0/*file_name*/, vcontent_type);
1.58 paf 673: r.write_no_lang(vfile);
1.63 paf 674: }
675:
1.108.2.19.2. (paf 676:): static void _save(Request& r, const String& method_name, MethodParams* params) {
1.108.2.13 paf 677: VXdoc& vdoc=GET_SELF(r, VXdoc);
1.63 paf 678:
1.108.2.19.2. (paf 679:): const String& file_spec=r.absolute(params->as_string(0, "file name must be string"));
1.63 paf 680:
681: VXdoc::Output_options oo(vdoc.output_options);
1.108.2.14 paf 682: xdoc2buf(r, vdoc, method_name, params, 1,
1.63 paf 683: oo,
1.108.2.14 paf 684: file_spec);
1.63 paf 685: }
686:
1.108.2.19.2. (paf 687:): static void _string(Request& r, const String& method_name, MethodParams* params) {
1.108.2.13 paf 688: VXdoc& vdoc=GET_SELF(r, VXdoc);
1.63 paf 689: VXdoc::Output_options oo(vdoc.output_options);
1.108.2.14 paf 690: Xdoc2buf_result buf=xdoc2buf(r, vdoc, method_name, params, 0,
1.63 paf 691: oo,
1.108.2.19.2. (paf 692:): 0/*not to file, to memory*/);
1.63 paf 693: // write out result
1.108.2.19.2. (paf 694:): r.write_no_lang(String(buf.ptr, buf.length));
1.1 parser 695: }
1.58 paf 696:
1.108.2.14 paf 697: #ifndef DOXYGEN
698: struct Add_xslt_param_info {
699: Request* r;
1.108.2.18 paf 700: Array<GdomeDOMString_auto_ptr>* strings;
1.108.2.14 paf 701: const char** current_transform_param;
702: };
703: #endif
704: static void add_xslt_param(
705: HashStringValue::key_type attribute,
706: HashStringValue::value_type meaning,
707: Add_xslt_param_info* info) {
1.108.2.18 paf 708: GdomeDOMString_auto_ptr s;
709: *info->current_transform_param++=(s=info->r->transcode(attribute))->str; *info->strings+=s;
710: *info->current_transform_param++=(s=info->r->transcode(meaning->as_string(&info->r->pool())))->str; *info->strings+=s;
1.1 parser 711: }
1.108.2.19.2. (paf 712:): static VXdocPtr _transform(Request& r, const String& doc_source, const String& stylesheet_source,
1.108.2.14 paf 713: VXdoc& vdoc, xsltStylesheetPtr stylesheet, const char** transform_params) {
1.93 paf 714: xmlDoc *document=gdome_xml_doc_get_xmlDoc(vdoc.get_document(doc_source));
1.65 paf 715: xsltTransformContext_auto_ptr transformContext(
716: xsltNewTransformContext(stylesheet, document));
1.90 paf 717: // make params literal
718: if (transformContext->globalVars == NULL) // strangly not initialized by xsltNewTransformContext
719: transformContext->globalVars = xmlHashCreate(20);
720: xsltQuoteUserParams(transformContext.get(), transform_params);
721: // do transform
1.59 paf 722: xmlDoc *transformed=xsltApplyStylesheetUser(
723: stylesheet,
724: document,
1.90 paf 725: 0/*already quoted-inserted transform_params*/,
1.108.2.2 paf 726: 0/*const char* output*/,
1.59 paf 727: 0/*FILE *profile*/,
1.65 paf 728: transformContext.get());
1.66 paf 729: if(!transformed || xmlHaveGenericErrors()) {
730: GdomeException exc=0;
1.87 paf 731: throw Exception(
1.93 paf 732: stylesheet_source,
1.66 paf 733: exc);
734: }
1.42 paf 735:
1.61 paf 736: //gdome_xml_doc_mkref dislikes XML_HTML_DOCUMENT_NODE type, fixing
737: transformed->type=XML_DOCUMENT_NODE;
1.59 paf 738: // constructing result
739: GdomeDocument *gdomeDocument=gdome_xml_doc_mkref(transformed);
740: if(!gdomeDocument)
1.87 paf 741: throw Exception(0,
1.93 paf 742: doc_source,
1.59 paf 743: "gdome_xml_doc_mkref failed");
1.108.2.19.2. (paf 744:): VXdocPtr result(new VXdoc(&&r.charsets, gdomeDocument));
1.61 paf 745: /* grabbing options
746:
747: <xsl:output
748: !method = "xml" | "html" | "text"
749: X| qname-but-not-ncname
750: !version = nmtoken
751: !encoding = string
752: !omit-xml-declaration = "yes" | "no"
753: !standalone = "yes" | "no"
754: !doctype-public = string
755: !doctype-system = string
756: Xcdata-section-elements = qnames
757: !indent = "yes" | "no"
758: !media-type = string />
1.59 paf 759: */
1.108.2.14 paf 760: VXdoc::Output_options& oo=result->output_options;
1.59 paf 761:
1.108.2.19.2. (paf 762:): oo.method=stylesheet->method?r.transcode(stylesheet->method, stylesheet_source):0;
763:): oo.encoding=stylesheet->encoding?r.transcode(stylesheet->encoding, stylesheet_source):0;
764:): oo.mediaType=stylesheet->mediaType?r.transcode(stylesheet->mediaType, stylesheet_source):0;
765:): oo.doctypeSystem=stylesheet->doctypeSystem?r.transcode(stylesheet->doctypeSystem, stylesheet_source):0;
766:): oo.doctypePublic=stylesheet->doctypePublic?r.transcode(stylesheet->doctypePublic, stylesheet_source):0;
1.59 paf 767: oo.indent=stylesheet->indent!=0;
1.108.2.19.2. (paf 768:): oo.version=stylesheet->version?r.transcode(stylesheet->version, stylesheet_source):0;
1.59 paf 769: oo.standalone=stylesheet->standalone!=0;
770: oo.omitXmlDeclaration=stylesheet->omitXmlDeclaration!=0;
771:
1.93 paf 772: // return
773: return result;
774: }
1.108.2.19.2. (paf 775:): static void _transform(Request& r, const String& method_name, MethodParams* params) {
1.108.2.13 paf 776: VXdoc& vdoc=GET_SELF(r, VXdoc);
1.93 paf 777:
778: // params
1.108.2.18 paf 779: Array<GdomeDOMString_auto_ptr> transform_strings;
1.108.2.14 paf 780: smart_ptr<const char*> transform_params;
1.108.2.10 paf 781: if(params->count()>1) {
1.108.2.19.2. (paf 782:): Value* vparams=params->as_no_junction(1, "transform parameters must be hash");
1.108.2.10 paf 783: if(!vparams->is_string())
1.108.2.14 paf 784: if(HashStringValue* params=vparams->get_hash(method_name)) {
785: transform_params=smart_ptr<const char*>(new const char*[params->count()*2+1]);
786: Add_xslt_param_info info={
787: &r,
1.108.2.18 paf 788: &transform_strings,
1.108.2.14 paf 789: transform_params
790: };
791: params->for_each(add_xslt_param, &info);
792: transform_params[params->count()*2]=0;
1.93 paf 793: } else
794: throw Exception("parser.runtime",
1.108.2.5 paf 795: method_name,
1.93 paf 796: "transform parameters parameter must be hash");
797: }
798:
1.108.2.14 paf 799: VXdocPtr result;
1.108.2.19.2. (paf 800:): Value* vmaybe_xdoc=(*params)[0];
1.108.2.14 paf 801: if(Value *vxdoc=vmaybe_xdoc->as(VXDOC_TYPE, false)) { // stylesheet (xdoc)
1.93 paf 802: xmlDoc *document=gdome_xml_doc_get_xmlDoc(
1.108.2.13 paf 803: static_cast<VXdoc *>(vxdoc)->get_document(method_name));
1.93 paf 804: // compile xdoc stylesheet
1.94 paf 805: xsltStylesheet_auto_ptr stylesheet_ptr(xsltParseStylesheetDoc(document));
806: // strange thing - xsltParseStylesheetDoc records document and destroys it in stylesheet destructor
807: // we don't need that
808: stylesheet_ptr->doc=0;
1.93 paf 809: if(xmlHaveGenericErrors()) {
810: GdomeException exc=0;
1.108.2.5 paf 811: throw Exception(method_name, exc);
1.93 paf 812: }
813: if(!stylesheet_ptr.get())
814: throw Exception("xml",
1.108.2.5 paf 815: method_name,
1.93 paf 816: "stylesheet failed to compile");
817:
818: // transform!
1.108.2.14 paf 819: result=_transform(r, method_name, method_name,
1.93 paf 820: vdoc, stylesheet_ptr.get(),
821: transform_params);
822: } else { // stylesheet (file name)
823: // extablish stylesheet connection
1.108.2.19.2. (paf 824:): const String& stylesheet_filespec=
1.108.2.10 paf 825: r.absolute(params->as_string(0, "stylesheet must be file name (string) or DOM document (xdoc)"));
1.108.2.14 paf 826: Stylesheet_connectionPtr connection=stylesheet_manager.get_connection(stylesheet_filespec);
1.93 paf 827:
828: // load and compile file to stylesheet [or get cached if any]
829: // transform!
1.108.2.14 paf 830: result=_transform(r, method_name, stylesheet_filespec,
1.93 paf 831: vdoc, connection->stylesheet(false/*nocache*/),
832: transform_params);
833: }
834:
1.59 paf 835: // write out result
1.108.2.14 paf 836: r.write_no_lang(result);
1.1 parser 837: }
838:
1.16 parser 839: // constructor
1.2 parser 840:
1.92 paf 841: /// @test how to create empty type html?
1.108.2.15 paf 842: MXdoc::MXdoc(): MXnode(XDOC_CLASS_NAME, xnode_class.get()) {
1.16 parser 843: /// DOM1
1.2 parser 844:
1.16 parser 845: // Element createElement(in DOMString tagName) raises(DOMException);
846: add_native_method("createElement", Method::CT_DYNAMIC, _createElement, 1, 1);
847: // DocumentFragment createDocumentFragment();
848: add_native_method("createDocumentFragment", Method::CT_DYNAMIC, _createDocumentFragment, 0, 0);
849: // Text createTextNode(in DOMString data);
850: add_native_method("createTextNode", Method::CT_DYNAMIC, _createTextNode, 1, 1);
851: // Comment createComment(in DOMString data);
852: add_native_method("createComment", Method::CT_DYNAMIC, _createComment, 1, 1);
853: // CDATASection createCDATASection(in DOMString data) raises(DOMException);
854: add_native_method("createCDATASection", Method::CT_DYNAMIC, _createCDATASection, 1, 1);
855: // ProcessingInstruction createProcessingInstruction(in DOMString target, in DOMString data) raises(DOMException);
856: add_native_method("createProcessingInstruction", Method::CT_DYNAMIC, _createProcessingInstruction, 2, 2);
857: // Attr createAttribute(in DOMString name) raises(DOMException);
858: add_native_method("createAttribute", Method::CT_DYNAMIC, _createAttribute, 1, 1);
859: // EntityReference createEntityReference(in DOMString name) raises(DOMException);
860: add_native_method("createEntityReference", Method::CT_DYNAMIC, _createEntityReference, 1, 1);
1.99 paf 861: // NodeList getElementsByTagName(in DOMString name);
862: add_native_method("getElementsByTagName", Method::CT_DYNAMIC, _getElementsByTagName, 1, 1);
1.2 parser 863:
1.79 paf 864: /// DOM2
1.2 parser 865:
1.16 parser 866: // ^xdoc.getElementById[elementId]
867: add_native_method("getElementById", Method::CT_DYNAMIC, _getElementById, 1, 1);
1.79 paf 868:
869: // Node (in Node importedNode, in boolean deep) raises(DOMException)
870: add_native_method("importNode", Method::CT_DYNAMIC, _importNode, 2, 2);
1.99 paf 871:
872: // NodeList getElementsByTagNameNS(in DOMString namespaceURI, in DOMString localName);
873: add_native_method("getElementsByTagNameNS", Method::CT_DYNAMIC, _getElementsByTagNameNS, 2, 2);
1.1 parser 874:
1.16 parser 875: /// parser
876:
1.54 paf 877: // ^xdoc::create{qualifiedName}
1.95 paf 878: // ^xdoc::create[<some>xml</some>]
879: // ^xdoc::create[URI][<some>xml</some>]
880: add_native_method("create", Method::CT_DYNAMIC, _create, 1, 2);
1.83 paf 881: // for backward compatibility with <=v 1.82 2002/01/31 11:51:46 paf
882: add_native_method("set", Method::CT_DYNAMIC, _create, 1, 1);
1.54 paf 883:
884: // ^xdoc::load[some.xml]
1.105 paf 885: add_native_method("load", Method::CT_DYNAMIC, _load, 1, 2);
1.54 paf 886:
1.2 parser 887: // ^xdoc.save[some.xml]
888: // ^xdoc.save[some.xml;options hash]
1.1 parser 889: add_native_method("save", Method::CT_DYNAMIC, _save, 1, 2);
890:
1.2 parser 891: // ^xdoc.string[] <doc/>
892: // ^xdoc.string[options hash] <doc/>
1.1 parser 893: add_native_method("string", Method::CT_DYNAMIC, _string, 0, 1);
894:
1.2 parser 895: // ^xdoc.file[] file with "<doc/>"
896: // ^xdoc.file[options hash] file with "<doc/>"
1.58 paf 897: add_native_method("file", Method::CT_DYNAMIC, _file, 0, 1);
1.1 parser 898:
1.98 paf 899: // ^xdoc.transform[stylesheet file_name/xdoc]
900: // ^xdoc.transform[stylesheet file_name/xdoc;params hash]
1.59 paf 901: add_native_method("transform", Method::CT_DYNAMIC, _transform, 1, 2);
1.2 parser 902:
1.1 parser 903: }
1.5 parser 904:
905: void MXdoc::configure_admin(Request& r) {
906: }
907:
1.108.2.7 paf 908: # else
1.108.2.19 paf 909:
910: // global variable
911:
912: DECLARE_CLASS_VAR(xdoc, 0, 0); // fictive
1.1 parser 913:
914: #endif
915:
E-mail: