-
Notifications
You must be signed in to change notification settings - Fork 5
/
README
155 lines (117 loc) · 5.27 KB
/
README
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
pyjames - A simple XML schema compiler for Python, written in C++
This is a fork of james (by Tomas Härdin), while the fork itself was initially
created by Ludvig Widman
Purpose/goals
=============
The purpose of this program is to transform a subset of XSL into Python code for marshalling and unmarshalling documents conforming to one or more schemas.
The generated code should not be needlessly complicated (no getters or setters).
The number of dependencies should be kept to a minimum.
Compilation
===========
pyjames makes use of CMake.
This allows project files and Makefiles to be generated for a variety of system without having to maintain said files.
The program is known to compile in *NIX like system (GNU/Linux, Mac OS X) via Makefiles and Windows via Visual Studio 2008.
Dependencies
------------
pyjames depends on Xerces-C++ 2.8.x or 3.1.x.
Building
--------
The program is built like a typical CMake project.
A normal build and install will look something like this (output omitted):
~/pyjames$ mkdir build
~/pyjames$ cd build
~/pyjames/build$ cmake ..
~/pyjames/build$ make
~/pyjames/build$ sudo make install
A short guide to usage
======================
Running the program without arguments produces the following usage information:
USAGE: pyjames [-v] [--dry-run] output-dir list-of-XSL-documents
-v Verbose mode
--dry-run Perform generation but don't write anything to disk - instead does exit(1) if any file changes
Generates Python classes for marshalling and unmarshalling XML to Python objects according to the given schemas.
Files are output in the specified output directory and are named type.py
The --dry-run switch can be used to test whether running pyjames would change any files on disk.
This includes modifying existing files or creating new ones, but not no longer generating files for types that no longer exist.
Generation example
------------------
For a small project with a single schema, generating Python code for handling said schema looks like this:
~/foo$ mkdir generated
~/foo$ pyjames generated schema.xsd
To make generated into a proper package you must then create the empty file generated/__init__.py and copy pyjames/py/JamesXMLObject.py in there.
Note that outputing the files in the current directory is not recommended since that makes cleaning up difficult.
Using the generated code
========================
Here is a small example schema and code that makes use of the generated classes:
example.xsd
-----------
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="http://example.com/" elementFormDefault="qualified" xmlns="http://example.com/">
<xs:element name="PersonDocument" type="tns:PersonType"/>
<xs:element name="PersonListDocument">
<xs:complexType>
<xs:sequence>
<xs:element name="person" type="tns:PersonType" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:complexType name="PersonType">
<xs:attribute name="name" type="xs:string" use="required"/>
<xs:attribute name="address" type="xs:string" use="required"/>
<xs:attribute name="birthYear" type="xs:int" use="required"/>
</xs:complexType>
</xs:schema>
person.xml
----------
<?xml version="1.0" encoding="UTF-8"?>
<PersonDocument name="Foo Oldperson" address="Bar Street 123" birthYear="1900"/>
example.py
-----------
import sys
from xml.dom.minidom import *
from generated.PersonDocument import *
from generated.PersonListDocument import *
def main():
#unmarshal personIn from stdin
personIn = PersonDocument.fromxml(sys.stdin)
#create a list containing personIn and some other person
list = PersonListDocument()
list.person.append(personIn)
list.person.append(PersonType("Some Otherguy", "Somewhere 999", 1985))
#finally, marshal the list to stdout
print list.toxml()
if __name__ == "__main__":
main()
Generating a package for handling the schema
--------------------------------------------
The following creates a self-contained package for handling the schema.
This is a part of pyjames that will probably be improved in the near future.
~/example$ mkdir generated
~/example$ pyjames generated example.xsd
A generated/PersonDocument.py
A generated/PersonListDocument.py
A generated/PersonListDocumentType.py
A generated/PersonType.py
~/example$ touch generated/__init__.py
~/example$ cp ~/pyjames/py/JamesXMLObject.py generated
Running
-------
$ python example.py < person.xml | xmllint --format -
<?xml version="1.0" encoding="UTF-8"?>
<PersonListDocument xmlns="http://example.com/">
<person address="Bar Street 123" birthYear="1900" name="Foo Oldperson"/>
<person address="Somewhere 999" birthYear="1985" name="Some Otherguy"/>
</PersonListDocument>
Limitations
===========
Some schemas, like that of XHTML or XSL itself, will never be supported by pyjames.
The intent is to only support schemas that can be compiled into classes that consist of plain C++ objects.
Any schema that allows arbitrary order of elements in any type is explicitly not supported.
TODO
====
* Support more XSL features (within reason)
* Make switching between Xerces-C++ 2.8.x and 3.1.x easier
* Create output directory if it doesn't exist
* Create proper self-contained packages
- touch __init__.py
- output JamesXMLObject.py