ReactOS  0.4.15-dev-3745-g356babc
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 
39 static const xmlChar DT_prefix[] = "dt";
40 static const xmlChar DT_href[] = "urn:schemas-microsoft-com:datatypes";
41 static const xmlChar XDR_href[] = "urn:schemas-microsoft-com:xml-data";
42 static const xmlChar XSD_prefix[] = "xsd";
43 static const xmlChar XSD_href[] = "http://www.w3.org/2001/XMLSchema";
44 
45 static const xmlChar xs_all[] = "all";
46 static const xmlChar xs_annotation[] = "annotation";
47 static const xmlChar xs_any[] = "any";
48 static const xmlChar xs_anyAttribute[] = "anyAttribute";
49 static const xmlChar xs_attribute[] = "attribute";
50 static const xmlChar xs_AttributeType[] = "AttributeType";
51 static const xmlChar xs_base[] = "base";
52 static const xmlChar xs_choice[] = "choice";
53 static const xmlChar xs_complexType[] = "complexType";
54 static const xmlChar xs_content[] = "content";
55 static const xmlChar xs_datatype[] = "datatype";
56 static const xmlChar xs_default[] = "default";
57 static const xmlChar xs_description[] = "description";
58 static const xmlChar xs_documentation[] = "documentation";
59 static const xmlChar xs_element[] = "element";
60 static const xmlChar xs_ElementType[] = "ElementType";
61 static const xmlChar xs_eltOnly[] = "eltOnly";
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_open[] = "open";
76 static const xmlChar xs_optional[] = "optional";
77 static const xmlChar xs_order[] = "order";
78 static const xmlChar xs_processContents[] = "processContents";
79 static const xmlChar xs_ref[] = "ref";
80 static const xmlChar xs_required[] = "required";
81 static const xmlChar xs_restriction[] = "restriction";
82 static const xmlChar xs_schema[] = "schema";
83 static const xmlChar xs_seq[] = "seq";
84 static const xmlChar xs_sequence[] = "sequence";
85 static const xmlChar xs_simpleContent[] = "simpleContent";
86 static const xmlChar xs_simpleType[] = "simpleType";
87 static const xmlChar xs_strict[] = "strict";
88 static const xmlChar xs_targetNamespace[] = "targetNamespace";
89 static const xmlChar xs_textOnly[] = "textOnly";
90 static const xmlChar xs_true[] = "true";
91 static const xmlChar xs_type[] = "type";
92 static const xmlChar xs_unbounded[] = "unbounded";
93 static const xmlChar xs_use[] = "use";
94 static const xmlChar xs_value[] = "value";
95 static const xmlChar xs_values[] = "values";
96 static const xmlChar xs_xsd_string[] = "xsd:string";
97 
98 typedef enum _CONTENT_TYPE
99 {
100  CONTENT_EMPTY,
101  CONTENT_TEXTONLY,
102  CONTENT_ELTONLY,
103  CONTENT_MIXED
104 } CONTENT_TYPE;
105 
106 typedef 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 
123 static inline xmlNodePtr get_schema(xmlNodePtr node)
124 {
125  return xmlDocGetRootElement(node->doc);
126 }
127 
128 static 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 
143 static 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 
172 static 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 
188 static 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 
200 static inline xmlChar* get_attr_val(xmlAttrPtr attr)
201 {
203 }
204 
205 static 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 
217 static 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 
224 static 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 }
231 static 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 
238 static 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 
253 static 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 
269 static 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 
276 static 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 
283 static 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 
294 static 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 
309 static 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 
325 static 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 
401 static 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 
437 static 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 
462 static 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 
503 static 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 
765 static 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 
817 xmlDocPtr 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 */
XMLPUBFUN xmlAttrPtr XMLCALL xmlCopyProp(xmlNodePtr target, xmlAttrPtr cur)
#define isspace(c)
Definition: acclib.h:69
GLuint GLdouble GLdouble GLint GLint order
Definition: glext.h:11194
xmlNs * ns
Definition: tree.h:444
const xmlChar * name
Definition: tree.h:492
#define TRUE
Definition: types.h:120
Definition: tree.h:389
XMLPUBFUN xmlChar *XMLCALL xmlStrndup(const xmlChar *cur, int len)
Definition: xmlstring.c:41
XMLPUBFUN xmlChar *XMLCALL xmlGetProp(const xmlNode *node, const xmlChar *name)
#define assert(x)
Definition: debug.h:53
static HWND child
Definition: cursoricon.c:298
struct node node
#define FALSE
Definition: types.h:117
unsigned int BOOL
Definition: ntddk_ex.h:94
XMLPUBFUN xmlChar *XMLCALL xmlStrcat(xmlChar *cur, const xmlChar *add)
Definition: xmlstring.c:529
#define FIXME(fmt,...)
Definition: debug.h:111
content
Definition: atl_ax.c:993
const WCHAR * str
#define BAD_CAST
Definition: xmlstring.h:35
struct _xmlNode * parent
Definition: tree.h:495
#define TRACE(s)
Definition: solgame.cpp:4
r parent
Definition: btrfs.c:2944
XMLPUBVAR xmlFreeFunc xmlFree
Definition: globals.h:250
XMLPUBFUN xmlChar *XMLCALL xmlGetNsProp(const xmlNode *node, const xmlChar *name, const xmlChar *nameSpace)
Definition: cookie.c:201
xmlChar * content
Definition: tree.h:502
Definition: tree.h:489
__u8 attr
Definition: mkdosfs.c:359
Definition: mxnamespace.c:44
unsigned char xmlChar
Definition: xmlstring.h:28
XMLPUBFUN xmlNsPtr XMLCALL xmlNewNs(xmlNodePtr node, const xmlChar *href, const xmlChar *prefix)
XMLPUBFUN xmlChar *XMLCALL xmlNodeGetContent(const xmlNode *cur)
#define NULL
Definition: types.h:112
XMLPUBFUN xmlNodePtr XMLCALL xmlNewDocNode(xmlDocPtr doc, xmlNsPtr ns, const xmlChar *name, const xmlChar *content)
Definition: tree.h:551
Definition: tree.h:434
Definition: name.c:38
XMLPUBFUN xmlNodePtr XMLCALL xmlDocGetRootElement(const xmlDoc *doc)
XMLPUBFUN void XMLCALL xmlSetNs(xmlNodePtr node, xmlNsPtr ns)
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
const xmlChar * name
Definition: tree.h:437
XMLPUBFUN int XMLCALL xmlStrEqual(const xmlChar *str1, const xmlChar *str2)
Definition: xmlstring.c:159
const xmlChar * prefix
Definition: tree.h:393
const xmlChar * href
Definition: tree.h:392
#define WINE_DEFAULT_DEBUG_CHANNEL(t)
Definition: precomp.h:23
XMLPUBFUN xmlDocPtr XMLCALL xmlNewDoc(const xmlChar *version)
XMLPUBFUN xmlChar *XMLCALL xmlStrdup(const xmlChar *cur)
Definition: xmlstring.c:66
Definition: dlist.c:348