ntdll/tests: Skip test if LdrAddRefDll is missing.
[wine.git] / dlls / msxml3 / xdr.c
blobaf86907184355d0ef7aa9d26121ebe6e72b9e654
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"
24 #include <assert.h>
25 #ifdef HAVE_LIBXML2
26 # include <libxml/tree.h>
27 #endif
29 #include "wine/debug.h"
31 WINE_DEFAULT_DEBUG_CHANNEL(msxml);
33 /* Both XDR and XSD are valid XML
34 * We just convert the doc tree, no need for a parser.
37 #ifdef HAVE_LIBXML2
39 static const xmlChar DT_prefix[] = "dt";
40 static const xmlChar DT_href[] = "urn:schemas-microsoft-com:datatypes";
41 static const xmlChar XDR_prefix[] = "xdr";
42 static const xmlChar XDR_href[] = "urn:schemas-microsoft-com:xml-data";
43 static const xmlChar XSD_prefix[] = "xsd";
44 static const xmlChar XSD_href[] = "http://www.w3.org/2001/XMLSchema";
46 static const xmlChar xs_all[] = "all";
47 static const xmlChar xs_annotation[] = "annotation";
48 static const xmlChar xs_any[] = "any";
49 static const xmlChar xs_anyAttribute[] = "anyAttribute";
50 static const xmlChar xs_attribute[] = "attribute";
51 static const xmlChar xs_AttributeType[] = "AttributeType";
52 static const xmlChar xs_base[] = "base";
53 static const xmlChar xs_choice[] = "choice";
54 static const xmlChar xs_complexContent[] = "complexContent";
55 static const xmlChar xs_complexType[] = "complexType";
56 static const xmlChar xs_content[] = "content";
57 static const xmlChar xs_datatype[] = "datatype";
58 static const xmlChar xs_default[] = "default";
59 static const xmlChar xs_description[] = "description";
60 static const xmlChar xs_documentation[] = "documentation";
61 static const xmlChar xs_element[] = "element";
62 static const xmlChar xs_ElementType[] = "ElementType";
63 static const xmlChar xs_eltOnly[] = "eltOnly";
64 static const xmlChar xs_empty[] = "empty";
65 static const xmlChar xs_enumeration[] = "enumeration";
66 static const xmlChar xs_extension[] = "extension";
67 static const xmlChar xs_group[] = "group";
68 static const xmlChar xs_lax[] = "lax";
69 static const xmlChar xs_length[] = "length";
70 static const xmlChar xs_many[] = "many";
71 static const xmlChar xs_maxOccurs[] = "maxOccurs";
72 static const xmlChar xs_minOccurs[] = "minOccurs";
73 static const xmlChar xs_mixed[] = "mixed";
74 static const xmlChar xs_model[] = "model";
75 static const xmlChar xs_name[] = "name";
76 static const xmlChar xs_namespace[] = "namespace";
77 static const xmlChar xs_no[] = "no";
78 static const xmlChar xs_one[] = "one";
79 static const xmlChar xs_open[] = "open";
80 static const xmlChar xs_optional[] = "optional";
81 static const xmlChar xs_order[] = "order";
82 static const xmlChar xs_processContents[] = "processContents";
83 static const xmlChar xs_ref[] = "ref";
84 static const xmlChar xs_required[] = "required";
85 static const xmlChar xs_restriction[] = "restriction";
86 static const xmlChar xs_schema[] = "schema";
87 static const xmlChar xs_Schema[] = "Schema";
88 static const xmlChar xs_seq[] = "seq";
89 static const xmlChar xs_sequence[] = "sequence";
90 static const xmlChar xs_simpleContent[] = "simpleContent";
91 static const xmlChar xs_simpleType[] = "simpleType";
92 static const xmlChar xs_strict[] = "strict";
93 static const xmlChar xs_targetNamespace[] = "targetNamespace";
94 static const xmlChar xs_textOnly[] = "textOnly";
95 static const xmlChar xs_true[] = "true";
96 static const xmlChar xs_type[] = "type";
97 static const xmlChar xs_unbounded[] = "unbounded";
98 static const xmlChar xs_use[] = "use";
99 static const xmlChar xs_value[] = "value";
100 static const xmlChar xs_values[] = "values";
101 static const xmlChar xs_xsd_string[] = "xsd:string";
102 static const xmlChar xs_yes[] = "yes";
104 typedef enum _CONTENT_TYPE
106 CONTENT_EMPTY,
107 CONTENT_TEXTONLY,
108 CONTENT_ELTONLY,
109 CONTENT_MIXED
110 } CONTENT_TYPE;
112 typedef enum _ORDER_TYPE
114 ORDER_SEQ,
115 ORDER_MANY,
116 ORDER_ONE
117 } ORDER_TYPE;
119 #define FOREACH_CHILD(node, child) \
120 for (child = node->children; child != NULL; child = child->next) \
121 if (child->type == XML_ELEMENT_NODE)
123 #define FOREACH_ATTR(node, attr) \
124 for (attr = node->properties; attr != NULL; attr = attr->next)
126 #define FOREACH_NS(node, ns) \
127 for (ns = node->nsDef; ns != NULL; ns = ns->next)
129 static inline xmlNodePtr get_schema(xmlNodePtr node)
131 return xmlDocGetRootElement(node->doc);
134 static inline xmlNodePtr get_child(xmlNodePtr node, xmlChar const* name)
136 xmlNodePtr child = NULL;
137 if (node)
139 FOREACH_CHILD(node, child)
141 if (xmlStrEqual(child->name, name))
142 break;
146 return child;
149 static inline xmlNodePtr get_child_with_attr(xmlNodePtr node, xmlChar const* name,
150 xmlChar const* attr_ns, xmlChar const* attr_name,
151 xmlChar const* attr_val)
153 xmlChar* str;
154 if (node)
156 FOREACH_CHILD(node, node)
158 if (xmlStrEqual(node->name, name))
160 str = (attr_ns != NULL)? xmlGetNsProp(node, attr_name, attr_ns) :
161 xmlGetProp(node, attr_name);
162 if (str)
164 if (xmlStrEqual(str, attr_val))
166 xmlFree(str);
167 return node;
169 xmlFree(str);
175 return NULL;
178 static inline xmlNsPtr get_dt_ns(xmlNodePtr node)
180 xmlNsPtr ns;
182 node = get_schema(node);
183 assert(node != NULL);
185 FOREACH_NS(node, ns)
187 if (xmlStrEqual(ns->href, DT_href))
188 break;
191 return ns;
194 static inline xmlChar* get_dt_type(xmlNodePtr xdr)
196 xmlChar* str = xmlGetNsProp(xdr, xs_type, DT_href);
197 if (!str)
199 xmlNodePtr datatype = get_child(xdr, xs_datatype);
200 if (datatype)
201 str = xmlGetNsProp(datatype, xs_type, DT_href);
203 return str;
206 static inline xmlChar* get_attr_val(xmlAttrPtr attr)
208 return xmlNodeGetContent((xmlNodePtr)attr);
211 static inline xmlNodePtr add_any_child(xmlNodePtr parent, BOOL set_occurs)
213 xmlNodePtr child = xmlNewChild(parent, NULL, xs_any, NULL);
214 if (set_occurs)
216 xmlSetProp(child, xs_minOccurs, BAD_CAST "0");
217 xmlSetProp(child, xs_maxOccurs, xs_unbounded);
219 xmlSetProp(child, xs_processContents, xs_strict);
220 return child;
223 static inline xmlNodePtr add_anyAttribute_child(xmlNodePtr parent)
225 xmlNodePtr child = xmlNewChild(parent, NULL, xs_anyAttribute, NULL);
226 xmlSetProp(child, xs_processContents, xs_lax);
227 return child;
230 static inline xmlAttrPtr copy_prop_ignore_ns(xmlAttrPtr xdr_attr, xmlNodePtr node)
232 xmlChar* str = get_attr_val(xdr_attr);
233 xmlAttrPtr attr = xmlSetProp(node, xdr_attr->name, str);
234 xmlFree(str);
235 return attr;
237 static inline xmlAttrPtr XDR_A_default(xmlAttrPtr xdr_attr, xmlNodePtr node)
239 TRACE("(%p, %p)\n", xdr_attr, node);
241 return copy_prop_ignore_ns(xdr_attr, node);
244 static inline xmlAttrPtr XDR_A_dt_type(xmlAttrPtr xdr_attr, xmlNodePtr node)
246 xmlChar* str = get_attr_val(xdr_attr);
247 xmlAttrPtr attr;
249 TRACE("(%p, %p)\n", xdr_attr, node);
251 if (xmlStrEqual(str, xs_enumeration))
252 attr = NULL;
253 else
254 attr = xmlSetNsProp(node, get_dt_ns(node), DT_prefix, str);
255 xmlFree(str);
256 return attr;
259 static xmlAttrPtr XDR_A_maxOccurs(xmlAttrPtr xdr_attr, xmlNodePtr node)
261 xmlChar* str = get_attr_val(xdr_attr);
262 xmlAttrPtr attr;
264 TRACE("(%p, %p)\n", xdr_attr, node);
266 if (xmlStrEqual(str, BAD_CAST "*"))
267 attr = xmlSetProp(node, xs_maxOccurs, xs_unbounded);
268 else
269 attr = copy_prop_ignore_ns(xdr_attr, node);
271 xmlFree(str);
272 return attr;
275 static inline xmlAttrPtr XDR_A_minOccurs(xmlAttrPtr xdr_attr, xmlNodePtr node)
277 TRACE("(%p, %p)\n", xdr_attr, node);
279 return copy_prop_ignore_ns(xdr_attr, node);
282 static inline xmlAttrPtr XDR_A_name(xmlAttrPtr xdr_attr, xmlNodePtr node)
284 TRACE("(%p, %p)\n", xdr_attr, node);
286 return copy_prop_ignore_ns(xdr_attr, node);
289 static xmlAttrPtr XDR_A_type(xmlAttrPtr xdr_attr, xmlNodePtr node)
291 xmlChar* str = get_attr_val(xdr_attr);
292 xmlAttrPtr attr = xmlSetProp(node, xs_ref, str);
294 TRACE("(%p, %p)\n", xdr_attr, node);
296 xmlFree(str);
297 return attr;
300 static xmlAttrPtr XDR_A_required(xmlAttrPtr xdr_attr, xmlNodePtr node)
302 xmlChar* str = get_attr_val(xdr_attr);
303 xmlAttrPtr attr;
305 TRACE("(%p, %p)\n", xdr_attr, node);
307 if (xmlStrEqual(str, xs_no))
308 attr = xmlSetProp(node, xs_use, xs_optional);
309 else /* yes */
310 attr = xmlSetProp(node, xs_use, xs_required);
311 xmlFree(str);
312 return attr;
315 static xmlNodePtr XDR_E_description(xmlNodePtr xdr, xmlNodePtr parent)
317 xmlNodePtr xsd_node = xmlNewChild(parent, NULL, xs_annotation, NULL);
318 xmlAttrPtr xdr_attr;
320 TRACE("(%p, %p)\n", xdr, parent);
322 xmlNewChild(xsd_node, NULL, xs_documentation, xdr->content);
324 FOREACH_ATTR(xdr, xdr_attr)
326 xmlCopyProp(xsd_node, xdr_attr);
328 return xsd_node;
331 static xmlNodePtr XDR_E_AttributeType(xmlNodePtr xdr, xmlNodePtr parent)
333 xmlChar *str, *type = get_dt_type(xdr);
334 xmlNodePtr xsd_node, xsd_child, xdr_child;
335 xmlAttrPtr xdr_attr;
337 TRACE("(%p, %p)\n", xdr, parent);
339 xsd_node = xmlNewChild(parent, NULL, xs_attribute, NULL);
341 if (type && xmlStrEqual(type, xs_enumeration))
343 xmlChar *tmp, *tokBegin, *tokEnd = NULL;
344 xmlNodePtr xsd_enum;
345 xsd_child = xmlNewChild(xsd_node, NULL, xs_simpleType, NULL);
346 xsd_child = xmlNewChild(xsd_child, NULL, xs_restriction, NULL);
347 xmlSetProp(xsd_child, xs_base, xs_xsd_string);
349 tokBegin = str = xmlGetNsProp(xdr, xs_values, DT_href);
350 while (tokBegin && *tokBegin)
352 while (*tokBegin && isspace(*tokBegin))
353 ++tokBegin;
354 tokEnd = tokBegin;
355 while (*tokEnd && !isspace(*tokEnd))
356 ++tokEnd;
357 if (tokEnd == tokBegin)
358 break;
359 xsd_enum = xmlNewChild(xsd_child, NULL, xs_enumeration, NULL);
360 tmp = xmlStrndup(tokBegin, tokEnd-tokBegin);
361 xmlSetProp(xsd_enum, xs_value, tmp);
362 xmlFree(tmp);
363 tokBegin = tokEnd;
365 xmlFree(str);
368 else if (type)
370 str = xmlStrdup(DT_prefix);
371 str = xmlStrcat(str, BAD_CAST ":");
372 str = xmlStrcat(str, type);
373 xmlSetProp(xsd_node, xs_type, str);
374 xmlFree(str);
376 xmlFree(type);
378 FOREACH_ATTR(xdr, xdr_attr)
380 if (xmlStrEqual(xdr_attr->name, xs_default))
381 XDR_A_default(xdr_attr, xsd_node);
382 else if (xmlStrEqual(xdr_attr->name, xs_name))
383 XDR_A_name(xdr_attr, xsd_node);
384 else if (xmlStrEqual(xdr_attr->name, xs_type) && xdr_attr->ns == get_dt_ns(xdr))
385 XDR_A_dt_type(xdr_attr, xsd_node);
386 else if (xmlStrEqual(xdr_attr->name, xs_values) && xdr_attr->ns == get_dt_ns(xdr))
387 ; /* already handled */
388 else if (xmlStrEqual(xdr_attr->name, xs_required))
389 XDR_A_required(xdr_attr, xsd_node);
390 else
391 xmlCopyProp(xsd_node, xdr_attr);
394 FOREACH_CHILD(xdr, xdr_child)
396 if (xmlStrEqual(xdr_child->name, xs_datatype))
397 ; /* already handled */
398 else if (xmlStrEqual(xdr_child->name, xs_description))
399 XDR_E_description(xdr_child, xsd_node);
400 else
401 FIXME("unexpected child <%s>\n", xdr_child->name);
404 return xsd_node;
407 static xmlNodePtr XDR_E_attribute(xmlNodePtr xdr, xmlNodePtr parent)
409 xmlChar* str = xmlGetProp(xdr, xs_type);
410 xmlNodePtr xsd_node, xdr_child, xdr_attrType;
411 xmlAttrPtr xdr_attr;
413 TRACE("(%p, %p)\n", xdr, parent);
415 xdr_attrType = get_child_with_attr(xdr->parent, xs_AttributeType, NULL, xs_name, str);
416 xmlFree(str);
418 if (xdr_attrType)
419 xsd_node = XDR_E_AttributeType(xdr_attrType, parent);
420 else
421 xsd_node = xmlNewChild(parent, NULL, xs_attribute, NULL);
423 FOREACH_ATTR(xdr, xdr_attr)
425 if (xmlStrEqual(xdr_attr->name, xs_default))
426 XDR_A_default(xdr_attr, xsd_node);
427 else if (xmlStrEqual(xdr_attr->name, xs_type) && !xdr_attrType)
428 XDR_A_type(xdr_attr, xsd_node);
429 else if (xmlStrEqual(xdr_attr->name, xs_required))
430 XDR_A_required(xdr_attr, xsd_node);
431 else
432 xmlCopyProp(xsd_node, xdr_attr);
435 FOREACH_CHILD(xdr, xdr_child)
437 FIXME("unexpected child <%s>\n", xdr_child->name);
440 return xsd_node;
443 static xmlNodePtr XDR_E_element(xmlNodePtr xdr, xmlNodePtr parent)
445 xmlNodePtr xdr_child, xsd_node = xmlNewChild(parent, NULL, xs_element, NULL);
446 xmlAttrPtr xdr_attr;
448 FOREACH_ATTR(xdr, xdr_attr)
450 if (xmlStrEqual(xdr_attr->name, xs_type))
451 XDR_A_type(xdr_attr, xsd_node);
452 else if (xmlStrEqual(xdr_attr->name, xs_maxOccurs))
453 XDR_A_maxOccurs(xdr_attr, xsd_node);
454 else if (xmlStrEqual(xdr_attr->name, xs_minOccurs))
455 XDR_A_minOccurs(xdr_attr, xsd_node);
456 else
457 xmlCopyProp(xsd_node, xdr_attr);
460 FOREACH_CHILD(xdr, xdr_child)
462 FIXME("unexpected child <%s>\n", xdr_child->name);
465 return xsd_node;
468 static xmlNodePtr XDR_E_group(xmlNodePtr xdr, xmlNodePtr parent)
470 xmlNodePtr xdr_child, xsd_node;
471 xmlChar* str = xmlGetProp(xdr, xs_order);
472 xmlAttrPtr xdr_attr;
474 TRACE("(%p, %p)\n", xdr, parent);
476 if (!str || xmlStrEqual(str, xs_seq))
477 xsd_node = xmlNewChild(parent, NULL, xs_sequence, NULL);
478 else if (xmlStrEqual(str, xs_many))
479 xsd_node = xmlNewChild(parent, NULL, xs_choice, NULL);
480 else /* one */
481 xsd_node = xmlNewChild(parent, NULL, xs_all, NULL);
482 xmlFree(str);
484 FOREACH_ATTR(xdr, xdr_attr)
486 if (xmlStrEqual(xdr_attr->name, xs_order))
487 ; /* already handled */
488 else if (xmlStrEqual(xdr_attr->name, xs_model))
489 ; /* ignored */
490 else if (xmlStrEqual(xdr_attr->name, xs_maxOccurs))
491 XDR_A_maxOccurs(xdr_attr, xsd_node);
492 else if (xmlStrEqual(xdr_attr->name, xs_minOccurs))
493 XDR_A_minOccurs(xdr_attr, xsd_node);
494 else
495 xmlCopyProp(xsd_node, xdr_attr);
498 FOREACH_CHILD(xdr, xdr_child)
500 if (xmlStrEqual(xdr_child->name, xs_description))
501 XDR_E_description(xdr_child, xsd_node);
502 else if (xmlStrEqual(xdr_child->name, xs_element))
503 XDR_E_element(xdr_child, xsd_node);
506 return xsd_node;
509 static xmlNodePtr XDR_E_ElementType(xmlNodePtr xdr, xmlNodePtr parent)
511 xmlChar *str, *type = get_dt_type(xdr);
512 BOOL is_open = TRUE;
513 int n_attributes = 0, n_elements = 0, n_groups = 0;
514 CONTENT_TYPE content;
515 ORDER_TYPE order;
516 xmlNodePtr xsd_node, xsd_type, xsd_child, xdr_child;
517 xmlAttrPtr xdr_attr;
518 xmlNsPtr dt_ns = get_dt_ns(parent);
520 TRACE("(%p, %p)\n", xdr, parent);
522 str = xmlGetProp(xdr, xs_model);
523 if (str && !xmlStrEqual(str, xs_open))
524 is_open = FALSE;
525 xmlFree(str);
527 if (type)
529 content = CONTENT_TEXTONLY;
531 else
533 str = xmlGetProp(xdr, xs_content);
534 if (!str || xmlStrEqual(str, xs_mixed))
535 content = CONTENT_MIXED;
536 else if (xmlStrEqual(str, xs_eltOnly))
537 content = CONTENT_ELTONLY;
538 else if (xmlStrEqual(str, xs_textOnly))
539 content = CONTENT_TEXTONLY;
540 else /* empty */
541 content = CONTENT_EMPTY;
542 xmlFree(str);
545 str = xmlGetProp(xdr, xs_order);
546 if (!str || xmlStrEqual(str, xs_seq))
548 order = ORDER_SEQ;
550 else if (xmlStrEqual(str, xs_many))
552 order = ORDER_MANY;
554 else /* one */
556 order = ORDER_ONE;
557 is_open = FALSE;
559 xmlFree(str);
561 FOREACH_CHILD(xdr, xdr_child)
563 if (xmlStrEqual(xdr_child->name, xs_element))
564 ++n_elements;
565 else if (xmlStrEqual(xdr_child->name, xs_group))
566 ++n_groups;
567 else if (xmlStrEqual(xdr_child->name, xs_attribute))
568 ++n_attributes;
571 xsd_node = xmlNewChild(parent, NULL, xs_element, NULL);
572 assert(xsd_node != NULL);
573 switch (content)
575 case CONTENT_MIXED:
576 case CONTENT_ELTONLY:
578 xmlNodePtr xsd_base;
579 xsd_type = xmlNewChild(xsd_node, NULL, xs_complexType, NULL);
581 if (content == CONTENT_MIXED)
582 xmlSetProp(xsd_type, xs_mixed, xs_true);
584 if (is_open)
585 xsd_base = xmlNewChild(xsd_type, NULL, xs_sequence, NULL);
586 else
587 xsd_base = xsd_type;
589 if (is_open && n_elements < 2 && !n_groups)
590 {/* no specific sequence of elements we need,
591 just has to start with the right one, if any */
592 if ((xdr_child = get_child(xdr, xs_element)))
594 xsd_child = XDR_E_element(xdr_child, xsd_base);
595 xmlUnsetProp(xsd_child, xs_maxOccurs);
598 else
600 switch (order)
602 case ORDER_SEQ:
603 xsd_child = xmlNewChild(xsd_base, NULL, xs_sequence, NULL);
604 break;
605 case ORDER_MANY:
606 xsd_child = xmlNewChild(xsd_base, NULL, xs_choice, NULL);
607 xmlSetProp(xsd_child, xs_maxOccurs, xs_unbounded);
608 break;
609 case ORDER_ONE:
610 xsd_child = xmlNewChild(xsd_base, NULL, xs_all, NULL);
611 break;
614 FOREACH_CHILD(xdr, xdr_child)
616 if (xmlStrEqual(xdr_child->name, xs_element))
617 XDR_E_element(xdr_child, xsd_child);
618 else if (xmlStrEqual(xdr_child->name, xs_group))
619 XDR_E_group(xdr_child, xsd_child);
623 if (n_attributes)
625 FOREACH_CHILD(xdr, xdr_child)
627 if (xmlStrEqual(xdr_child->name, xs_attribute))
628 XDR_E_attribute(xdr_child, xsd_type);
632 if (is_open)
634 add_any_child(xsd_base, TRUE);
635 add_anyAttribute_child(xsd_type);
638 break;
639 case CONTENT_TEXTONLY:
641 if (is_open)
643 xsd_type = xmlNewChild(xsd_node, NULL, xs_complexType, NULL);
644 if (type)
646 xsd_child = xmlNewChild(xsd_type, NULL, xs_simpleContent, NULL);
647 xsd_child = xmlNewChild(xsd_child, NULL, xs_extension, NULL);
648 str = xmlStrdup(DT_prefix);
649 str = xmlStrcat(str, BAD_CAST ":");
650 str = xmlStrcat(str, type);
651 xmlSetProp(xsd_child, xs_base, str);
652 xmlFree(str);
653 assert(dt_ns != NULL);
654 xmlSetNsProp(xsd_node, dt_ns, DT_prefix, type);
656 else
658 xmlSetProp(xsd_type, xs_mixed, xs_true);
659 xsd_child = xmlNewChild(xsd_type, NULL, xs_choice, NULL);
660 xmlSetProp(xsd_child, xs_minOccurs, BAD_CAST "0");
661 xmlSetProp(xsd_child, xs_maxOccurs, xs_unbounded);
662 xsd_child = add_any_child(xsd_child, FALSE);
663 xmlSetProp(xsd_child, xs_namespace, BAD_CAST "##other");
664 xsd_child = xsd_type;
667 if (n_attributes)
668 FOREACH_CHILD(xdr, xdr_child)
670 if (xmlStrEqual(xdr_child->name, xs_attribute))
671 XDR_E_attribute(xdr_child, xsd_child);
674 xmlNewChild(xsd_child, NULL, xs_anyAttribute, NULL);
676 else if (!n_attributes)
678 if (type)
680 str = xmlStrdup(DT_prefix);
681 str = xmlStrcat(str, BAD_CAST ":");
682 str = xmlStrcat(str, type);
683 xmlSetProp(xsd_node, xs_type, str);
684 xmlFree(str);
685 str = NULL;
686 xmlSetNsProp(xsd_node, dt_ns, DT_prefix, type);
688 else
690 xmlSetProp(xsd_node, xs_type, xs_xsd_string);
693 else
695 xsd_type = xmlNewChild(xsd_node, NULL, xs_complexType, NULL);
696 xsd_child = xmlNewChild(xsd_type, NULL, xs_simpleContent, NULL);
697 xsd_child = xmlNewChild(xsd_child, NULL, xs_extension, NULL);
698 xmlSetProp(xsd_child, xs_base, xs_xsd_string);
700 FOREACH_CHILD(xdr, xdr_child)
702 if (xmlStrEqual(xdr_child->name, xs_attribute))
703 XDR_E_attribute(xdr_child, xsd_child);
707 break;
708 case CONTENT_EMPTY: /* not allowed with model="open" */
710 if (n_attributes)
712 xsd_type = xmlNewChild(xsd_node, NULL, xs_complexType, NULL);
714 FOREACH_CHILD(xdr, xdr_child)
716 if (xmlStrEqual(xdr_child->name, xs_attribute))
717 XDR_E_attribute(xdr_child, xsd_type);
720 else
722 xsd_type = xmlNewChild(xsd_node, NULL, xs_simpleType, NULL);
723 xsd_child = xmlNewChild(xsd_type, NULL, xs_restriction, NULL);
724 xmlSetProp(xsd_child, xs_base, xs_xsd_string);
725 xsd_child = xmlNewChild(xsd_child, NULL, xs_length, NULL);
726 xmlSetProp(xsd_child, xs_value, BAD_CAST "0");
729 break;
731 xmlFree(type);
733 FOREACH_ATTR(xdr, xdr_attr)
735 if (xmlStrEqual(xdr_attr->name, xs_content))
736 ; /* already handled */
737 else if (xmlStrEqual(xdr_attr->name, xs_name))
738 XDR_A_name(xdr_attr, xsd_node);
739 else if (xmlStrEqual(xdr_attr->name, xs_type) && xdr_attr->ns == get_dt_ns(xdr))
740 XDR_A_dt_type(xdr_attr, xsd_node);
741 else if (xmlStrEqual(xdr_attr->name, xs_model))
742 ; /* already handled */
743 else if (xmlStrEqual(xdr_attr->name, xs_order))
744 ; /* already handled */
745 else
746 xmlCopyProp(xsd_node, xdr_attr);
750 FOREACH_CHILD(xdr, xdr_child)
752 if (xmlStrEqual(xdr_child->name, xs_attribute))
753 ; /* already handled */
754 else if (xmlStrEqual(xdr_child->name, xs_AttributeType))
755 ; /* handled through XDR_E_attribute when parent is not <Schema> */
756 else if (xmlStrEqual(xdr_child->name, xs_datatype))
757 ; /* already handled */
758 else if (xmlStrEqual(xdr_child->name, xs_description))
759 XDR_E_description(xdr_child, xsd_node);
760 else if (xmlStrEqual(xdr_child->name, xs_element))
761 ; /* already handled */
762 else if (xmlStrEqual(xdr_child->name, xs_group))
763 ; /* already handled */
764 else
765 FIXME("unexpected child <%s>\n", xdr_child->name);
768 return xsd_node;
771 static xmlNodePtr XDR_E_Schema(xmlNodePtr xdr, xmlNodePtr parent, xmlChar const* nsURI)
773 xmlNodePtr xsd_node, xdr_child;
774 xmlNsPtr ns, xdr_ns;
775 xmlAttrPtr xdr_attr;
777 TRACE("(%p, %p)\n", xdr, parent);
779 xsd_node = xmlNewDocNode((xmlDocPtr)parent, NULL, xs_schema, NULL);
780 xmlDocSetRootElement((xmlDocPtr)parent, xsd_node);
781 assert(xsd_node != NULL);
783 if (nsURI && *nsURI) xmlNewNs(xsd_node, nsURI, NULL);
784 ns = xmlNewNs(xsd_node, XSD_href, XSD_prefix);
785 assert(ns != NULL);
787 xmlSetNs(xsd_node, ns);
789 if (nsURI && *nsURI) xmlSetProp(xsd_node, xs_targetNamespace, nsURI);
791 FOREACH_NS(xdr, xdr_ns)
793 /* TODO: special handling for dt namespace? */
794 assert(xdr_ns->href != NULL);
795 if (xmlStrEqual(xdr_ns->href, XDR_href))
796 ; /* ignored */
797 else if (xdr_ns->prefix != NULL)
798 xmlNewNs(xsd_node, xdr_ns->href, xdr_ns->prefix);
799 else
800 FIXME("unexpected default xmlns: %s\n", xdr_ns->href);
803 FOREACH_ATTR(xdr, xdr_attr)
805 xmlCopyProp(xsd_node, xdr_attr);
808 FOREACH_CHILD(xdr, xdr_child)
810 if (xmlStrEqual(xdr_child->name, xs_AttributeType))
811 XDR_E_AttributeType(xdr_child, xsd_node);
812 else if (xmlStrEqual(xdr_child->name, xs_description))
813 XDR_E_description(xdr_child, xsd_node);
814 else if (xmlStrEqual(xdr_child->name, xs_ElementType))
815 XDR_E_ElementType(xdr_child, xsd_node);
816 else
817 FIXME("unexpected child <%s>\n", xdr_child->name);
820 return xsd_node;
823 xmlDocPtr XDR_to_XSD_doc(xmlDocPtr xdr_doc, xmlChar const* nsURI)
825 xmlDocPtr xsd_doc = xmlNewDoc(NULL);
827 TRACE("(%p)\n", xdr_doc);
829 XDR_E_Schema(get_schema((xmlNodePtr)xdr_doc), (xmlNodePtr)xsd_doc, nsURI);
831 return xsd_doc;
834 #endif /* HAVE_LIBXML2 */