msxml3: Add IObjectSafety support to IXMLHTTPRequest.
[wine.git] / dlls / msxml3 / xdr.c
blob6e0da949d3a532de15352b85f656b72af9174810
1 /*
2 * XDR (XML-Data Reduced) -> XSD (XML Schema Document) conversion
4 * Copyright 2010 Adam Martinson for CodeWeavers
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.
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.
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
22 #include "config.h"
23 #include "wine/debug.h"
24 #include <assert.h>
26 WINE_DEFAULT_DEBUG_CHANNEL(msxml);
28 /* Both XDR and XSD are valid XML
29 * We just convert the doc tree, no need for a parser.
32 #ifdef HAVE_LIBXML2
34 #include <libxml/tree.h>
36 static const xmlChar DT_prefix[] = "dt";
37 static const xmlChar DT_href[] = "urn:schemas-microsoft-com:datatypes";
38 static const xmlChar XDR_prefix[] = "xdr";
39 static const xmlChar XDR_href[] = "urn:schemas-microsoft-com:xml-data";
40 static const xmlChar XSD_prefix[] = "xsd";
41 static const xmlChar XSD_href[] = "http://www.w3.org/2001/XMLSchema";
43 static const xmlChar xs_all[] = "all";
44 static const xmlChar xs_annotation[] = "annotation";
45 static const xmlChar xs_any[] = "any";
46 static const xmlChar xs_anyAttribute[] = "anyAttribute";
47 static const xmlChar xs_attribute[] = "attribute";
48 static const xmlChar xs_AttributeType[] = "AttributeType";
49 static const xmlChar xs_base[] = "base";
50 static const xmlChar xs_choice[] = "choice";
51 static const xmlChar xs_complexContent[] = "complexContent";
52 static const xmlChar xs_complexType[] = "complexType";
53 static const xmlChar xs_content[] = "content";
54 static const xmlChar xs_datatype[] = "datatype";
55 static const xmlChar xs_default[] = "default";
56 static const xmlChar xs_description[] = "description";
57 static const xmlChar xs_documentation[] = "documentation";
58 static const xmlChar xs_element[] = "element";
59 static const xmlChar xs_ElementType[] = "ElementType";
60 static const xmlChar xs_eltOnly[] = "eltOnly";
61 static const xmlChar xs_empty[] = "empty";
62 static const xmlChar xs_enumeration[] = "enumeration";
63 static const xmlChar xs_extension[] = "extension";
64 static const xmlChar xs_group[] = "group";
65 static const xmlChar xs_lax[] = "lax";
66 static const xmlChar xs_length[] = "length";
67 static const xmlChar xs_many[] = "many";
68 static const xmlChar xs_maxOccurs[] = "maxOccurs";
69 static const xmlChar xs_minOccurs[] = "minOccurs";
70 static const xmlChar xs_mixed[] = "mixed";
71 static const xmlChar xs_model[] = "model";
72 static const xmlChar xs_name[] = "name";
73 static const xmlChar xs_namespace[] = "namespace";
74 static const xmlChar xs_no[] = "no";
75 static const xmlChar xs_one[] = "one";
76 static const xmlChar xs_open[] = "open";
77 static const xmlChar xs_optional[] = "optional";
78 static const xmlChar xs_order[] = "order";
79 static const xmlChar xs_processContents[] = "processContents";
80 static const xmlChar xs_ref[] = "ref";
81 static const xmlChar xs_required[] = "required";
82 static const xmlChar xs_restriction[] = "restriction";
83 static const xmlChar xs_schema[] = "schema";
84 static const xmlChar xs_Schema[] = "Schema";
85 static const xmlChar xs_seq[] = "seq";
86 static const xmlChar xs_sequence[] = "sequence";
87 static const xmlChar xs_simpleContent[] = "simpleContent";
88 static const xmlChar xs_simpleType[] = "simpleType";
89 static const xmlChar xs_strict[] = "strict";
90 static const xmlChar xs_targetNamespace[] = "targetNamespace";
91 static const xmlChar xs_textOnly[] = "textOnly";
92 static const xmlChar xs_true[] = "true";
93 static const xmlChar xs_type[] = "type";
94 static const xmlChar xs_unbounded[] = "unbounded";
95 static const xmlChar xs_use[] = "use";
96 static const xmlChar xs_value[] = "value";
97 static const xmlChar xs_values[] = "values";
98 static const xmlChar xs_xsd_string[] = "xsd:string";
99 static const xmlChar xs_yes[] = "yes";
101 typedef enum _CONTENT_TYPE
103 CONTENT_EMPTY,
104 CONTENT_TEXTONLY,
105 CONTENT_ELTONLY,
106 CONTENT_MIXED
107 } CONTENT_TYPE;
109 typedef enum _ORDER_TYPE
111 ORDER_SEQ,
112 ORDER_MANY,
113 ORDER_ONE
114 } ORDER_TYPE;
116 #define FOREACH_CHILD(node, child) \
117 for (child = node->children; child != NULL; child = child->next) \
118 if (child->type == XML_ELEMENT_NODE)
120 #define FOREACH_ATTR(node, attr) \
121 for (attr = node->properties; attr != NULL; attr = attr->next)
123 #define FOREACH_NS(node, ns) \
124 for (ns = node->nsDef; ns != NULL; ns = ns->next)
126 static inline xmlNodePtr get_schema(xmlNodePtr node)
128 return xmlDocGetRootElement(node->doc);
131 static inline xmlNodePtr get_child(xmlNodePtr node, xmlChar const* name)
133 xmlNodePtr child = NULL;
134 if (node)
136 FOREACH_CHILD(node, child)
138 if (xmlStrEqual(child->name, name))
139 break;
143 return child;
146 static inline xmlNodePtr get_child_with_attr(xmlNodePtr node, xmlChar const* name,
147 xmlChar const* attr_ns, xmlChar const* attr_name,
148 xmlChar const* attr_val)
150 xmlChar* str;
151 if (node)
153 FOREACH_CHILD(node, node)
155 if (xmlStrEqual(node->name, name))
157 str = (attr_ns != NULL)? xmlGetNsProp(node, attr_name, attr_ns) :
158 xmlGetProp(node, attr_name);
159 if (str)
161 if (xmlStrEqual(str, attr_val))
163 xmlFree(str);
164 return node;
166 xmlFree(str);
172 return NULL;
175 static inline xmlNsPtr get_dt_ns(xmlNodePtr node)
177 xmlNsPtr ns;
179 node = get_schema(node);
180 assert(node != NULL);
182 FOREACH_NS(node, ns)
184 if (xmlStrEqual(ns->href, DT_href))
185 break;
188 return ns;
191 static inline xmlChar* get_dt_type(xmlNodePtr xdr)
193 xmlChar* str = xmlGetNsProp(xdr, xs_type, DT_href);
194 if (!str)
196 xmlNodePtr datatype = get_child(xdr, xs_datatype);
197 if (datatype)
198 str = xmlGetNsProp(datatype, xs_type, DT_href);
200 return str;
203 static inline xmlChar* get_attr_val(xmlAttrPtr attr)
205 return xmlNodeGetContent((xmlNodePtr)attr);
208 static inline xmlNodePtr add_any_child(xmlNodePtr parent, BOOL set_occurs)
210 xmlNodePtr child = xmlNewChild(parent, NULL, xs_any, NULL);
211 if (set_occurs)
213 xmlSetProp(child, xs_minOccurs, BAD_CAST "0");
214 xmlSetProp(child, xs_maxOccurs, xs_unbounded);
216 xmlSetProp(child, xs_processContents, xs_strict);
217 return child;
220 static inline xmlNodePtr add_anyAttribute_child(xmlNodePtr parent)
222 xmlNodePtr child = xmlNewChild(parent, NULL, xs_anyAttribute, NULL);
223 xmlSetProp(child, xs_processContents, xs_lax);
224 return child;
227 static inline xmlAttrPtr copy_prop_ignore_ns(xmlAttrPtr xdr_attr, xmlNodePtr node)
229 xmlChar* str = get_attr_val(xdr_attr);
230 xmlAttrPtr attr = xmlSetProp(node, xdr_attr->name, str);
231 xmlFree(str);
232 return attr;
234 static inline xmlAttrPtr XDR_A_default(xmlAttrPtr xdr_attr, xmlNodePtr node)
236 TRACE("(%p, %p)\n", xdr_attr, node);
238 return copy_prop_ignore_ns(xdr_attr, node);
241 static inline xmlAttrPtr XDR_A_dt_type(xmlAttrPtr xdr_attr, xmlNodePtr node)
243 xmlChar* str = get_attr_val(xdr_attr);
244 xmlAttrPtr attr;
246 TRACE("(%p, %p)\n", xdr_attr, node);
248 if (xmlStrEqual(str, xs_enumeration))
249 attr = NULL;
250 else
251 attr = xmlSetNsProp(node, get_dt_ns(node), DT_prefix, str);
252 xmlFree(str);
253 return attr;
256 static xmlAttrPtr XDR_A_maxOccurs(xmlAttrPtr xdr_attr, xmlNodePtr node)
258 xmlChar* str = get_attr_val(xdr_attr);
259 xmlAttrPtr attr;
261 TRACE("(%p, %p)\n", xdr_attr, node);
263 if (xmlStrEqual(str, BAD_CAST "*"))
264 attr = xmlSetProp(node, xs_maxOccurs, xs_unbounded);
265 else
266 attr = copy_prop_ignore_ns(xdr_attr, node);
268 xmlFree(str);
269 return attr;
272 static inline xmlAttrPtr XDR_A_minOccurs(xmlAttrPtr xdr_attr, xmlNodePtr node)
274 TRACE("(%p, %p)\n", xdr_attr, node);
276 return copy_prop_ignore_ns(xdr_attr, node);
279 static inline xmlAttrPtr XDR_A_name(xmlAttrPtr xdr_attr, xmlNodePtr node)
281 TRACE("(%p, %p)\n", xdr_attr, node);
283 return copy_prop_ignore_ns(xdr_attr, node);
286 static xmlAttrPtr XDR_A_type(xmlAttrPtr xdr_attr, xmlNodePtr node)
288 xmlChar* str = get_attr_val(xdr_attr);
289 xmlAttrPtr attr = xmlSetProp(node, xs_ref, str);
291 TRACE("(%p, %p)\n", xdr_attr, node);
293 xmlFree(str);
294 return attr;
297 static xmlAttrPtr XDR_A_required(xmlAttrPtr xdr_attr, xmlNodePtr node)
299 xmlChar* str = get_attr_val(xdr_attr);
300 xmlAttrPtr attr;
302 TRACE("(%p, %p)\n", xdr_attr, node);
304 if (xmlStrEqual(str, xs_no))
305 attr = xmlSetProp(node, xs_use, xs_optional);
306 else /* yes */
307 attr = xmlSetProp(node, xs_use, xs_required);
308 xmlFree(str);
309 return attr;
312 static xmlNodePtr XDR_E_description(xmlNodePtr xdr, xmlNodePtr parent)
314 xmlNodePtr xsd_node = xmlNewChild(parent, NULL, xs_annotation, NULL);
315 xmlAttrPtr xdr_attr;
317 TRACE("(%p, %p)\n", xdr, parent);
319 xmlNewChild(xsd_node, NULL, xs_documentation, xdr->content);
321 FOREACH_ATTR(xdr, xdr_attr)
323 xmlCopyProp(xsd_node, xdr_attr);
325 return xsd_node;
328 static xmlNodePtr XDR_E_AttributeType(xmlNodePtr xdr, xmlNodePtr parent)
330 xmlChar *str, *type = get_dt_type(xdr);
331 xmlNodePtr xsd_node, xsd_child, xdr_child;
332 xmlAttrPtr xdr_attr;
334 TRACE("(%p, %p)\n", xdr, parent);
336 xsd_node = xmlNewChild(parent, NULL, xs_attribute, NULL);
338 if (type && xmlStrEqual(type, xs_enumeration))
340 xmlChar *tmp, *tokBegin, *tokEnd = NULL;
341 xmlNodePtr xsd_enum;
342 xsd_child = xmlNewChild(xsd_node, NULL, xs_simpleType, NULL);
343 xsd_child = xmlNewChild(xsd_child, NULL, xs_restriction, NULL);
344 xmlSetProp(xsd_child, xs_base, xs_xsd_string);
346 tokBegin = str = xmlGetNsProp(xdr, xs_values, DT_href);
347 while (tokBegin && *tokBegin)
349 while (*tokBegin && isspace(*tokBegin))
350 ++tokBegin;
351 tokEnd = tokBegin;
352 while (*tokEnd && !isspace(*tokEnd))
353 ++tokEnd;
354 if (tokEnd == tokBegin)
355 break;
356 xsd_enum = xmlNewChild(xsd_child, NULL, xs_enumeration, NULL);
357 tmp = xmlStrndup(tokBegin, tokEnd-tokBegin);
358 xmlSetProp(xsd_enum, xs_value, tmp);
359 xmlFree(tmp);
360 tokBegin = tokEnd;
362 xmlFree(str);
365 else if (type)
367 str = xmlStrdup(DT_prefix);
368 str = xmlStrcat(str, BAD_CAST ":");
369 str = xmlStrcat(str, type);
370 xmlSetProp(xsd_node, xs_type, str);
371 xmlFree(str);
373 xmlFree(type);
375 FOREACH_ATTR(xdr, xdr_attr)
377 if (xmlStrEqual(xdr_attr->name, xs_default))
378 XDR_A_default(xdr_attr, xsd_node);
379 else if (xmlStrEqual(xdr_attr->name, xs_name))
380 XDR_A_name(xdr_attr, xsd_node);
381 else if (xmlStrEqual(xdr_attr->name, xs_type) && xdr_attr->ns == get_dt_ns(xdr))
382 XDR_A_dt_type(xdr_attr, xsd_node);
383 else if (xmlStrEqual(xdr_attr->name, xs_values) && xdr_attr->ns == get_dt_ns(xdr))
384 ; /* already handled */
385 else if (xmlStrEqual(xdr_attr->name, xs_required))
386 XDR_A_required(xdr_attr, xsd_node);
387 else
388 xmlCopyProp(xsd_node, xdr_attr);
391 FOREACH_CHILD(xdr, xdr_child)
393 if (xmlStrEqual(xdr_child->name, xs_datatype))
394 ; /* already handled */
395 else if (xmlStrEqual(xdr_child->name, xs_description))
396 XDR_E_description(xdr_child, xsd_node);
397 else
398 FIXME("unexpected child <%s>\n", xdr_child->name);
401 return xsd_node;
404 static xmlNodePtr XDR_E_attribute(xmlNodePtr xdr, xmlNodePtr parent)
406 xmlChar* str = xmlGetProp(xdr, xs_type);
407 xmlNodePtr xsd_node, xdr_child, xdr_attrType;
408 xmlAttrPtr xdr_attr;
410 TRACE("(%p, %p)\n", xdr, parent);
412 xdr_attrType = get_child_with_attr(xdr->parent, xs_AttributeType, NULL, xs_name, str);
413 xmlFree(str);
415 if (xdr_attrType)
416 xsd_node = XDR_E_AttributeType(xdr_attrType, parent);
417 else
418 xsd_node = xmlNewChild(parent, NULL, xs_attribute, NULL);
420 FOREACH_ATTR(xdr, xdr_attr)
422 if (xmlStrEqual(xdr_attr->name, xs_default))
423 XDR_A_default(xdr_attr, xsd_node);
424 else if (xmlStrEqual(xdr_attr->name, xs_type) && !xdr_attrType)
425 XDR_A_type(xdr_attr, xsd_node);
426 else if (xmlStrEqual(xdr_attr->name, xs_required))
427 XDR_A_required(xdr_attr, xsd_node);
428 else
429 xmlCopyProp(xsd_node, xdr_attr);
432 FOREACH_CHILD(xdr, xdr_child)
434 FIXME("unexpected child <%s>\n", xdr_child->name);
437 return xsd_node;
440 static xmlNodePtr XDR_E_element(xmlNodePtr xdr, xmlNodePtr parent)
442 xmlNodePtr xdr_child, xsd_node = xmlNewChild(parent, NULL, xs_element, NULL);
443 xmlAttrPtr xdr_attr;
445 FOREACH_ATTR(xdr, xdr_attr)
447 if (xmlStrEqual(xdr_attr->name, xs_type))
448 XDR_A_type(xdr_attr, xsd_node);
449 else if (xmlStrEqual(xdr_attr->name, xs_maxOccurs))
450 XDR_A_maxOccurs(xdr_attr, xsd_node);
451 else if (xmlStrEqual(xdr_attr->name, xs_minOccurs))
452 XDR_A_minOccurs(xdr_attr, xsd_node);
453 else
454 xmlCopyProp(xsd_node, xdr_attr);
457 FOREACH_CHILD(xdr, xdr_child)
459 FIXME("unexpected child <%s>\n", xdr_child->name);
462 return xsd_node;
465 static xmlNodePtr XDR_E_group(xmlNodePtr xdr, xmlNodePtr parent)
467 xmlNodePtr xdr_child, xsd_node;
468 xmlChar* str = xmlGetProp(xdr, xs_order);
469 xmlAttrPtr xdr_attr;
471 TRACE("(%p, %p)\n", xdr, parent);
473 if (!str || xmlStrEqual(str, xs_seq))
474 xsd_node = xmlNewChild(parent, NULL, xs_sequence, NULL);
475 else if (xmlStrEqual(str, xs_many))
476 xsd_node = xmlNewChild(parent, NULL, xs_choice, NULL);
477 else /* one */
478 xsd_node = xmlNewChild(parent, NULL, xs_all, NULL);
479 xmlFree(str);
481 FOREACH_ATTR(xdr, xdr_attr)
483 if (xmlStrEqual(xdr_attr->name, xs_order))
484 ; /* already handled */
485 else if (xmlStrEqual(xdr_attr->name, xs_model))
486 ; /* ignored */
487 else if (xmlStrEqual(xdr_attr->name, xs_maxOccurs))
488 XDR_A_maxOccurs(xdr_attr, xsd_node);
489 else if (xmlStrEqual(xdr_attr->name, xs_minOccurs))
490 XDR_A_minOccurs(xdr_attr, xsd_node);
491 else
492 xmlCopyProp(xsd_node, xdr_attr);
495 FOREACH_CHILD(xdr, xdr_child)
497 if (xmlStrEqual(xdr_child->name, xs_description))
498 XDR_E_description(xdr_child, xsd_node);
499 else if (xmlStrEqual(xdr_child->name, xs_element))
500 XDR_E_element(xdr_child, xsd_node);
503 return xsd_node;
506 static xmlNodePtr XDR_E_ElementType(xmlNodePtr xdr, xmlNodePtr parent)
508 xmlChar *str, *type = get_dt_type(xdr);
509 BOOL is_open = TRUE;
510 int n_attributes = 0, n_elements = 0, n_groups = 0;
511 CONTENT_TYPE content;
512 ORDER_TYPE order;
513 xmlNodePtr xsd_node, xsd_type, xsd_child, xdr_child;
514 xmlAttrPtr xdr_attr;
515 xmlNsPtr dt_ns = get_dt_ns(parent);
517 TRACE("(%p, %p)\n", xdr, parent);
519 str = xmlGetProp(xdr, xs_model);
520 if (str && !xmlStrEqual(str, xs_open))
521 is_open = FALSE;
522 xmlFree(str);
524 if (type)
526 content = CONTENT_TEXTONLY;
528 else
530 str = xmlGetProp(xdr, xs_content);
531 if (!str || xmlStrEqual(str, xs_mixed))
532 content = CONTENT_MIXED;
533 else if (xmlStrEqual(str, xs_eltOnly))
534 content = CONTENT_ELTONLY;
535 else if (xmlStrEqual(str, xs_textOnly))
536 content = CONTENT_TEXTONLY;
537 else /* empty */
538 content = CONTENT_EMPTY;
539 xmlFree(str);
542 str = xmlGetProp(xdr, xs_order);
543 if (!str || xmlStrEqual(str, xs_seq))
545 order = ORDER_SEQ;
547 else if (xmlStrEqual(str, xs_many))
549 order = ORDER_MANY;
551 else /* one */
553 order = ORDER_ONE;
554 is_open = FALSE;
556 xmlFree(str);
558 FOREACH_CHILD(xdr, xdr_child)
560 if (xmlStrEqual(xdr_child->name, xs_element))
561 ++n_elements;
562 else if (xmlStrEqual(xdr_child->name, xs_group))
563 ++n_groups;
564 else if (xmlStrEqual(xdr_child->name, xs_attribute))
565 ++n_attributes;
568 xsd_node = xmlNewChild(parent, NULL, xs_element, NULL);
569 assert(xsd_node != NULL);
570 switch (content)
572 case CONTENT_MIXED:
573 case CONTENT_ELTONLY:
575 xmlNodePtr xsd_base;
576 xsd_type = xmlNewChild(xsd_node, NULL, xs_complexType, NULL);
578 if (content == CONTENT_MIXED)
579 xmlSetProp(xsd_type, xs_mixed, xs_true);
581 if (is_open)
582 xsd_base = xmlNewChild(xsd_type, NULL, xs_sequence, NULL);
583 else
584 xsd_base = xsd_type;
586 if (is_open && n_elements < 2 && !n_groups)
587 {/* no specific sequence of elements we need,
588 just has to start with the right one, if any */
589 if ((xdr_child = get_child(xdr, xs_element)))
591 xsd_child = XDR_E_element(xdr_child, xsd_base);
592 xmlUnsetProp(xsd_child, xs_maxOccurs);
595 else
597 switch (order)
599 case ORDER_SEQ:
600 xsd_child = xmlNewChild(xsd_base, NULL, xs_sequence, NULL);
601 break;
602 case ORDER_MANY:
603 xsd_child = xmlNewChild(xsd_base, NULL, xs_choice, NULL);
604 xmlSetProp(xsd_child, xs_maxOccurs, xs_unbounded);
605 break;
606 case ORDER_ONE:
607 xsd_child = xmlNewChild(xsd_base, NULL, xs_all, NULL);
608 break;
611 FOREACH_CHILD(xdr, xdr_child)
613 if (xmlStrEqual(xdr_child->name, xs_element))
614 XDR_E_element(xdr_child, xsd_child);
615 else if (xmlStrEqual(xdr_child->name, xs_group))
616 XDR_E_group(xdr_child, xsd_child);
620 if (n_attributes)
622 FOREACH_CHILD(xdr, xdr_child)
624 if (xmlStrEqual(xdr_child->name, xs_attribute))
625 XDR_E_attribute(xdr_child, xsd_type);
629 if (is_open)
631 add_any_child(xsd_base, TRUE);
632 add_anyAttribute_child(xsd_type);
635 break;
636 case CONTENT_TEXTONLY:
638 if (is_open)
640 xsd_type = xmlNewChild(xsd_node, NULL, xs_complexType, NULL);
641 if (type)
643 xsd_child = xmlNewChild(xsd_type, NULL, xs_simpleContent, NULL);
644 xsd_child = xmlNewChild(xsd_child, NULL, xs_extension, NULL);
645 str = xmlStrdup(DT_prefix);
646 str = xmlStrcat(str, BAD_CAST ":");
647 str = xmlStrcat(str, type);
648 xmlSetProp(xsd_child, xs_base, str);
649 xmlFree(str);
650 assert(dt_ns != NULL);
651 xmlSetNsProp(xsd_node, dt_ns, DT_prefix, type);
653 else
655 xmlSetProp(xsd_type, xs_mixed, xs_true);
656 xsd_child = xmlNewChild(xsd_type, NULL, xs_choice, NULL);
657 xmlSetProp(xsd_child, xs_minOccurs, BAD_CAST "0");
658 xmlSetProp(xsd_child, xs_maxOccurs, xs_unbounded);
659 xsd_child = add_any_child(xsd_child, FALSE);
660 xmlSetProp(xsd_child, xs_namespace, BAD_CAST "##other");
661 xsd_child = xsd_type;
664 if (n_attributes)
665 FOREACH_CHILD(xdr, xdr_child)
667 if (xmlStrEqual(xdr_child->name, xs_attribute))
668 XDR_E_attribute(xdr_child, xsd_child);
671 xmlNewChild(xsd_child, NULL, xs_anyAttribute, NULL);
673 else if (!n_attributes)
675 if (type)
677 str = xmlStrdup(DT_prefix);
678 str = xmlStrcat(str, BAD_CAST ":");
679 str = xmlStrcat(str, type);
680 xmlSetProp(xsd_node, xs_type, str);
681 xmlFree(str);
682 str = NULL;
683 xmlSetNsProp(xsd_node, dt_ns, DT_prefix, type);
685 else
687 xmlSetProp(xsd_node, xs_type, xs_xsd_string);
690 else
692 xsd_type = xmlNewChild(xsd_node, NULL, xs_complexType, NULL);
693 xsd_child = xmlNewChild(xsd_type, NULL, xs_simpleContent, NULL);
694 xsd_child = xmlNewChild(xsd_child, NULL, xs_extension, NULL);
695 xmlSetProp(xsd_child, xs_base, xs_xsd_string);
697 FOREACH_CHILD(xdr, xdr_child)
699 if (xmlStrEqual(xdr_child->name, xs_attribute))
700 XDR_E_attribute(xdr_child, xsd_child);
704 break;
705 case CONTENT_EMPTY: /* not allowed with model="open" */
707 if (n_attributes)
709 xsd_type = xmlNewChild(xsd_node, NULL, xs_complexType, NULL);
711 FOREACH_CHILD(xdr, xdr_child)
713 if (xmlStrEqual(xdr_child->name, xs_attribute))
714 XDR_E_attribute(xdr_child, xsd_type);
717 else
719 xsd_type = xmlNewChild(xsd_node, NULL, xs_simpleType, NULL);
720 xsd_child = xmlNewChild(xsd_type, NULL, xs_restriction, NULL);
721 xmlSetProp(xsd_child, xs_base, xs_xsd_string);
722 xsd_child = xmlNewChild(xsd_child, NULL, xs_length, NULL);
723 xmlSetProp(xsd_child, xs_value, BAD_CAST "0");
726 break;
728 xmlFree(type);
730 FOREACH_ATTR(xdr, xdr_attr)
732 if (xmlStrEqual(xdr_attr->name, xs_content))
733 ; /* already handled */
734 else if (xmlStrEqual(xdr_attr->name, xs_name))
735 XDR_A_name(xdr_attr, xsd_node);
736 else if (xmlStrEqual(xdr_attr->name, xs_type) && xdr_attr->ns == get_dt_ns(xdr))
737 XDR_A_dt_type(xdr_attr, xsd_node);
738 else if (xmlStrEqual(xdr_attr->name, xs_model))
739 ; /* already handled */
740 else if (xmlStrEqual(xdr_attr->name, xs_order))
741 ; /* already handled */
742 else
743 xmlCopyProp(xsd_node, xdr_attr);
747 FOREACH_CHILD(xdr, xdr_child)
749 if (xmlStrEqual(xdr_child->name, xs_attribute))
750 ; /* already handled */
751 else if (xmlStrEqual(xdr_child->name, xs_AttributeType))
752 ; /* handled through XDR_E_attribute when parent is not <Schema> */
753 else if (xmlStrEqual(xdr_child->name, xs_datatype))
754 ; /* already handled */
755 else if (xmlStrEqual(xdr_child->name, xs_description))
756 XDR_E_description(xdr_child, xsd_node);
757 else if (xmlStrEqual(xdr_child->name, xs_element))
758 ; /* already handled */
759 else if (xmlStrEqual(xdr_child->name, xs_group))
760 ; /* already handled */
761 else
762 FIXME("unexpected child <%s>\n", xdr_child->name);
765 return xsd_node;
768 static xmlNodePtr XDR_E_Schema(xmlNodePtr xdr, xmlNodePtr parent, xmlChar const* nsURI)
770 xmlNodePtr xsd_node, xdr_child;
771 xmlNsPtr ns, xdr_ns;
772 xmlAttrPtr xdr_attr;
774 TRACE("(%p, %p)\n", xdr, parent);
776 xsd_node = xmlNewDocNode((xmlDocPtr)parent, NULL, xs_schema, NULL);
777 xmlDocSetRootElement((xmlDocPtr)parent, xsd_node);
778 assert(xsd_node != NULL);
780 if (nsURI && *nsURI) xmlNewNs(xsd_node, nsURI, NULL);
781 ns = xmlNewNs(xsd_node, XSD_href, XSD_prefix);
782 assert(ns != NULL);
784 xmlSetNs(xsd_node, ns);
786 if (nsURI && *nsURI) xmlSetProp(xsd_node, xs_targetNamespace, nsURI);
788 FOREACH_NS(xdr, xdr_ns)
790 /* TODO: special handling for dt namespace? */
791 assert(xdr_ns->href != NULL);
792 if (xmlStrEqual(xdr_ns->href, XDR_href))
793 ; /* ignored */
794 else if (xdr_ns->prefix != NULL)
795 xmlNewNs(xsd_node, xdr_ns->href, xdr_ns->prefix);
796 else
797 FIXME("unexpected default xmlns: %s\n", xdr_ns->href);
800 FOREACH_ATTR(xdr, xdr_attr)
802 xmlCopyProp(xsd_node, xdr_attr);
805 FOREACH_CHILD(xdr, xdr_child)
807 if (xmlStrEqual(xdr_child->name, xs_AttributeType))
808 XDR_E_AttributeType(xdr_child, xsd_node);
809 else if (xmlStrEqual(xdr_child->name, xs_description))
810 XDR_E_description(xdr_child, xsd_node);
811 else if (xmlStrEqual(xdr_child->name, xs_ElementType))
812 XDR_E_ElementType(xdr_child, xsd_node);
813 else
814 FIXME("unexpected child <%s>\n", xdr_child->name);
817 return xsd_node;
820 xmlDocPtr XDR_to_XSD_doc(xmlDocPtr xdr_doc, xmlChar const* nsURI)
822 xmlDocPtr xsd_doc = xmlNewDoc(NULL);
824 TRACE("(%p)\n", xdr_doc);
826 XDR_E_Schema(get_schema((xmlNodePtr)xdr_doc), (xmlNodePtr)xsd_doc, nsURI);
828 return xsd_doc;
831 #endif /* HAVE_LIBXML2 */