[SHELL32] Implement support for IID_IDropTarget in CDesktopFolder::GetUIObjectOf...
[reactos.git] / reactos / dll / win32 / msxml3 / xdr.c
1 /*
2 * XDR (XML-Data Reduced) -> XSD (XML Schema Document) conversion
3 *
4 * Copyright 2010 Adam Martinson for CodeWeavers
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 */
20
21
22 #include "precomp.h"
23
24 #include <assert.h>
25
26 #ifdef HAVE_LIBXML2
27 # include <libxml/tree.h>
28 #endif
29
30 /* Both XDR and XSD are valid XML
31 * We just convert the doc tree, no need for a parser.
32 */
33
34 #ifdef HAVE_LIBXML2
35
36 static const xmlChar DT_prefix[] = "dt";
37 static const xmlChar DT_href[] = "urn:schemas-microsoft-com:datatypes";
38 static const xmlChar XDR_href[] = "urn:schemas-microsoft-com:xml-data";
39 static const xmlChar XSD_prefix[] = "xsd";
40 static const xmlChar XSD_href[] = "http://www.w3.org/2001/XMLSchema";
41
42 static const xmlChar xs_all[] = "all";
43 static const xmlChar xs_annotation[] = "annotation";
44 static const xmlChar xs_any[] = "any";
45 static const xmlChar xs_anyAttribute[] = "anyAttribute";
46 static const xmlChar xs_attribute[] = "attribute";
47 static const xmlChar xs_AttributeType[] = "AttributeType";
48 static const xmlChar xs_base[] = "base";
49 static const xmlChar xs_choice[] = "choice";
50 static const xmlChar xs_complexType[] = "complexType";
51 static const xmlChar xs_content[] = "content";
52 static const xmlChar xs_datatype[] = "datatype";
53 static const xmlChar xs_default[] = "default";
54 static const xmlChar xs_description[] = "description";
55 static const xmlChar xs_documentation[] = "documentation";
56 static const xmlChar xs_element[] = "element";
57 static const xmlChar xs_ElementType[] = "ElementType";
58 static const xmlChar xs_eltOnly[] = "eltOnly";
59 static const xmlChar xs_enumeration[] = "enumeration";
60 static const xmlChar xs_extension[] = "extension";
61 static const xmlChar xs_group[] = "group";
62 static const xmlChar xs_lax[] = "lax";
63 static const xmlChar xs_length[] = "length";
64 static const xmlChar xs_many[] = "many";
65 static const xmlChar xs_maxOccurs[] = "maxOccurs";
66 static const xmlChar xs_minOccurs[] = "minOccurs";
67 static const xmlChar xs_mixed[] = "mixed";
68 static const xmlChar xs_model[] = "model";
69 static const xmlChar xs_name[] = "name";
70 static const xmlChar xs_namespace[] = "namespace";
71 static const xmlChar xs_no[] = "no";
72 static const xmlChar xs_open[] = "open";
73 static const xmlChar xs_optional[] = "optional";
74 static const xmlChar xs_order[] = "order";
75 static const xmlChar xs_processContents[] = "processContents";
76 static const xmlChar xs_ref[] = "ref";
77 static const xmlChar xs_required[] = "required";
78 static const xmlChar xs_restriction[] = "restriction";
79 static const xmlChar xs_schema[] = "schema";
80 static const xmlChar xs_seq[] = "seq";
81 static const xmlChar xs_sequence[] = "sequence";
82 static const xmlChar xs_simpleContent[] = "simpleContent";
83 static const xmlChar xs_simpleType[] = "simpleType";
84 static const xmlChar xs_strict[] = "strict";
85 static const xmlChar xs_targetNamespace[] = "targetNamespace";
86 static const xmlChar xs_textOnly[] = "textOnly";
87 static const xmlChar xs_true[] = "true";
88 static const xmlChar xs_type[] = "type";
89 static const xmlChar xs_unbounded[] = "unbounded";
90 static const xmlChar xs_use[] = "use";
91 static const xmlChar xs_value[] = "value";
92 static const xmlChar xs_values[] = "values";
93 static const xmlChar xs_xsd_string[] = "xsd:string";
94
95 typedef enum _CONTENT_TYPE
96 {
97 CONTENT_EMPTY,
98 CONTENT_TEXTONLY,
99 CONTENT_ELTONLY,
100 CONTENT_MIXED
101 } CONTENT_TYPE;
102
103 typedef enum _ORDER_TYPE
104 {
105 ORDER_SEQ,
106 ORDER_MANY,
107 ORDER_ONE
108 } ORDER_TYPE;
109
110 #define FOREACH_CHILD(node, child) \
111 for (child = node->children; child != NULL; child = child->next) \
112 if (child->type == XML_ELEMENT_NODE)
113
114 #define FOREACH_ATTR(node, attr) \
115 for (attr = node->properties; attr != NULL; attr = attr->next)
116
117 #define FOREACH_NS(node, ns) \
118 for (ns = node->nsDef; ns != NULL; ns = ns->next)
119
120 static inline xmlNodePtr get_schema(xmlNodePtr node)
121 {
122 return xmlDocGetRootElement(node->doc);
123 }
124
125 static inline xmlNodePtr get_child(xmlNodePtr node, xmlChar const* name)
126 {
127 xmlNodePtr child = NULL;
128 if (node)
129 {
130 FOREACH_CHILD(node, child)
131 {
132 if (xmlStrEqual(child->name, name))
133 break;
134 }
135 }
136
137 return child;
138 }
139
140 static inline xmlNodePtr get_child_with_attr(xmlNodePtr node, xmlChar const* name,
141 xmlChar const* attr_ns, xmlChar const* attr_name,
142 xmlChar const* attr_val)
143 {
144 xmlChar* str;
145 if (node)
146 {
147 FOREACH_CHILD(node, node)
148 {
149 if (xmlStrEqual(node->name, name))
150 {
151 str = (attr_ns != NULL)? xmlGetNsProp(node, attr_name, attr_ns) :
152 xmlGetProp(node, attr_name);
153 if (str)
154 {
155 if (xmlStrEqual(str, attr_val))
156 {
157 xmlFree(str);
158 return node;
159 }
160 xmlFree(str);
161 }
162 }
163 }
164 }
165
166 return NULL;
167 }
168
169 static inline xmlNsPtr get_dt_ns(xmlNodePtr node)
170 {
171 xmlNsPtr ns;
172
173 node = get_schema(node);
174 assert(node != NULL);
175
176 FOREACH_NS(node, ns)
177 {
178 if (xmlStrEqual(ns->href, DT_href))
179 break;
180 }
181
182 return ns;
183 }
184
185 static inline xmlChar* get_dt_type(xmlNodePtr xdr)
186 {
187 xmlChar* str = xmlGetNsProp(xdr, xs_type, DT_href);
188 if (!str)
189 {
190 xmlNodePtr datatype = get_child(xdr, xs_datatype);
191 if (datatype)
192 str = xmlGetNsProp(datatype, xs_type, DT_href);
193 }
194 return str;
195 }
196
197 static inline xmlChar* get_attr_val(xmlAttrPtr attr)
198 {
199 return xmlNodeGetContent((xmlNodePtr)attr);
200 }
201
202 static inline xmlNodePtr add_any_child(xmlNodePtr parent, BOOL set_occurs)
203 {
204 xmlNodePtr child = xmlNewChild(parent, NULL, xs_any, NULL);
205 if (set_occurs)
206 {
207 xmlSetProp(child, xs_minOccurs, BAD_CAST "0");
208 xmlSetProp(child, xs_maxOccurs, xs_unbounded);
209 }
210 xmlSetProp(child, xs_processContents, xs_strict);
211 return child;
212 }
213
214 static inline xmlNodePtr add_anyAttribute_child(xmlNodePtr parent)
215 {
216 xmlNodePtr child = xmlNewChild(parent, NULL, xs_anyAttribute, NULL);
217 xmlSetProp(child, xs_processContents, xs_lax);
218 return child;
219 }
220
221 static inline xmlAttrPtr copy_prop_ignore_ns(xmlAttrPtr xdr_attr, xmlNodePtr node)
222 {
223 xmlChar* str = get_attr_val(xdr_attr);
224 xmlAttrPtr attr = xmlSetProp(node, xdr_attr->name, str);
225 xmlFree(str);
226 return attr;
227 }
228 static inline xmlAttrPtr XDR_A_default(xmlAttrPtr xdr_attr, xmlNodePtr node)
229 {
230 TRACE("(%p, %p)\n", xdr_attr, node);
231
232 return copy_prop_ignore_ns(xdr_attr, node);
233 }
234
235 static inline xmlAttrPtr XDR_A_dt_type(xmlAttrPtr xdr_attr, xmlNodePtr node)
236 {
237 xmlChar* str = get_attr_val(xdr_attr);
238 xmlAttrPtr attr;
239
240 TRACE("(%p, %p)\n", xdr_attr, node);
241
242 if (xmlStrEqual(str, xs_enumeration))
243 attr = NULL;
244 else
245 attr = xmlSetNsProp(node, get_dt_ns(node), DT_prefix, str);
246 xmlFree(str);
247 return attr;
248 }
249
250 static xmlAttrPtr XDR_A_maxOccurs(xmlAttrPtr xdr_attr, xmlNodePtr node)
251 {
252 xmlChar* str = get_attr_val(xdr_attr);
253 xmlAttrPtr attr;
254
255 TRACE("(%p, %p)\n", xdr_attr, node);
256
257 if (xmlStrEqual(str, BAD_CAST "*"))
258 attr = xmlSetProp(node, xs_maxOccurs, xs_unbounded);
259 else
260 attr = copy_prop_ignore_ns(xdr_attr, node);
261
262 xmlFree(str);
263 return attr;
264 }
265
266 static inline xmlAttrPtr XDR_A_minOccurs(xmlAttrPtr xdr_attr, xmlNodePtr node)
267 {
268 TRACE("(%p, %p)\n", xdr_attr, node);
269
270 return copy_prop_ignore_ns(xdr_attr, node);
271 }
272
273 static inline xmlAttrPtr XDR_A_name(xmlAttrPtr xdr_attr, xmlNodePtr node)
274 {
275 TRACE("(%p, %p)\n", xdr_attr, node);
276
277 return copy_prop_ignore_ns(xdr_attr, node);
278 }
279
280 static xmlAttrPtr XDR_A_type(xmlAttrPtr xdr_attr, xmlNodePtr node)
281 {
282 xmlChar* str = get_attr_val(xdr_attr);
283 xmlAttrPtr attr = xmlSetProp(node, xs_ref, str);
284
285 TRACE("(%p, %p)\n", xdr_attr, node);
286
287 xmlFree(str);
288 return attr;
289 }
290
291 static xmlAttrPtr XDR_A_required(xmlAttrPtr xdr_attr, xmlNodePtr node)
292 {
293 xmlChar* str = get_attr_val(xdr_attr);
294 xmlAttrPtr attr;
295
296 TRACE("(%p, %p)\n", xdr_attr, node);
297
298 if (xmlStrEqual(str, xs_no))
299 attr = xmlSetProp(node, xs_use, xs_optional);
300 else /* yes */
301 attr = xmlSetProp(node, xs_use, xs_required);
302 xmlFree(str);
303 return attr;
304 }
305
306 static xmlNodePtr XDR_E_description(xmlNodePtr xdr, xmlNodePtr parent)
307 {
308 xmlNodePtr xsd_node = xmlNewChild(parent, NULL, xs_annotation, NULL);
309 xmlAttrPtr xdr_attr;
310
311 TRACE("(%p, %p)\n", xdr, parent);
312
313 xmlNewChild(xsd_node, NULL, xs_documentation, xdr->content);
314
315 FOREACH_ATTR(xdr, xdr_attr)
316 {
317 xmlCopyProp(xsd_node, xdr_attr);
318 }
319 return xsd_node;
320 }
321
322 static xmlNodePtr XDR_E_AttributeType(xmlNodePtr xdr, xmlNodePtr parent)
323 {
324 xmlChar *str, *type = get_dt_type(xdr);
325 xmlNodePtr xsd_node, xsd_child, xdr_child;
326 xmlAttrPtr xdr_attr;
327
328 TRACE("(%p, %p)\n", xdr, parent);
329
330 xsd_node = xmlNewChild(parent, NULL, xs_attribute, NULL);
331
332 if (type && xmlStrEqual(type, xs_enumeration))
333 {
334 xmlChar *tmp, *tokBegin, *tokEnd = NULL;
335 xmlNodePtr xsd_enum;
336 xsd_child = xmlNewChild(xsd_node, NULL, xs_simpleType, NULL);
337 xsd_child = xmlNewChild(xsd_child, NULL, xs_restriction, NULL);
338 xmlSetProp(xsd_child, xs_base, xs_xsd_string);
339
340 tokBegin = str = xmlGetNsProp(xdr, xs_values, DT_href);
341 while (tokBegin && *tokBegin)
342 {
343 while (*tokBegin && isspace(*tokBegin))
344 ++tokBegin;
345 tokEnd = tokBegin;
346 while (*tokEnd && !isspace(*tokEnd))
347 ++tokEnd;
348 if (tokEnd == tokBegin)
349 break;
350 xsd_enum = xmlNewChild(xsd_child, NULL, xs_enumeration, NULL);
351 tmp = xmlStrndup(tokBegin, tokEnd-tokBegin);
352 xmlSetProp(xsd_enum, xs_value, tmp);
353 xmlFree(tmp);
354 tokBegin = tokEnd;
355 }
356 xmlFree(str);
357
358 }
359 else if (type)
360 {
361 str = xmlStrdup(DT_prefix);
362 str = xmlStrcat(str, BAD_CAST ":");
363 str = xmlStrcat(str, type);
364 xmlSetProp(xsd_node, xs_type, str);
365 xmlFree(str);
366 }
367 xmlFree(type);
368
369 FOREACH_ATTR(xdr, xdr_attr)
370 {
371 if (xmlStrEqual(xdr_attr->name, xs_default))
372 XDR_A_default(xdr_attr, xsd_node);
373 else if (xmlStrEqual(xdr_attr->name, xs_name))
374 XDR_A_name(xdr_attr, xsd_node);
375 else if (xmlStrEqual(xdr_attr->name, xs_type) && xdr_attr->ns == get_dt_ns(xdr))
376 XDR_A_dt_type(xdr_attr, xsd_node);
377 else if (xmlStrEqual(xdr_attr->name, xs_values) && xdr_attr->ns == get_dt_ns(xdr))
378 ; /* already handled */
379 else if (xmlStrEqual(xdr_attr->name, xs_required))
380 XDR_A_required(xdr_attr, xsd_node);
381 else
382 xmlCopyProp(xsd_node, xdr_attr);
383 }
384
385 FOREACH_CHILD(xdr, xdr_child)
386 {
387 if (xmlStrEqual(xdr_child->name, xs_datatype))
388 ; /* already handled */
389 else if (xmlStrEqual(xdr_child->name, xs_description))
390 XDR_E_description(xdr_child, xsd_node);
391 else
392 FIXME("unexpected child <%s>\n", xdr_child->name);
393 }
394
395 return xsd_node;
396 }
397
398 static xmlNodePtr XDR_E_attribute(xmlNodePtr xdr, xmlNodePtr parent)
399 {
400 xmlChar* str = xmlGetProp(xdr, xs_type);
401 xmlNodePtr xsd_node, xdr_child, xdr_attrType;
402 xmlAttrPtr xdr_attr;
403
404 TRACE("(%p, %p)\n", xdr, parent);
405
406 xdr_attrType = get_child_with_attr(xdr->parent, xs_AttributeType, NULL, xs_name, str);
407 xmlFree(str);
408
409 if (xdr_attrType)
410 xsd_node = XDR_E_AttributeType(xdr_attrType, parent);
411 else
412 xsd_node = xmlNewChild(parent, NULL, xs_attribute, NULL);
413
414 FOREACH_ATTR(xdr, xdr_attr)
415 {
416 if (xmlStrEqual(xdr_attr->name, xs_default))
417 XDR_A_default(xdr_attr, xsd_node);
418 else if (xmlStrEqual(xdr_attr->name, xs_type) && !xdr_attrType)
419 XDR_A_type(xdr_attr, xsd_node);
420 else if (xmlStrEqual(xdr_attr->name, xs_required))
421 XDR_A_required(xdr_attr, xsd_node);
422 else
423 xmlCopyProp(xsd_node, xdr_attr);
424 }
425
426 FOREACH_CHILD(xdr, xdr_child)
427 {
428 FIXME("unexpected child <%s>\n", xdr_child->name);
429 }
430
431 return xsd_node;
432 }
433
434 static xmlNodePtr XDR_E_element(xmlNodePtr xdr, xmlNodePtr parent)
435 {
436 xmlNodePtr xdr_child, xsd_node = xmlNewChild(parent, NULL, xs_element, NULL);
437 xmlAttrPtr xdr_attr;
438
439 FOREACH_ATTR(xdr, xdr_attr)
440 {
441 if (xmlStrEqual(xdr_attr->name, xs_type))
442 XDR_A_type(xdr_attr, xsd_node);
443 else if (xmlStrEqual(xdr_attr->name, xs_maxOccurs))
444 XDR_A_maxOccurs(xdr_attr, xsd_node);
445 else if (xmlStrEqual(xdr_attr->name, xs_minOccurs))
446 XDR_A_minOccurs(xdr_attr, xsd_node);
447 else
448 xmlCopyProp(xsd_node, xdr_attr);
449 }
450
451 FOREACH_CHILD(xdr, xdr_child)
452 {
453 FIXME("unexpected child <%s>\n", xdr_child->name);
454 }
455
456 return xsd_node;
457 }
458
459 static xmlNodePtr XDR_E_group(xmlNodePtr xdr, xmlNodePtr parent)
460 {
461 xmlNodePtr xdr_child, xsd_node;
462 xmlChar* str = xmlGetProp(xdr, xs_order);
463 xmlAttrPtr xdr_attr;
464
465 TRACE("(%p, %p)\n", xdr, parent);
466
467 if (!str || xmlStrEqual(str, xs_seq))
468 xsd_node = xmlNewChild(parent, NULL, xs_sequence, NULL);
469 else if (xmlStrEqual(str, xs_many))
470 xsd_node = xmlNewChild(parent, NULL, xs_choice, NULL);
471 else /* one */
472 xsd_node = xmlNewChild(parent, NULL, xs_all, NULL);
473 xmlFree(str);
474
475 FOREACH_ATTR(xdr, xdr_attr)
476 {
477 if (xmlStrEqual(xdr_attr->name, xs_order))
478 ; /* already handled */
479 else if (xmlStrEqual(xdr_attr->name, xs_model))
480 ; /* ignored */
481 else if (xmlStrEqual(xdr_attr->name, xs_maxOccurs))
482 XDR_A_maxOccurs(xdr_attr, xsd_node);
483 else if (xmlStrEqual(xdr_attr->name, xs_minOccurs))
484 XDR_A_minOccurs(xdr_attr, xsd_node);
485 else
486 xmlCopyProp(xsd_node, xdr_attr);
487 }
488
489 FOREACH_CHILD(xdr, xdr_child)
490 {
491 if (xmlStrEqual(xdr_child->name, xs_description))
492 XDR_E_description(xdr_child, xsd_node);
493 else if (xmlStrEqual(xdr_child->name, xs_element))
494 XDR_E_element(xdr_child, xsd_node);
495 }
496
497 return xsd_node;
498 }
499
500 static xmlNodePtr XDR_E_ElementType(xmlNodePtr xdr, xmlNodePtr parent)
501 {
502 xmlChar *str, *type = get_dt_type(xdr);
503 BOOL is_open = TRUE;
504 int n_attributes = 0, n_elements = 0, n_groups = 0;
505 CONTENT_TYPE content;
506 ORDER_TYPE order;
507 xmlNodePtr xsd_node, xsd_type, xsd_child, xdr_child;
508 xmlAttrPtr xdr_attr;
509 xmlNsPtr dt_ns = get_dt_ns(parent);
510
511 TRACE("(%p, %p)\n", xdr, parent);
512
513 str = xmlGetProp(xdr, xs_model);
514 if (str && !xmlStrEqual(str, xs_open))
515 is_open = FALSE;
516 xmlFree(str);
517
518 if (type)
519 {
520 content = CONTENT_TEXTONLY;
521 }
522 else
523 {
524 str = xmlGetProp(xdr, xs_content);
525 if (!str || xmlStrEqual(str, xs_mixed))
526 content = CONTENT_MIXED;
527 else if (xmlStrEqual(str, xs_eltOnly))
528 content = CONTENT_ELTONLY;
529 else if (xmlStrEqual(str, xs_textOnly))
530 content = CONTENT_TEXTONLY;
531 else /* empty */
532 content = CONTENT_EMPTY;
533 xmlFree(str);
534 }
535
536 str = xmlGetProp(xdr, xs_order);
537 if (!str || xmlStrEqual(str, xs_seq))
538 {
539 order = ORDER_SEQ;
540 }
541 else if (xmlStrEqual(str, xs_many))
542 {
543 order = ORDER_MANY;
544 }
545 else /* one */
546 {
547 order = ORDER_ONE;
548 is_open = FALSE;
549 }
550 xmlFree(str);
551
552 FOREACH_CHILD(xdr, xdr_child)
553 {
554 if (xmlStrEqual(xdr_child->name, xs_element))
555 ++n_elements;
556 else if (xmlStrEqual(xdr_child->name, xs_group))
557 ++n_groups;
558 else if (xmlStrEqual(xdr_child->name, xs_attribute))
559 ++n_attributes;
560 }
561
562 xsd_node = xmlNewChild(parent, NULL, xs_element, NULL);
563 assert(xsd_node != NULL);
564 switch (content)
565 {
566 case CONTENT_MIXED:
567 case CONTENT_ELTONLY:
568 {
569 xmlNodePtr xsd_base;
570 xsd_type = xmlNewChild(xsd_node, NULL, xs_complexType, NULL);
571
572 if (content == CONTENT_MIXED)
573 xmlSetProp(xsd_type, xs_mixed, xs_true);
574
575 if (is_open)
576 xsd_base = xmlNewChild(xsd_type, NULL, xs_sequence, NULL);
577 else
578 xsd_base = xsd_type;
579
580 if (is_open && n_elements < 2 && !n_groups)
581 {/* no specific sequence of elements we need,
582 just has to start with the right one, if any */
583 if ((xdr_child = get_child(xdr, xs_element)))
584 {
585 xsd_child = XDR_E_element(xdr_child, xsd_base);
586 xmlUnsetProp(xsd_child, xs_maxOccurs);
587 }
588 }
589 else
590 {
591 switch (order)
592 {
593 case ORDER_SEQ:
594 xsd_child = xmlNewChild(xsd_base, NULL, xs_sequence, NULL);
595 break;
596 case ORDER_MANY:
597 xsd_child = xmlNewChild(xsd_base, NULL, xs_choice, NULL);
598 xmlSetProp(xsd_child, xs_maxOccurs, xs_unbounded);
599 break;
600 case ORDER_ONE:
601 xsd_child = xmlNewChild(xsd_base, NULL, xs_all, NULL);
602 break;
603 }
604
605 FOREACH_CHILD(xdr, xdr_child)
606 {
607 if (xmlStrEqual(xdr_child->name, xs_element))
608 XDR_E_element(xdr_child, xsd_child);
609 else if (xmlStrEqual(xdr_child->name, xs_group))
610 XDR_E_group(xdr_child, xsd_child);
611 }
612 }
613
614 if (n_attributes)
615 {
616 FOREACH_CHILD(xdr, xdr_child)
617 {
618 if (xmlStrEqual(xdr_child->name, xs_attribute))
619 XDR_E_attribute(xdr_child, xsd_type);
620 }
621 }
622
623 if (is_open)
624 {
625 add_any_child(xsd_base, TRUE);
626 add_anyAttribute_child(xsd_type);
627 }
628 }
629 break;
630 case CONTENT_TEXTONLY:
631 {
632 if (is_open)
633 {
634 xsd_type = xmlNewChild(xsd_node, NULL, xs_complexType, NULL);
635 if (type)
636 {
637 xsd_child = xmlNewChild(xsd_type, NULL, xs_simpleContent, NULL);
638 xsd_child = xmlNewChild(xsd_child, NULL, xs_extension, NULL);
639 str = xmlStrdup(DT_prefix);
640 str = xmlStrcat(str, BAD_CAST ":");
641 str = xmlStrcat(str, type);
642 xmlSetProp(xsd_child, xs_base, str);
643 xmlFree(str);
644 assert(dt_ns != NULL);
645 xmlSetNsProp(xsd_node, dt_ns, DT_prefix, type);
646 }
647 else
648 {
649 xmlSetProp(xsd_type, xs_mixed, xs_true);
650 xsd_child = xmlNewChild(xsd_type, NULL, xs_choice, NULL);
651 xmlSetProp(xsd_child, xs_minOccurs, BAD_CAST "0");
652 xmlSetProp(xsd_child, xs_maxOccurs, xs_unbounded);
653 xsd_child = add_any_child(xsd_child, FALSE);
654 xmlSetProp(xsd_child, xs_namespace, BAD_CAST "##other");
655 xsd_child = xsd_type;
656 }
657
658 if (n_attributes)
659 FOREACH_CHILD(xdr, xdr_child)
660 {
661 if (xmlStrEqual(xdr_child->name, xs_attribute))
662 XDR_E_attribute(xdr_child, xsd_child);
663 }
664
665 xmlNewChild(xsd_child, NULL, xs_anyAttribute, NULL);
666 }
667 else if (!n_attributes)
668 {
669 if (type)
670 {
671 str = xmlStrdup(DT_prefix);
672 str = xmlStrcat(str, BAD_CAST ":");
673 str = xmlStrcat(str, type);
674 xmlSetProp(xsd_node, xs_type, str);
675 xmlFree(str);
676 str = NULL;
677 xmlSetNsProp(xsd_node, dt_ns, DT_prefix, type);
678 }
679 else
680 {
681 xmlSetProp(xsd_node, xs_type, xs_xsd_string);
682 }
683 }
684 else
685 {
686 xsd_type = xmlNewChild(xsd_node, NULL, xs_complexType, NULL);
687 xsd_child = xmlNewChild(xsd_type, NULL, xs_simpleContent, NULL);
688 xsd_child = xmlNewChild(xsd_child, NULL, xs_extension, NULL);
689 xmlSetProp(xsd_child, xs_base, xs_xsd_string);
690
691 FOREACH_CHILD(xdr, xdr_child)
692 {
693 if (xmlStrEqual(xdr_child->name, xs_attribute))
694 XDR_E_attribute(xdr_child, xsd_child);
695 }
696 }
697 }
698 break;
699 case CONTENT_EMPTY: /* not allowed with model="open" */
700 {
701 if (n_attributes)
702 {
703 xsd_type = xmlNewChild(xsd_node, NULL, xs_complexType, NULL);
704
705 FOREACH_CHILD(xdr, xdr_child)
706 {
707 if (xmlStrEqual(xdr_child->name, xs_attribute))
708 XDR_E_attribute(xdr_child, xsd_type);
709 }
710 }
711 else
712 {
713 xsd_type = xmlNewChild(xsd_node, NULL, xs_simpleType, NULL);
714 xsd_child = xmlNewChild(xsd_type, NULL, xs_restriction, NULL);
715 xmlSetProp(xsd_child, xs_base, xs_xsd_string);
716 xsd_child = xmlNewChild(xsd_child, NULL, xs_length, NULL);
717 xmlSetProp(xsd_child, xs_value, BAD_CAST "0");
718 }
719 }
720 break;
721 }
722 xmlFree(type);
723
724 FOREACH_ATTR(xdr, xdr_attr)
725 {
726 if (xmlStrEqual(xdr_attr->name, xs_content))
727 ; /* already handled */
728 else if (xmlStrEqual(xdr_attr->name, xs_name))
729 XDR_A_name(xdr_attr, xsd_node);
730 else if (xmlStrEqual(xdr_attr->name, xs_type) && xdr_attr->ns == get_dt_ns(xdr))
731 XDR_A_dt_type(xdr_attr, xsd_node);
732 else if (xmlStrEqual(xdr_attr->name, xs_model))
733 ; /* already handled */
734 else if (xmlStrEqual(xdr_attr->name, xs_order))
735 ; /* already handled */
736 else
737 xmlCopyProp(xsd_node, xdr_attr);
738
739 }
740
741 FOREACH_CHILD(xdr, xdr_child)
742 {
743 if (xmlStrEqual(xdr_child->name, xs_attribute))
744 ; /* already handled */
745 else if (xmlStrEqual(xdr_child->name, xs_AttributeType))
746 ; /* handled through XDR_E_attribute when parent is not <Schema> */
747 else if (xmlStrEqual(xdr_child->name, xs_datatype))
748 ; /* already handled */
749 else if (xmlStrEqual(xdr_child->name, xs_description))
750 XDR_E_description(xdr_child, xsd_node);
751 else if (xmlStrEqual(xdr_child->name, xs_element))
752 ; /* already handled */
753 else if (xmlStrEqual(xdr_child->name, xs_group))
754 ; /* already handled */
755 else
756 FIXME("unexpected child <%s>\n", xdr_child->name);
757 }
758
759 return xsd_node;
760 }
761
762 static xmlNodePtr XDR_E_Schema(xmlNodePtr xdr, xmlNodePtr parent, xmlChar const* nsURI)
763 {
764 xmlNodePtr xsd_node, xdr_child;
765 xmlNsPtr ns, xdr_ns;
766 xmlAttrPtr xdr_attr;
767
768 TRACE("(%p, %p)\n", xdr, parent);
769
770 xsd_node = xmlNewDocNode((xmlDocPtr)parent, NULL, xs_schema, NULL);
771 xmlDocSetRootElement((xmlDocPtr)parent, xsd_node);
772 assert(xsd_node != NULL);
773
774 if (nsURI && *nsURI) xmlNewNs(xsd_node, nsURI, NULL);
775 ns = xmlNewNs(xsd_node, XSD_href, XSD_prefix);
776 assert(ns != NULL);
777
778 xmlSetNs(xsd_node, ns);
779
780 if (nsURI && *nsURI) xmlSetProp(xsd_node, xs_targetNamespace, nsURI);
781
782 FOREACH_NS(xdr, xdr_ns)
783 {
784 /* TODO: special handling for dt namespace? */
785 assert(xdr_ns->href != NULL);
786 if (xmlStrEqual(xdr_ns->href, XDR_href))
787 ; /* ignored */
788 else if (xdr_ns->prefix != NULL)
789 xmlNewNs(xsd_node, xdr_ns->href, xdr_ns->prefix);
790 else
791 FIXME("unexpected default xmlns: %s\n", xdr_ns->href);
792 }
793
794 FOREACH_ATTR(xdr, xdr_attr)
795 {
796 xmlCopyProp(xsd_node, xdr_attr);
797 }
798
799 FOREACH_CHILD(xdr, xdr_child)
800 {
801 if (xmlStrEqual(xdr_child->name, xs_AttributeType))
802 XDR_E_AttributeType(xdr_child, xsd_node);
803 else if (xmlStrEqual(xdr_child->name, xs_description))
804 XDR_E_description(xdr_child, xsd_node);
805 else if (xmlStrEqual(xdr_child->name, xs_ElementType))
806 XDR_E_ElementType(xdr_child, xsd_node);
807 else
808 FIXME("unexpected child <%s>\n", xdr_child->name);
809 }
810
811 return xsd_node;
812 }
813
814 xmlDocPtr XDR_to_XSD_doc(xmlDocPtr xdr_doc, xmlChar const* nsURI)
815 {
816 xmlDocPtr xsd_doc = xmlNewDoc(NULL);
817
818 TRACE("(%p)\n", xdr_doc);
819
820 XDR_E_Schema(get_schema((xmlNodePtr)xdr_doc), (xmlNodePtr)xsd_doc, nsURI);
821
822 return xsd_doc;
823 }
824
825 #endif /* HAVE_LIBXML2 */