forked from Juniper/contrail-generateDS
-
Notifications
You must be signed in to change notification settings - Fork 1
/
generateDS.txt
2565 lines (1894 loc) · 90 KB
/
generateDS.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
======================================================
generateDS -- Generate Data Structures from XML Schema
======================================================
:author: Dave Kuhlman
:address: dkuhlman@rexx.com
http://www.rexx.com/~dkuhlman
.. Do not modify the following version comments.
They are used by updateversion.py.
.. version
:revision: 2.7c
.. version
:date: |date|
.. |date| date:: %B %d, %Y
:copyright: Copyright (c) 2004 Dave Kuhlman. This documentation
and the software it describes is covered by The MIT License:
http://www.opensource.org/licenses/mit-license.php.
:abstract: ``generateDS.py`` generates Python data structures (for
example, class definitions) from an XML Schema document. These
data structures represent the elements in an XML document
described by the XML Schema. It also generates parsers that
load an XML document into those data structures. In addition,
a separate file containing subclasses (stubs) is optionally
generated. The user can add methods to the subclasses in order
to process the contents of an XML document.
.. sectnum:: :depth: 4
.. contents::
:depth: 4
Introduction
============
``generateDS.py`` generates Python data structures (for example,
class definitions) from an XML Schema document. These data
structures represent the elements in an XML document described by
the XML Schema. It also generates parsers that load an XML
document into those data structures. In addition, a separate file
containing subclasses (stubs) is optionally generated. The user
can add methods to the subclasses in order to process the contents
of an XML document.
The generated Python code contains:
- A class definition for each element defined in the XML Schema
document.
- A main and driver function that can be used to test the
generated code.
- A parser that will read an XML document which satisfies the XML
Schema from which the parser was generated. The parser creates
and populates a tree structure of instances of the generated
Python classes.
- Methods in each class to export the instance back out to XML
(method ``export``) and to export the instance to a literal
representing the Python data structure (method
``exportLiteral``).
The generated classes contain the following:
- A constructor method (__init__), with member variable
initializers.
- Methods with names 'getX' and 'setX' for each member variable
'X' or, if the member variable is defined with
maxOccurs="unbounded", methods with names 'getX', 'setX',
'addX', and 'insertX'.
- A "build" method that can be used to populate an instance of the
class from a node in a minidom tree.
- An "export" method that will write the instance (and any nested
sub-instances) to a file object as XML text.
- An "exportLiteral" method that will write the instance (and any
nested sub-instances) to a file object as Python literals (text).
The generated subclass file contains one (sub-)class definition
for each data representation class. If the subclass file is used,
then the parser creates instances of the subclasses (instead of
creating instances of the superclasses). This enables the user to
extend the subclasses with "tree walk" methods, for example, that
process the contents of the XML file. The user can also generate
and extend multiple subclass files which use a single, common
superclass file, thus implementing a number of different processes
on the same XML document type.
This document explains (1) how to use ``generateDS.py``; (2) how
to use the Python code and data structures that it generates; and
(3) how to modify the generated code for special purposes.
There is also support for packaging the code you generate with
``generateDS.py``. See `Packaging your code`_.
Where To find it
================
Download
--------
You can find the source distribution here:
- `Python Package Index --
http://pypi.python.org/pypi/generateDS/
<http://pypi.python.org/pypi/generateDS/>`_
- `Source Forge --
http://sourceforge.net/projects/generateds/
<http://sourceforge.net/projects/generateds/>`_
Support and more information
------------------------------
There is a mailing list at SourceForge:
`generateds-users --
https://lists.sourceforge.net/lists/listinfo/generateds-users
<https://lists.sourceforge.net/lists/listinfo/generateds-users>`_.
There is a tutorial in the distribution:
``tutorial/tutorial.html`` and at
`generateDS -- Introduction and Tutorial --
http://www.rexx.com/~dkuhlman/generateds_tutorial.html
<http://www.rexx.com/~dkuhlman/generateds_tutorial.html>`_.
How to build and install it
===========================
Newer versions of Python have XML support in the Python standard
library. For older versions of Python, install PyXML. You can find
it at: http://pyxml.sourceforge.net/
De-compress the ``generateDS`` distribution file. Use something
like the following::
tar xzvf generateDS-x.xx.tar.gz
Then, the regular Distutils commands should work::
$ cd generateDS-x.xx
$ python setup.py build
$ python setup.py install # probably as root
Packaging your code
=====================
There is some support for packaging the code you generate with
``generateDS.py``. This support helps you to produce a directory
structure with places to put sample code, sample XML instance
documents, and utility code for use with your generated module. It
also assists you in using `Sphinx <http://sphinx.pocoo.org/>`_ to
generate documentation for your module. The Sphinx support is
especially useful when the schema used to generate code contains
"annotation" elements that document complexType definitions.
Instructions on how to use it are here:
`How to package a generateDS.py generated library --
librarytemplate_howto.html
<librarytemplate_howto.html>`_
And the package building support itself is here:
`LibraryTemplate --
http://www.rexx.com/~dkuhlman/librarytemplate0-1.0a.zip
<http://www.rexx.com/~dkuhlman/librarytemplate0-1.0a.zip>`_.
It is also included in the generateDS distribution package.
The command line interface -- How to use it
============================================================
Running ``generateDS.py``
-------------------------
Run ``generateDS.py`` with a single argument, the XML Schema file
that defines the data structures. For example, the following will
generate Python source code for data structures described in
people.xsd and will write it to the file people.py. In addition,
it will write subclass stubs to the file peoplesubs.py::
python generateDS.py -o people.py -s peoplesubs.py people.xsd
Here is the usage message displayed by ``generateDS.py``::
Synopsis:
Generate Python classes from XML Schema definition.
Input is read from in_xsd_file or, if "-" (dash) arg, from stdin.
Output is written to files named in "-o" and "-s" options.
Usage:
python generateDS.py [ options ] <xsd_file>
python generateDS.py [ options ] -
Options:
-h, --help Display this help information.
-o <outfilename> Output file name for data representation classes
-s <subclassfilename> Output file name for subclasses
-p <prefix> Prefix string to be pre-pended to the class names
-f Force creation of output files. Do not ask.
-a <namespaceabbrev> Namespace abbreviation, e.g. "xsd:".
Default = 'xs:'.
-b <behaviorfilename> Input file name for behaviors added to subclasses
-m Generate properties for member variables
--subclass-suffix="XXX" Append XXX to the generated subclass names.
Default="Sub".
--root-element="XXX" Assume XXX is root element of instance docs.
Default is first element defined in schema.
--super="XXX" Super module name in subclass module. Default="???"
--validator-bodies=path Path to a directory containing files that provide
bodies (implementations) of validator methods.
--use-old-getter-setter Name getters and setters getVar() and setVar(),
instead of get_var() and set_var().
--user-methods= <module>,
-u <module> Optional module containing user methods. See
section "User Methods" in the documentation.
--no-dates Do not include the current date in the generated
files. This is useful if you want to minimize
the amount of (no-operation) changes to the
generated python code.
--no-versions Do not include the current version in the generated
files. This is useful if you want to minimize
the amount of (no-operation) changes to the
generated python code.
--no-process-includes Do not process included XML Schema files. By
default, generateDS.py will insert content
from files referenced by <include ... />
elements into the XML Schema to be processed.
--silence Normally, the code generated with generateDS
echoes the information being parsed. To prevent
the echo from occurring, use the --silence switch.
--namespacedef='xmlns:abc="http://www.abc.com"'
Namespace definition to be passed in as the
value for the namespacedef_ parameter of
the export() method by the generated
parse() and parseString() functions.
Default=''.
--external-encoding=<encoding>
Encode output written by the generated export
methods using this encoding. Default, if omitted,
is the value returned by sys.getdefaultencoding().
Example: --external-encoding='utf-8'.
--member-specs=list|dict
Generate member (type) specifications in each
class: a dictionary of instances of class
MemberSpec_ containing member name, type,
and array or not. Allowed values are
"list" or "dict". Default: None.
--session=mysession.session
Load and use options from session file. You can
create session file in generateds_gui.py.
--version Print version and exit.
The following command line flags are recognized by ``generateDS.py``:
o <filename>
Write the data representation classes to file filename.
s <filename>
Write the subclass stubs to file filename.
p <prefix>
Prepend prefix to the name of each generated data structure
(class).
f
Force generation of output files even if they already exist.
Do not ask before over-writing existing files.
a <namespaceabbrev>
Namespace abbreviation, for example "xsd:". The default is
'xs:'. If the ``<schema> element`` in your XML Schema,
specifies something other than "xmlns:xs=", then you need to
use this option. So, suppose you have the following at the
beginning of your XSchema file::
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
Then you can the following command line option::
-a "xsd:"
But, note that ``generateDS.py`` also tries to pick-up the
namespace prefix used in the XMLSchema file automatically. If
the <schema> element has an attribute "xmlns:xxx" whose value
is "http://www.w3.org/2001/XMLSchema", then ``generateDS.py``
will use "xxx:" as the alias for the XMLSchema namespace in
the XMLSchema document.
b <behaviorfilename>
Input file name for behaviors to be added to subclasses.
Specifies is the name of an XML document containing
descriptions of methods to be added to subclasses generated
with the -s flag. The -b flag requires the -s flag. See the
section on `XMLBehaviors`_ below.
m
Generate property members and new style classes. Causes
generated classes to inherit from class object. Generates
a call to the built-in property function for each pair of
getters and setters. This is experimental.
subclass-suffix=<suffix>
Append suffix to the name of classes generated in the subclass
file. The default, if omitted, is "Sub". For example, the
following will append "_Action" to each generated subclass
name::
generateDS.py --subclass-suffix="_Action" -s actions.py mydef.xsd
And the following will append nothing, making the superclass
and subclass names the same::
generateDS.py --subclass-suffix="" -s actions.py mydef.xsd
root-element=<element_name>
Make element_name the assumed root of instance documents. The
default is the name of the element whose definition is first
in the XML Schema document. This flag effects the parsing
functions (for example, parse(), parseString()).
super=<module_name>
Make module_name the name of the superclass module imported
by the subclass module. If this flag is omitted, the
following is generated near the top of the subclass file::
import ??? as supermod
and you will need to hand edit this so the correct superclass
module is imported.
validator-bodies=<path>
Obtain the bodies (implementations) for validator methods for
members defined as ``simpleType`` from files in directory
specified by ``<path>``. The name of the file in that
directory should be the same as the ``simpleType`` name with
an optional ".py" extension. If a file is not provided for a
given type, an empty body (``pass``) is generated. In these
files, lines with "##" in the first two columns are ignored
and are not inserted.
use-old-getter-setter
``generateDS.py`` now generates getter and setter methods (for
variable "abc", for example) with the names get_abc() and
set_abc(), which I believe is a more Pythonic style, instead
of getAbc() and setAbc(), which was the old behavior. Use
this flag to generate getters and setters in the old style
(getAbc() and setAbc()).
u, user-methods=<module>
If specified, ``generateDS.py`` will add methods to generated
classes as specified in the indicated module. For more
information, see section `User Methods`_.
no-dates
Do not include the current date in the generated files. This is
useful if you want to minimize the amount of (no-operation)
changes to the generated python code.
no-versions
Do not include the current version in the generated files. This is
useful if you want to minimize the amount of (no-operation)
changes to the generated python code.
no-process-includes
Do not process included XML Schema files. By default,
generateDS.py will insert content from files referenced by
``<include ... />`` elements into the XML Schema to be processed.
See section `Include file processing`_.
silence
Normally, the code generated with generateDS echoes the
information being parsed. To prevent the echo from occurring,
use the --silence switch. This switch causes generateDS.py,
when it generates boiler-plate parsing functions, (parse(),
parseString(), parseLiteral()), to generate code that does
*not* print out output (export output to stdout).
namespacedef="<http://...>"
Namespace definition to be passed in as the value for the
``namespacedef_`` parameter of the export() method by the generated
parse() and parseString() functions. If this parameter is
specified, then the export function will insert a namespace
prefix definition attribute in the top-most (outer-most)
element. (Actually, you can insert any attribute.) The default
is an empty string.
external-encoding=<encoding>
If an XML instance document contains character data or
attribute values that are not in the ASCII character set, then
that data will not be written out correctly or will throw an
exception. This flag enables the user to specify a character
encoding into which character data will be encoded before it is
written out by the export functions. The generated export
methods encode data using this encoding. The default value, if
this flag is omitted, is the value returned by
sys.getdefaultencoding(). You can find a list of standard
encodings here: http://docs.python.org/library/codecs.html#id3.
Example use: --external-encoding='utf-8'.
member-specs
Generate member (type) specifications in each class: a
dictionary of instances of class ``MemberSpec_`` containing
member name, type, and array or not. See `User Methods`_
section for more information about ``MemberSpec_``. Allowed
values are "list" or "dict". Default: do *not* generate member
specifications (unless --user-methods specified).
session=mysession.session
Load and use options from session file. You can create a
session file in generateds_gui.py, the graphical front-end for
generateDS.py. Additional options on the command line can be
used to override options in the session file. A session file
is an XML document, so you can modify it with a text editor.
version
Print out the current version of generateDS.py and immediately
exit.
Name conflicts
--------------
Conflicts with Python keywords
..............................
In some cases the element and attribute names in an XML document
will conflict with Python keywords. There are two solutions to fixing
and avoiding name conflicts:
- In an attempt to avoid these clashes, ``generateDS.py`` contains a
table that maps names that might clash to acceptable names. This
table is a Python dictionary named ``NameTable``. The user can
modify existing entries in this table within ``generateDS.py``
itself and add additional name-replacement pairs to this table, for
example, if new conflicts occur.
- Or, you can fix additional conflicts by following these steps:
1. Create a module named ``generateds_config.py``.
2. Define a dictionary in that module named ``NameTable``.
3. Place additional name mappings in that dictionary. Here is a
sample::
NameTable = {
'range': 'rangeType',
}
3. And, place that module where ``generateDS.py`` can import it, or
place the directory containing that module on your
``PYTHONPATH`` environment variable.
``generateDS.py`` will attempt to import that module
(``generateds_config.py``) and will add the name mappings in it to
the default set of mappings in ``NameTable`` in ``generateDS.py``
itself.
Conflicts between child elements and attributes
...............................................
In some cases the name of a child element and the name of an
attribute will be the same. (I believe, but am not sure, that
this is allowed by XML Schema.) Since generateDS.py treats both
child elements and attributes as members of the generated class,
this is a name conflict. Therefore, where such conflicts exist,
generateDS.py modifies the name of the attribute by adding "_attr"
to its name.
The graphical user interface -- How to use it
==============================================================
Here are a few notes on how to use the GUI front-end.
- ``generateds_gui.py`` is installed when you do the standard
installation::
$ python setup.py install
- Run it by typing the following at the command line::
$ generateds_gui.py
- For help with command line options, run::
$ generateds_gui.py --help
- For a description of the values and flags that you can set, see
section `Running generateDS.py`_. There are also tool tips on
the various widgets in the graphical user interface.
- Generate the python bindings modules by using the
``Tools/Generate`` menu item or the ``Generate`` button at the
bottom of the window.
- Capture the command line generated by using the
``Tools/Capture command line`` menu item. You might consider copying and
pasting that command line into a shell script or batch file for
repeated reuse.
- You can also save and later reload your values and
flags in a session file. See the ``Save session``,
``Save session as``, and ``Load session`` items under the ``File`` menu.
By default, a session file has the extension ".session".
- You can load a session on start-up with the "-s" or "--session"
comand line options. For example::
$ generateds_gui.py --session=mybindingsjob.session
Or, use the "session" option in a configuration file.
- If the command to be run when generating bindings is not
standard, you can specify that command with the "--exec-path"
command line option or with the "exec-path" option configuration
file. The default is "generateDS.py".
- Command line options can also be specified in a configuration
file. ``generateds_gui.py`` checks for that configuration file in
the following locations in this order:
1. ``~/.generateds_gui.ini``
2. ``./generateds_gui.ini``
Here is a sample configuration file::
[general]
exec-path: /usr/bin/python ~/bin/generateDS.py
impl-path: generateds_gui.glade
session: a1.session
Options on the command line override options in configuration
files.
Common problems
===============
Namespace prefix mis-match
--------------------------
``generateDS.py`` is not very intelligent about detecting what
prefix is used in the schema file for the XML Schema namespace.
When this problem occurs, you may see the following when running
``generateDS.py``::
AttributeError: 'NoneType' object has no attribute 'annotate'
``generateDS.py`` assumes that the XML Schema namespace prefix in
your schema is "xs:".
So, if the XML Schema namespace prefix in your schema is not "xs:",
you will need to use the "-a" command line option when you run
``generateDS.py``. Here is an example::
generateDS.py -a "xsd:" --super=mylib -o mylib.py -s myapp.py someschema.xsd
Supported features of XML Schema
================================
The following constructs, among others, in XML Schema are
supported:
- Attributes of types xs:string, xs:integer, xs:float, and
xs:boolean.
- Repeated sub-elements specified with maxOccurs="unbounded".
- Sub-elements of simple types xs:string, xs:integer, and xs:float.
- Sub-elements of complex types defined separately in the XML
Schema document.
See file people.xsd for examples of the definition of data types
and structures. Also see the section on `The XML Schema Input
to generateDS`_.
Attributes + no nested children
-------------------------------
Element definitions that contain attributes but *no* nested child
elements provide access to their data content through getter and
setter methods ``getValueOf_`` and ``setValueOf_`` and member
variable ``valueOf_``.
Mixed content
-------------
Elements that are defined to contain both text and nested child
elements have "mixed content". ``generateDS.py`` provides access
to mixed content, but the generated data structures (classes) are
fundamentally different from that generated for other elements.
See section `Mixed content`_ for more details.
Note that elements defined with attributes but with *no* nested
sub-elements do not need to be declared as "mixed". For these
elements, character data is captured in a member variable
``valueOf_``, and can be accessed with member methods
``getValueOf_`` and ``setValueOf_``.
anyAttribute
------------
``generateDS.py`` supports ``anyAttribute``. For example, if an
element is defined as follows::
<xs:element name="Tool">
<xs:complexType>
<xs:attribute name="PartNumber" type="xs:string" />
<xs:anyAttribute processContents="skip" />
</xs:complexType>
</xs:element>
Then ``generateDS.py`` will generate a class with a member
variable ``anyAttributes_`` containing a dictionary. Any
attributes found in the instance XML document that are not
explicitly defined for this element will be stored in this
dictionary. ``generateDS.py`` also generates getters and setters
as well as code for parsing and export. ``generateDS.py`` ignores
``processContents``. See section `anyAttribute`_ for more details.
Element extensions
------------------
``generateDS.py`` now generates subclasses for extensions, that is
when an element definition contains something like this::
<xs:extension base="sometag">
**Limitation** -- There is an important limitation, however:
member names duplicated (overridden ?) in an extension generate
erroneous code. Sigh. I guess I needed something more to do.
Several of the generated methods have been refactored so that
subclasses can reuse the code in their superclasses. Take a look
at the generated code to learn how to use it.
The Python compiler/interpreter requires that it has seen a
superclass before it sees the subclass that uses it. Because of
this, ``generateDS.py`` delays generating a subclass until after
its superclass has been generated. Therefore, the order in which
classes are generated may be different from what you expect.
Attribute groups
----------------
``generateDS.py`` now handles definition and use of attribute
groups. For example: the use of something like the following::
<xs:attributeGroup name="favorites">
<xs:attribute name="fruit" />
<xs:attribute name="vegetable" />
</xs:attributeGroup>
And, a reference or use like the following::
<xs:element name="person">
<xs:complexType mixed="0">
<xs:attributeGroup ref="favorites" />
o
o
o
Results in generation of class ``person`` that contains members
``fruit`` and ``vegetable``.
Substitution groups
-------------------
``generateDS.py`` now handles a limited range of substitution
groups, but, there is an important **limitation**, in particular
``generateDS.py`` handles substitution groups that involve complex
types, but does not handle those that involve (substitute for)
simple types (for example, xs:string, xs:integer, etc). This is
because the code generated for members defined as simple types
does not provide the needed information to handle substitution
groups.
Primitive types
---------------
``generateDS.py`` supports some, but not all, simple types defined
in "XML Schema Part 0: Primer Second Edition" (
http://www.w3.org/TR/xmlschema-0/. See section "Simple Types" and
appendix B). Validation is performed for some simple types. When
performed, validation is done while the XML document is being read
and instances are created.
Here is a list of supported simple types:
- ``xs:string`` -- No validation.
- ``xs:token`` -- No validation. White space between tokens is
coerced to a single blank between tokens.
- ``xs:integer``, ``xs:short``, ``xs:long``. ``xs:int`` -- All
treated the same. Checked for valid integer.
- ``xs:float``, ``xs:double``, ``xs:decimal`` -- All treated the
same. Checked for valid float.
- ``xs:positiveInteger`` -- Checked for valid range (> 0).
- ``xs:nonPositiveInteger`` -- Checked for valid range (<= 0).
- ``xs:negativeInteger`` -- Checked for valid range (< 0).
- ``xs:nonNegativeInteger`` -- Checked for valid range (>= 0).
- ``xs:date``, ``xs:dateTime`` -- All treated the same. No
validation.
- ``xs:boolean`` -- Checked for one of ``0``, ``false``, ``1``,
``true``.
simpleType
----------
``generateDS.py`` generates minimal support for members defined as
``simpleType``. However, the code generated by ``generateDS.py``
does **not** enforce restrictions. For notes on how to enforce
restrictions, see section `simpleType and validators`_.
A ``simpleType`` can be a restriction on a primitive type or on a
defined element type. So, for example, the following will
generate valid code::
<xs:element name="percent">
<xs:simpleType>
<xs:restriction base="xs:integer">
<xs:minInclusive value="1"/>
<xs:maxInclusive value="100"/>
</xs:restriction>
</xs:simpleType>
</xs:element>
And, the following will also generate valid code::
<xs:simpleType name="emptyString">
<xs:restriction base="xs:string">
<xs:whiteSpace value="collapse"/>
</xs:restriction>
</xs:simpleType>
<xs:element name="merge">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="emptyString">
<xs:attribute name="fromTag" type="xs:string"/>
<xs:attribute name="toTag" type="xs:string"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
List values, optional values, maxOccurs, etc.
---------------------------------------------
For elements defined with ``maxOccurs="unbounded"``,
``generateDS.py`` generates code that processes a list of elements.
For elements defined with ``minOccurs="0"`` and ``maxOccurs="1"``,
``generateDS.py`` generates code that exports an element only if
that element has a (non-None) value.
simpleType and validators
-------------------------
Here are a few notes that should help you use validator methods to
enforce restrictions.
- Default behavior -- The generated code, by default, treats the
value of a member whose type is a ``simpleType`` as if it were
declared as type ``xs:string``.
- Validator method stubs -- For a member variable name declared as a
``simpleType`` named ``X``, a validator method ``validate_X`` is
generated. Example -- from::
<xs:simpleType name="tAnyName">
<xs:restriction base="xs:string"/>
</xs:simpleType>
The class generated by ``generateDS.py`` will contain the
following method definition::
def validate_tAnyName(self, value):
# Validate type tAnyName, a restriction on xs:string.
pass
- Calls to validator methods -- For a member variable declared as a
``simpleType`` ``X``, a call to ``validate X`` is added to the
build method. Example -- from::
<xs:element name="person">
<xs:complexType mixed="0">
<xs:sequence>
<xs:element name="test2" type="tAnyName"/>
</xs:sequence>
</xs:complexType>
</xs:element>
``generateDS.py`` produces the following call::
self.validate_tAnyName(self.test2) # validate type tAnyName
- Code bodies for validator methods can be added either (1)
manually or (2) automatically from an external source. See
command line option "--validator-bodies" and see below.
You can add code to the validator method stub to enforce the
restriction for the base type and further restrictions imposed on
that base type. This can be done in the following ways:
1. Add code manually after generation. I recommend that you use
the "-s" command line option and override the validator method
in the resulting subclass file.
2. Or, supply code bodies (implementations) in an external
source and ask ``generateDS.py`` to insert those code bodies
into generated validator methods. Here are notes on how to do
this:
- Use the "--validator-bodies=path" command line option to specify
a directory.
- In that directory, provide one file for each ``simpleType``.
The name of the file should be the same as the name of
the ``simpleType`` with an optional extension ".py".
``generateDS.py`` looks for a file named ``type_name.py``,
first, and if not found, looks for a file named
``type_name``.
- If the "--validator-bodies" is not on the command line
or neither ``type_name.py`` nor ``type_name`` is found, an
empty body (a ``pass`` statement) is generated.
- Lines from the file are inserted as is, except that lines
containing "##" in the first two columns are omitted. Note
that you will need to provide the correct indentation for a
method in a class, specifically 8 spaces.
The support for ``simpleType`` in ``generateDS.py`` has the
following limitations (among others, I'm sure):
- It only works for ``simpleType`` defined with and referenced
through a name. It does not work for "in-line" definitions.
So, for example, the following works::
<xs:element name="person">
<xs:complexType>
<xs:sequence>
<xs:element name="test3" type="tAnyName"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:simpleType name="tAnyName">
<xs:restriction base="xs:string"/>
</xs:simpleType>
But, the following does not work::
<xs:element name="person">
<xs:complexType>
<xs:sequence>
<xs:element name="test3">
<xs:simpleType name="tAnyName">
<xs:restriction base="xs:string"/>
</xs:simpleType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
- Attributes defined as a simple type are not supported.
Include file processing
-----------------------
By default, generateDS.py will insert content from files referenced by
``include`` elements into the XML Schema to be processed. This
behavior can be turned off by using the "--no-process-includes"
command line option.
``include`` elements are processed and the referenced content is
inserted in the XML Schema by importing and using
``process_includes.py``, which is included in the ``generateDS.py``
distribution.
``process_includes.py`` will use either ``lxml`` or ``ElementTree``,
but its preference is ``lxml`` because ``lxml`` attempts to preserve
namespace prefixes. So if your XML Schemas have ``<include ... />``
elements in them, you might want to consider installing ``lxml``, even
though ``ElementTree`` is in the Python standard library for Python
versions >= 2.5.
The include file processing is capable of retrieve included files
via FTP and HTTP internet protocols as well as from the local file
system.
Abstract types
--------------
``generateDS.py`` has support for abstract types. For more on
this, see:
`XML Schema Part 0: Primer Second Edition: Abstract Elements and Types --
http://www.w3.org/TR/xmlschema-0/#abstract
<http://www.w3.org/TR/xmlschema-0/#abstract>`_.
The XML schema input to generateDS
==================================
**Note:** Quite a bit of work has been done on ``generateDS.py``
since this section was written. So, it accepts and processes
more of features in XML Schema than earlier. The best advice is to
give it a try on your schema. If it works, great. If it does not,
post a message to the list:
`generateds-users --
https://lists.sourceforge.net/lists/listinfo/generateds-users
<https://lists.sourceforge.net/lists/listinfo/generateds-users>`_.
``generateDS.py`` actually accepts a subset of XML Schema.
The sample XML Schema file should give you a picture of how to
describe an XML file and the Python classes that you will
generate. And here are some notes that should help:
- Specify the tag in the XML file and the name of the generated
Python class in the name attribute on the xs:element. For
example, to generate a Python class named "person", which will
be populated from an XML element/tag "person", use the following
XML Schema snippet::
<xs:element name="person" ...
- To specify a data member for a generated Python class that will
be propogated from an attribute in an element in an XML file,
use the XML Schema xs:attribute. For attributes, generateDS
recognizes the following types: "xs:string", "xs:integer", and
"xs:float". For example, the following adds member data items
"hobby" and "category" with types "xs:string" and "xs:integer"::
<xs:element name="person">
<complexType>
<xs:attribute name="hobby" type="xs:string" />
<xs:attribute name="category" type="xs:integer" />
</complexType>
</xs:element>
- To specify a data member for a generated Python class whose
value is a string, integer, or float and which will be populated
from a nested (simple) element, specify a nested XML Schema
element whose type is "xs:string", "xs:integer", or "xs:float".
Here is an example which defines a Python class "person" with a
data member "description" which is a string and which is
populated from a (simple) nested element::
<xs:element name="person">
<complexType>
<sequence>
<xs:element name="description" type="xs:string" />
<sequence>
</complexType>
</xs:element>