mfplat/sample: Optimize copying to 2d buffer.
[wine.git] / dlls / msxml3 / xdr.c
blob0ac9632c8e607a3485375b7290b66757637a3030
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
21 #include <assert.h>
22 #include <libxml/tree.h>
24 #include "wine/debug.h"
26 /* Both XDR and XSD are valid XML
27 * We just convert the doc tree, no need for a parser.
30 WINE_DEFAULT_DEBUG_CHANNEL(msxml);
32 static const xmlChar DT_prefix[] = "dt";
33 static const xmlChar DT_href[] = "urn:schemas-microsoft-com:datatypes";
34 static const xmlChar XDR_href[] = "urn:schemas-microsoft-com:xml-data";
35 static const xmlChar XSD_prefix[] = "xsd";
36 static const xmlChar XSD_href[] = "http://www.w3.org/2001/XMLSchema";
38 static const xmlChar xs_all[] = "all";
39 static const xmlChar xs_annotation[] = "annotation";
40 static const xmlChar xs_any[] = "any";
41 static const xmlChar xs_anyAttribute[] = "anyAttribute";
42 static const xmlChar xs_attribute[] = "attribute";
43 static const xmlChar xs_AttributeType[] = "AttributeType";
44 static const xmlChar xs_base[] = "base";
45 static const xmlChar xs_choice[] = "choice";
46 static const xmlChar xs_complexType[] = "complexType";
47 static const xmlChar xs_content[] = "content";
48 static const xmlChar xs_datatype[] = "datatype";
49 static const xmlChar xs_default[] = "default";
50 static const xmlChar xs_description[] = "description";
51 static const xmlChar xs_documentation[] = "documentation";
52 static const xmlChar xs_element[] = "element";
53 static const xmlChar xs_ElementType[] = "ElementType";
54 static const xmlChar xs_eltOnly[] = "eltOnly";
55 static const xmlChar xs_enumeration[] = "enumeration";
56 static const xmlChar xs_extension[] = "extension";
57 static const xmlChar xs_group[] = "group";
58 static const xmlChar xs_lax[] = "lax";
59 static const xmlChar xs_length[] = "length";
60 static const xmlChar xs_many[] = "many";
61 static const xmlChar xs_maxOccurs[] = "maxOccurs";
62 static const xmlChar xs_minOccurs[] = "minOccurs";
63 static const xmlChar xs_mixed[] = "mixed";
64 static const xmlChar xs_model[] = "model";
65 static const xmlChar xs_name[] = "name";
66 static const xmlChar xs_namespace[] = "namespace";
67 static const xmlChar xs_no[] = "no";
68 static const xmlChar xs_open[] = "open";
69 static const xmlChar xs_optional[] = "optional";
70 static const xmlChar xs_order[] = "order";
71 static const xmlChar xs_processContents[] = "processContents";
72 static const xmlChar xs_ref[] = "ref";
73 static const xmlChar xs_required[] = "required";
74 static const xmlChar xs_restriction[] = "restriction";
75 static const xmlChar xs_schema[] = "schema";
76 static const xmlChar xs_seq[] = "seq";
77 static const xmlChar xs_sequence[] = "sequence";
78 static const xmlChar xs_simpleContent[] = "simpleContent";
79 static const xmlChar xs_simpleType[] = "simpleType";
80 static const xmlChar xs_strict[] = "strict";
81 static const xmlChar xs_targetNamespace[] = "targetNamespace";
82 static const xmlChar xs_textOnly[] = "textOnly";
83 static const xmlChar xs_true[] = "true";
84 static const xmlChar xs_type[] = "type";
85 static const xmlChar xs_unbounded[] = "unbounded";
86 static const xmlChar xs_use[] = "use";
87 static const xmlChar xs_value[] = "value";
88 static const xmlChar xs_values[] = "values";
89 static const xmlChar xs_xsd_string[] = "xsd:string";
91 typedef enum _CONTENT_TYPE
93 CONTENT_EMPTY,
94 CONTENT_TEXTONLY,
95 CONTENT_ELTONLY,
96 CONTENT_MIXED
97 } CONTENT_TYPE;
99 typedef enum _ORDER_TYPE
101 ORDER_SEQ,
102 ORDER_MANY,
103 ORDER_ONE
104 } ORDER_TYPE;
106 #define FOREACH_CHILD(node, child) \
107 for (child = node->children; child != NULL; child = child->next) \
108 if (child->type == XML_ELEMENT_NODE)
110 #define FOREACH_ATTR(node, attr) \
111 for (attr = node->properties; attr != NULL; attr = attr->next)
113 #define FOREACH_NS(node, ns) \
114 for (ns = node->nsDef; ns != NULL; ns = ns->next)
116 static inline xmlNodePtr get_schema(xmlNodePtr node)
118 return xmlDocGetRootElement(node->doc);
121 static inline xmlNodePtr get_child(xmlNodePtr node, xmlChar const* name)
123 xmlNodePtr child = NULL;
124 if (node)
126 FOREACH_CHILD(node, child)
128 if (xmlStrEqual(child->name, name))
129 break;
133 return child;
136 static inline xmlNodePtr get_child_with_attr(xmlNodePtr node, xmlChar const* name,
137 xmlChar const* attr_ns, xmlChar const* attr_name,
138 xmlChar const* attr_val)
140 xmlChar* str;
141 if (node)
143 FOREACH_CHILD(node, node)
145 if (xmlStrEqual(node->name, name))
147 str = (attr_ns != NULL)? xmlGetNsProp(node, attr_name, attr_ns) :
148 xmlGetProp(node, attr_name);
149 if (str)
151 if (xmlStrEqual(str, attr_val))
153 xmlFree(str);
154 return node;
156 xmlFree(str);
162 return NULL;
165 static inline xmlNsPtr get_dt_ns(xmlNodePtr node)
167 xmlNsPtr ns;
169 node = get_schema(node);
170 assert(node != NULL);
172 FOREACH_NS(node, ns)
174 if (xmlStrEqual(ns->href, DT_href))
175 break;
178 return ns;
181 static inline xmlChar* get_dt_type(xmlNodePtr xdr)
183 xmlChar* str = xmlGetNsProp(xdr, xs_type, DT_href);
184 if (!str)
186 xmlNodePtr datatype = get_child(xdr, xs_datatype);
187 if (datatype)
188 str = xmlGetNsProp(datatype, xs_type, DT_href);
190 return str;
193 static inline xmlChar* get_attr_val(xmlAttrPtr attr)
195 return xmlNodeGetContent((xmlNodePtr)attr);
198 static inline xmlNodePtr add_any_child(xmlNodePtr parent, BOOL set_occurs)
200 xmlNodePtr child = xmlNewChild(parent, NULL, xs_any, NULL);
201 if (set_occurs)
203 xmlSetProp(child, xs_minOccurs, BAD_CAST "0");
204 xmlSetProp(child, xs_maxOccurs, xs_unbounded);
206 xmlSetProp(child, xs_processContents, xs_strict);
207 return child;
210 static inline xmlNodePtr add_anyAttribute_child(xmlNodePtr parent)
212 xmlNodePtr child = xmlNewChild(parent, NULL, xs_anyAttribute, NULL);
213 xmlSetProp(child, xs_processContents, xs_lax);
214 return child;
217 static inline xmlAttrPtr copy_prop_ignore_ns(xmlAttrPtr xdr_attr, xmlNodePtr node)
219 xmlChar* str = get_attr_val(xdr_attr);
220 xmlAttrPtr attr = xmlSetProp(node, xdr_attr->name, str);
221 xmlFree(str);
222 return attr;
224 static inline xmlAttrPtr XDR_A_default(xmlAttrPtr xdr_attr, xmlNodePtr node)
226 TRACE("(%p, %p)\n", xdr_attr, node);
228 return copy_prop_ignore_ns(xdr_attr, node);
231 static inline xmlAttrPtr XDR_A_dt_type(xmlAttrPtr xdr_attr, xmlNodePtr node)
233 xmlChar* str = get_attr_val(xdr_attr);
234 xmlAttrPtr attr;
236 TRACE("(%p, %p)\n", xdr_attr, node);
238 if (xmlStrEqual(str, xs_enumeration))
239 attr = NULL;
240 else
241 attr = xmlSetNsProp(node, get_dt_ns(node), DT_prefix, str);
242 xmlFree(str);
243 return attr;
246 static xmlAttrPtr XDR_A_maxOccurs(xmlAttrPtr xdr_attr, xmlNodePtr node)
248 xmlChar* str = get_attr_val(xdr_attr);
249 xmlAttrPtr attr;
251 TRACE("(%p, %p)\n", xdr_attr, node);
253 if (xmlStrEqual(str, BAD_CAST "*"))
254 attr = xmlSetProp(node, xs_maxOccurs, xs_unbounded);
255 else
256 attr = copy_prop_ignore_ns(xdr_attr, node);
258 xmlFree(str);
259 return attr;
262 static inline xmlAttrPtr XDR_A_minOccurs(xmlAttrPtr xdr_attr, xmlNodePtr node)
264 TRACE("(%p, %p)\n", xdr_attr, node);
266 return copy_prop_ignore_ns(xdr_attr, node);
269 static inline xmlAttrPtr XDR_A_name(xmlAttrPtr xdr_attr, xmlNodePtr node)
271 TRACE("(%p, %p)\n", xdr_attr, node);
273 return copy_prop_ignore_ns(xdr_attr, node);
276 static xmlAttrPtr XDR_A_type(xmlAttrPtr xdr_attr, xmlNodePtr node)
278 xmlChar* str = get_attr_val(xdr_attr);
279 xmlAttrPtr attr = xmlSetProp(node, xs_ref, str);
281 TRACE("(%p, %p)\n", xdr_attr, node);
283 xmlFree(str);
284 return attr;
287 static xmlAttrPtr XDR_A_required(xmlAttrPtr xdr_attr, xmlNodePtr node)
289 xmlChar* str = get_attr_val(xdr_attr);
290 xmlAttrPtr attr;
292 TRACE("(%p, %p)\n", xdr_attr, node);
294 if (xmlStrEqual(str, xs_no))
295 attr = xmlSetProp(node, xs_use, xs_optional);
296 else /* yes */
297 attr = xmlSetProp(node, xs_use, xs_required);
298 xmlFree(str);
299 return attr;
302 static xmlNodePtr XDR_E_description(xmlNodePtr xdr, xmlNodePtr parent)
304 xmlNodePtr xsd_node = xmlNewChild(parent, NULL, xs_annotation, NULL);
305 xmlAttrPtr xdr_attr;
307 TRACE("(%p, %p)\n", xdr, parent);
309 xmlNewChild(xsd_node, NULL, xs_documentation, xdr->content);
311 FOREACH_ATTR(xdr, xdr_attr)
313 xmlCopyProp(xsd_node, xdr_attr);
315 return xsd_node;
318 static xmlNodePtr XDR_E_AttributeType(xmlNodePtr xdr, xmlNodePtr parent)
320 xmlChar *str, *type = get_dt_type(xdr);
321 xmlNodePtr xsd_node, xsd_child, xdr_child;
322 xmlAttrPtr xdr_attr;
324 TRACE("(%p, %p)\n", xdr, parent);
326 xsd_node = xmlNewChild(parent, NULL, xs_attribute, NULL);
328 if (type && xmlStrEqual(type, xs_enumeration))
330 xmlChar *tmp, *tokBegin, *tokEnd = NULL;
331 xmlNodePtr xsd_enum;
332 xsd_child = xmlNewChild(xsd_node, NULL, xs_simpleType, NULL);
333 xsd_child = xmlNewChild(xsd_child, NULL, xs_restriction, NULL);
334 xmlSetProp(xsd_child, xs_base, xs_xsd_string);
336 tokBegin = str = xmlGetNsProp(xdr, xs_values, DT_href);
337 while (tokBegin && *tokBegin)
339 while (*tokBegin && isspace(*tokBegin))
340 ++tokBegin;
341 tokEnd = tokBegin;
342 while (*tokEnd && !isspace(*tokEnd))
343 ++tokEnd;
344 if (tokEnd == tokBegin)
345 break;
346 xsd_enum = xmlNewChild(xsd_child, NULL, xs_enumeration, NULL);
347 tmp = xmlStrndup(tokBegin, tokEnd-tokBegin);
348 xmlSetProp(xsd_enum, xs_value, tmp);
349 xmlFree(tmp);
350 tokBegin = tokEnd;
352 xmlFree(str);
355 else if (type)
357 str = xmlStrdup(DT_prefix);
358 str = xmlStrcat(str, BAD_CAST ":");
359 str = xmlStrcat(str, type);
360 xmlSetProp(xsd_node, xs_type, str);
361 xmlFree(str);
363 xmlFree(type);
365 FOREACH_ATTR(xdr, xdr_attr)
367 if (xmlStrEqual(xdr_attr->name, xs_default))
368 XDR_A_default(xdr_attr, xsd_node);
369 else if (xmlStrEqual(xdr_attr->name, xs_name))
370 XDR_A_name(xdr_attr, xsd_node);
371 else if (xmlStrEqual(xdr_attr->name, xs_type) && xdr_attr->ns == get_dt_ns(xdr))
372 XDR_A_dt_type(xdr_attr, xsd_node);
373 else if (xmlStrEqual(xdr_attr->name, xs_values) && xdr_attr->ns == get_dt_ns(xdr))
374 ; /* already handled */
375 else if (xmlStrEqual(xdr_attr->name, xs_required))
376 XDR_A_required(xdr_attr, xsd_node);
377 else
378 xmlCopyProp(xsd_node, xdr_attr);
381 FOREACH_CHILD(xdr, xdr_child)
383 if (xmlStrEqual(xdr_child->name, xs_datatype))
384 ; /* already handled */
385 else if (xmlStrEqual(xdr_child->name, xs_description))
386 XDR_E_description(xdr_child, xsd_node);
387 else
388 FIXME("unexpected child <%s>\n", xdr_child->name);
391 return xsd_node;
394 static xmlNodePtr XDR_E_attribute(xmlNodePtr xdr, xmlNodePtr parent)
396 xmlChar* str = xmlGetProp(xdr, xs_type);
397 xmlNodePtr xsd_node, xdr_child, xdr_attrType;
398 xmlAttrPtr xdr_attr;
400 TRACE("(%p, %p)\n", xdr, parent);
402 xdr_attrType = get_child_with_attr(xdr->parent, xs_AttributeType, NULL, xs_name, str);
403 xmlFree(str);
405 if (xdr_attrType)
406 xsd_node = XDR_E_AttributeType(xdr_attrType, parent);
407 else
408 xsd_node = xmlNewChild(parent, NULL, xs_attribute, NULL);
410 FOREACH_ATTR(xdr, xdr_attr)
412 if (xmlStrEqual(xdr_attr->name, xs_default))
413 XDR_A_default(xdr_attr, xsd_node);
414 else if (xmlStrEqual(xdr_attr->name, xs_type) && !xdr_attrType)
415 XDR_A_type(xdr_attr, xsd_node);
416 else if (xmlStrEqual(xdr_attr->name, xs_required))
417 XDR_A_required(xdr_attr, xsd_node);
418 else
419 xmlCopyProp(xsd_node, xdr_attr);
422 FOREACH_CHILD(xdr, xdr_child)
424 FIXME("unexpected child <%s>\n", xdr_child->name);
427 return xsd_node;
430 static xmlNodePtr XDR_E_element(xmlNodePtr xdr, xmlNodePtr parent)
432 xmlNodePtr xdr_child, xsd_node = xmlNewChild(parent, NULL, xs_element, NULL);
433 xmlAttrPtr xdr_attr;
435 FOREACH_ATTR(xdr, xdr_attr)
437 if (xmlStrEqual(xdr_attr->name, xs_type))
438 XDR_A_type(xdr_attr, xsd_node);
439 else if (xmlStrEqual(xdr_attr->name, xs_maxOccurs))
440 XDR_A_maxOccurs(xdr_attr, xsd_node);
441 else if (xmlStrEqual(xdr_attr->name, xs_minOccurs))
442 XDR_A_minOccurs(xdr_attr, xsd_node);
443 else
444 xmlCopyProp(xsd_node, xdr_attr);
447 FOREACH_CHILD(xdr, xdr_child)
449 FIXME("unexpected child <%s>\n", xdr_child->name);
452 return xsd_node;
455 static xmlNodePtr XDR_E_group(xmlNodePtr xdr, xmlNodePtr parent)
457 xmlNodePtr xdr_child, xsd_node;
458 xmlChar* str = xmlGetProp(xdr, xs_order);
459 xmlAttrPtr xdr_attr;
461 TRACE("(%p, %p)\n", xdr, parent);
463 if (!str || xmlStrEqual(str, xs_seq))
464 xsd_node = xmlNewChild(parent, NULL, xs_sequence, NULL);
465 else if (xmlStrEqual(str, xs_many))
466 xsd_node = xmlNewChild(parent, NULL, xs_choice, NULL);
467 else /* one */
468 xsd_node = xmlNewChild(parent, NULL, xs_all, NULL);
469 xmlFree(str);
471 FOREACH_ATTR(xdr, xdr_attr)
473 if (xmlStrEqual(xdr_attr->name, xs_order))
474 ; /* already handled */
475 else if (xmlStrEqual(xdr_attr->name, xs_model))
476 ; /* ignored */
477 else if (xmlStrEqual(xdr_attr->name, xs_maxOccurs))
478 XDR_A_maxOccurs(xdr_attr, xsd_node);
479 else if (xmlStrEqual(xdr_attr->name, xs_minOccurs))
480 XDR_A_minOccurs(xdr_attr, xsd_node);
481 else
482 xmlCopyProp(xsd_node, xdr_attr);
485 FOREACH_CHILD(xdr, xdr_child)
487 if (xmlStrEqual(xdr_child->name, xs_description))
488 XDR_E_description(xdr_child, xsd_node);
489 else if (xmlStrEqual(xdr_child->name, xs_element))
490 XDR_E_element(xdr_child, xsd_node);
493 return xsd_node;
496 static xmlNodePtr XDR_E_ElementType(xmlNodePtr xdr, xmlNodePtr parent)
498 xmlChar *str, *type = get_dt_type(xdr);
499 BOOL is_open = TRUE;
500 int n_attributes = 0, n_elements = 0, n_groups = 0;
501 CONTENT_TYPE content;
502 ORDER_TYPE order;
503 xmlNodePtr xsd_node, xsd_type, xsd_child, xdr_child;
504 xmlAttrPtr xdr_attr;
505 xmlNsPtr dt_ns = get_dt_ns(parent);
507 TRACE("(%p, %p)\n", xdr, parent);
509 str = xmlGetProp(xdr, xs_model);
510 if (str && !xmlStrEqual(str, xs_open))
511 is_open = FALSE;
512 xmlFree(str);
514 if (type)
516 content = CONTENT_TEXTONLY;
518 else
520 str = xmlGetProp(xdr, xs_content);
521 if (!str || xmlStrEqual(str, xs_mixed))
522 content = CONTENT_MIXED;
523 else if (xmlStrEqual(str, xs_eltOnly))
524 content = CONTENT_ELTONLY;
525 else if (xmlStrEqual(str, xs_textOnly))
526 content = CONTENT_TEXTONLY;
527 else /* empty */
528 content = CONTENT_EMPTY;
529 xmlFree(str);
532 str = xmlGetProp(xdr, xs_order);
533 if (!str || xmlStrEqual(str, xs_seq))
535 order = ORDER_SEQ;
537 else if (xmlStrEqual(str, xs_many))
539 order = ORDER_MANY;
541 else /* one */
543 order = ORDER_ONE;
544 is_open = FALSE;
546 xmlFree(str);
548 FOREACH_CHILD(xdr, xdr_child)
550 if (xmlStrEqual(xdr_child->name, xs_element))
551 ++n_elements;
552 else if (xmlStrEqual(xdr_child->name, xs_group))
553 ++n_groups;
554 else if (xmlStrEqual(xdr_child->name, xs_attribute))
555 ++n_attributes;
558 xsd_node = xmlNewChild(parent, NULL, xs_element, NULL);
559 assert(xsd_node != NULL);
560 switch (content)
562 case CONTENT_MIXED:
563 case CONTENT_ELTONLY:
565 xmlNodePtr xsd_base;
566 xsd_type = xmlNewChild(xsd_node, NULL, xs_complexType, NULL);
568 if (content == CONTENT_MIXED)
569 xmlSetProp(xsd_type, xs_mixed, xs_true);
571 if (is_open)
572 xsd_base = xmlNewChild(xsd_type, NULL, xs_sequence, NULL);
573 else
574 xsd_base = xsd_type;
576 if (is_open && n_elements < 2 && !n_groups)
577 {/* no specific sequence of elements we need,
578 just has to start with the right one, if any */
579 if ((xdr_child = get_child(xdr, xs_element)))
581 xsd_child = XDR_E_element(xdr_child, xsd_base);
582 xmlUnsetProp(xsd_child, xs_maxOccurs);
585 else
587 switch (order)
589 case ORDER_SEQ:
590 xsd_child = xmlNewChild(xsd_base, NULL, xs_sequence, NULL);
591 break;
592 case ORDER_MANY:
593 xsd_child = xmlNewChild(xsd_base, NULL, xs_choice, NULL);
594 xmlSetProp(xsd_child, xs_maxOccurs, xs_unbounded);
595 break;
596 case ORDER_ONE:
597 xsd_child = xmlNewChild(xsd_base, NULL, xs_all, NULL);
598 break;
601 FOREACH_CHILD(xdr, xdr_child)
603 if (xmlStrEqual(xdr_child->name, xs_element))
604 XDR_E_element(xdr_child, xsd_child);
605 else if (xmlStrEqual(xdr_child->name, xs_group))
606 XDR_E_group(xdr_child, xsd_child);
610 if (n_attributes)
612 FOREACH_CHILD(xdr, xdr_child)
614 if (xmlStrEqual(xdr_child->name, xs_attribute))
615 XDR_E_attribute(xdr_child, xsd_type);
619 if (is_open)
621 add_any_child(xsd_base, TRUE);
622 add_anyAttribute_child(xsd_type);
625 break;
626 case CONTENT_TEXTONLY:
628 if (is_open)
630 xsd_type = xmlNewChild(xsd_node, NULL, xs_complexType, NULL);
631 if (type)
633 xsd_child = xmlNewChild(xsd_type, NULL, xs_simpleContent, NULL);
634 xsd_child = xmlNewChild(xsd_child, NULL, xs_extension, NULL);
635 str = xmlStrdup(DT_prefix);
636 str = xmlStrcat(str, BAD_CAST ":");
637 str = xmlStrcat(str, type);
638 xmlSetProp(xsd_child, xs_base, str);
639 xmlFree(str);
640 assert(dt_ns != NULL);
641 xmlSetNsProp(xsd_node, dt_ns, DT_prefix, type);
643 else
645 xmlSetProp(xsd_type, xs_mixed, xs_true);
646 xsd_child = xmlNewChild(xsd_type, NULL, xs_choice, NULL);
647 xmlSetProp(xsd_child, xs_minOccurs, BAD_CAST "0");
648 xmlSetProp(xsd_child, xs_maxOccurs, xs_unbounded);
649 xsd_child = add_any_child(xsd_child, FALSE);
650 xmlSetProp(xsd_child, xs_namespace, BAD_CAST "##other");
651 xsd_child = xsd_type;
654 if (n_attributes)
655 FOREACH_CHILD(xdr, xdr_child)
657 if (xmlStrEqual(xdr_child->name, xs_attribute))
658 XDR_E_attribute(xdr_child, xsd_child);
661 xmlNewChild(xsd_child, NULL, xs_anyAttribute, NULL);
663 else if (!n_attributes)
665 if (type)
667 str = xmlStrdup(DT_prefix);
668 str = xmlStrcat(str, BAD_CAST ":");
669 str = xmlStrcat(str, type);
670 xmlSetProp(xsd_node, xs_type, str);
671 xmlFree(str);
672 str = NULL;
673 xmlSetNsProp(xsd_node, dt_ns, DT_prefix, type);
675 else
677 xmlSetProp(xsd_node, xs_type, xs_xsd_string);
680 else
682 xsd_type = xmlNewChild(xsd_node, NULL, xs_complexType, NULL);
683 xsd_child = xmlNewChild(xsd_type, NULL, xs_simpleContent, NULL);
684 xsd_child = xmlNewChild(xsd_child, NULL, xs_extension, NULL);
685 xmlSetProp(xsd_child, xs_base, xs_xsd_string);
687 FOREACH_CHILD(xdr, xdr_child)
689 if (xmlStrEqual(xdr_child->name, xs_attribute))
690 XDR_E_attribute(xdr_child, xsd_child);
694 break;
695 case CONTENT_EMPTY: /* not allowed with model="open" */
697 if (n_attributes)
699 xsd_type = xmlNewChild(xsd_node, NULL, xs_complexType, NULL);
701 FOREACH_CHILD(xdr, xdr_child)
703 if (xmlStrEqual(xdr_child->name, xs_attribute))
704 XDR_E_attribute(xdr_child, xsd_type);
707 else
709 xsd_type = xmlNewChild(xsd_node, NULL, xs_simpleType, NULL);
710 xsd_child = xmlNewChild(xsd_type, NULL, xs_restriction, NULL);
711 xmlSetProp(xsd_child, xs_base, xs_xsd_string);
712 xsd_child = xmlNewChild(xsd_child, NULL, xs_length, NULL);
713 xmlSetProp(xsd_child, xs_value, BAD_CAST "0");
716 break;
718 xmlFree(type);
720 FOREACH_ATTR(xdr, xdr_attr)
722 if (xmlStrEqual(xdr_attr->name, xs_content))
723 ; /* already handled */
724 else if (xmlStrEqual(xdr_attr->name, xs_name))
725 XDR_A_name(xdr_attr, xsd_node);
726 else if (xmlStrEqual(xdr_attr->name, xs_type) && xdr_attr->ns == get_dt_ns(xdr))
727 XDR_A_dt_type(xdr_attr, xsd_node);
728 else if (xmlStrEqual(xdr_attr->name, xs_model))
729 ; /* already handled */
730 else if (xmlStrEqual(xdr_attr->name, xs_order))
731 ; /* already handled */
732 else
733 xmlCopyProp(xsd_node, xdr_attr);
737 FOREACH_CHILD(xdr, xdr_child)
739 if (xmlStrEqual(xdr_child->name, xs_attribute))
740 ; /* already handled */
741 else if (xmlStrEqual(xdr_child->name, xs_AttributeType))
742 ; /* handled through XDR_E_attribute when parent is not <Schema> */
743 else if (xmlStrEqual(xdr_child->name, xs_datatype))
744 ; /* already handled */
745 else if (xmlStrEqual(xdr_child->name, xs_description))
746 XDR_E_description(xdr_child, xsd_node);
747 else if (xmlStrEqual(xdr_child->name, xs_element))
748 ; /* already handled */
749 else if (xmlStrEqual(xdr_child->name, xs_group))
750 ; /* already handled */
751 else
752 FIXME("unexpected child <%s>\n", xdr_child->name);
755 return xsd_node;
758 static xmlNodePtr XDR_E_Schema(xmlNodePtr xdr, xmlNodePtr parent, xmlChar const* nsURI)
760 xmlNodePtr xsd_node, xdr_child;
761 xmlNsPtr ns, xdr_ns;
762 xmlAttrPtr xdr_attr;
764 TRACE("(%p, %p)\n", xdr, parent);
766 xsd_node = xmlNewDocNode((xmlDocPtr)parent, NULL, xs_schema, NULL);
767 xmlDocSetRootElement((xmlDocPtr)parent, xsd_node);
768 assert(xsd_node != NULL);
770 if (nsURI && *nsURI) xmlNewNs(xsd_node, nsURI, NULL);
771 ns = xmlNewNs(xsd_node, XSD_href, XSD_prefix);
772 assert(ns != NULL);
774 xmlSetNs(xsd_node, ns);
776 if (nsURI && *nsURI) xmlSetProp(xsd_node, xs_targetNamespace, nsURI);
778 FOREACH_NS(xdr, xdr_ns)
780 /* TODO: special handling for dt namespace? */
781 assert(xdr_ns->href != NULL);
782 if (xmlStrEqual(xdr_ns->href, XDR_href))
783 ; /* ignored */
784 else if (xdr_ns->prefix != NULL)
785 xmlNewNs(xsd_node, xdr_ns->href, xdr_ns->prefix);
786 else
787 FIXME("unexpected default xmlns: %s\n", xdr_ns->href);
790 FOREACH_ATTR(xdr, xdr_attr)
792 xmlCopyProp(xsd_node, xdr_attr);
795 FOREACH_CHILD(xdr, xdr_child)
797 if (xmlStrEqual(xdr_child->name, xs_AttributeType))
798 XDR_E_AttributeType(xdr_child, xsd_node);
799 else if (xmlStrEqual(xdr_child->name, xs_description))
800 XDR_E_description(xdr_child, xsd_node);
801 else if (xmlStrEqual(xdr_child->name, xs_ElementType))
802 XDR_E_ElementType(xdr_child, xsd_node);
803 else
804 FIXME("unexpected child <%s>\n", xdr_child->name);
807 return xsd_node;
810 xmlDocPtr XDR_to_XSD_doc(xmlDocPtr xdr_doc, xmlChar const* nsURI)
812 xmlDocPtr xsd_doc = xmlNewDoc(NULL);
814 TRACE("(%p)\n", xdr_doc);
816 XDR_E_Schema(get_schema((xmlNodePtr)xdr_doc), (xmlNodePtr)xsd_doc, nsURI);
818 return xsd_doc;