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