root/livinglogic.python.xist/src/ll/xist/scripts/xml2xsc.py @ 2789:e5c02fe0e72c

Revision 2789:e5c02fe0e72c, 5.1 KB (checked in by Walter Doerwald <walter@…>, 12 years ago)

Merge in rel-2-15-3.

Line 
1#!/usr/bin/env python
2# -*- coding: iso-8859-1 -*-
3
4## Copyright 1999-2007 by LivingLogic AG, Bayreuth/Germany.
5## Copyright 1999-2007 by Walter Dörwald
6##
7## All Rights Reserved
8##
9## See xist/__init__.py for the license
10
11
12import sys, optparse
13
14from xml.sax import sax2exts, handler, xmlreader
15
16from ll.xist import xsc, xnd, sims
17
18
19class Handler(handler.ErrorHandler, handler.ContentHandler, handler.DTDHandler, handler.EntityResolver):
20    def __init__(self, name, url, sims):
21        self.name = name
22        self.url = url
23        self.sims = sims
24        self.xnd = None # will be set by startDocument()
25        self.stack = None # will be set by startDocument()
26        self.elements = {} # maps name to (xnd.Element, content set, attrname->xnd.Attr map)
27        self.entities = {} # maps name to xnd.Entity
28        self.procinsts = {} # maps name to xnd.ProcInst
29
30    def error(self, exception):
31        print "error: %r" % exception
32        raise exception
33
34    def fatalError(self, exception):
35        print "fatalError: %r" % exception
36        raise exception
37
38    def warning(self, exception):
39        print "warning: %r" % exception
40
41    def startDocument(self):
42        self.xnd = xnd.Namespace(self.name, url=self.url)
43        self.stack = []
44
45    def endDocument(self):
46        # Put sims info into the element definitions
47        if self.sims == "none":
48            pass
49        elif self.sims == "simple":
50            for entry in self.elements.itervalues():
51                entry[0].modeltype = bool(entry[1])
52        elif self.sims == "full":
53            for entry in self.elements.itervalues():
54                if not entry[1]:
55                    entry[0].modeltype = "sims.Empty"
56                else:
57                    elements = [el for el in entry[1] if not el.startswith("#")]
58                    if not elements:
59                        if "#text" in entry[1]:
60                            entry[0].modeltype = "sims.NoElements"
61                        else:
62                            entry[0].modeltype = "sims.NoElementsOrText"
63                    else:
64                        if "#text" in entry[1]:
65                            entry[0].modeltype = "sims.ElementsOrText"
66                        else:
67                            entry[0].modeltype = "sims.Elements"
68                        entry[0].modelargs = [self.xnd.element(el) for el in elements]
69        else:
70            raise ValueError("unknown sims mode %r" % self.sims)
71
72    def startElement(self, name, attrs):
73        if name not in self.elements:
74            element = xnd.Element(name)
75            entry = self.elements[name] = (element, set(), {})
76            self.xnd(element)
77        else:
78            entry = self.elements[name]
79        for attrname in attrs.keys():
80            if attrname != "xmlns" and not attrname.startswith("xmlns:") and attrname not in entry[2]:
81                attr = xnd.Attr(attrname, type=xsc.TextAttr)
82                entry[0](attr)
83                entry[2][attrname] = attr
84        if self.stack:
85            self.stack[-1][1].add(name)
86        self.stack.append(entry)
87
88    def endElement(self, name):
89        self.stack.pop(-1)
90
91    #def startPrefixMapping(self, prefix, uri):
92
93    #def endPrefixMapping(self, prefix):
94
95    #def startElementNS(self, name, qname, attrs):
96
97    #def endElementNS(self, name, qname):
98
99    def characters(self, content):
100        if self.stack and content:
101            if content.isspace():
102                self.stack[-1][1].add("#whitespace")
103            else:
104                self.stack[-1][1].add("#text")
105
106    def entity(self, name):
107        self.skippedEntity(name)
108
109    def ignorableWhitespace(self, whitespace):
110        if self.stack:
111            self.stack[-1][1].add("#whitespace")
112
113    def comment(self, content):
114        if self.stack:
115            self.stack[-1][1].add("#comment")
116
117    def processingInstruction(self, target, data):
118        if self.stack:
119            self.stack[-1][1].add("#procinst")
120        if target not in self.procinsts:
121            procinst = xnd.ProcInst(target)
122            self.procinsts[name] = procinst
123            self.xnd(procinst)
124
125    def skippedEntity(self, name):
126        if self.stack:
127            self.stack[-1][1].add("#entity")
128        if name not in self.entities:
129            entity = xnd.Entity(name)
130            self.entities[name] = entity
131            self.xnd(entity)
132
133
134def stream2xnd(stream, name="foo", url="http://www.example.com/foons", sims="simple", parser=None):
135    if parser is None or parser==[]:
136        from ll.xist import parsers
137        parser = parsers.SGMLOPParser()
138    elif isinstance(parser, list):
139        parser = sax2exts.make_parser(parser)
140   
141    app = Handler(name, url, sims)
142
143    parser.setErrorHandler(app)
144    parser.setContentHandler(app)
145    parser.setDTDHandler(app)
146    parser.setEntityResolver(app)
147
148    #parser.setFeature(handler.feature_namespaces, 1)
149    parser.setFeature(handler.feature_external_ges, False) # Don't process external entities, but pass them to skippedEntity
150   
151    source = xmlreader.InputSource()
152    source.setByteStream(stream)
153
154    parser.parse(source)
155   
156    return app.xnd
157
158
159def main():
160    p = optparse.OptionParser(usage="usage: %prog [options] <input.xml >output.py")
161    p.add_option("-n", "--name", dest="name", help="xmlname for the new namespace", default="foo")
162    p.add_option("-u", "--url", dest="url", help="xmlurl for the new namespace", default="http://www.example.com/foons")
163    p.add_option("-p", "--parser", dest="parser", help="parser module to use for XML parsing", action="append", default=[])
164    choices = ["none", "simple", "full"]
165    p.add_option("-s", "--sims", dest="sims", help="Create sims info? (%s)" % ", ".join(choices), metavar="MODE", default="simple")
166
167    (options, args) = p.parse_args()
168    if len(args) != 0:
169        p.error("incorrect number of arguments")
170        return 1
171    print stream2xnd(sys.stdin, name=options.name, url=options.url, sims=options.sims, parser=options.parser).aspy()
172
173
174if __name__ == "__main__":
175    sys.exit(main())
Note: See TracBrowser for help on using the browser.