root/livinglogic.python.xist/src/ll/xist/scripts/xml2xsc.py @ 3691:4af6e4e1cf02

Revision 3691:4af6e4e1cf02, 3.7 KB (checked in by Walter Doerwald <walter@…>, 11 years ago)

Bump copyright year.

Line 
1#!/usr/bin/env python
2# -*- coding: utf-8 -*-
3
4## Copyright 1999-2009 by LivingLogic AG, Bayreuth/Germany
5## Copyright 1999-2009 by Walter Dörwald
6##
7## All Rights Reserved
8##
9## See ll/__init__.py for the license
10
11
12import sys, optparse
13
14from ll.xist import xsc, xnd, sims
15
16
17__docformat__ = "reStructuredText"
18
19
20def iterpath(node):
21    yield [node]
22    if hasattr(node, "text") and node.text:
23        yield [node, node.text]
24    if hasattr(node, "getchildren"):
25        for child in node:
26            for path in iterpath(child):
27                yield [node] + path
28    if hasattr(node, "tail") and node.tail:
29        yield [node, node.tail]
30
31
32def getelementname(node):
33    xmlns = None
34    name = node.tag
35    if name.startswith("{"):
36        (xmlns, sep, name) = name[1:].partition("}")
37    return (name, xmlns)
38
39
40def etree2xnd(sims, node):
41    ns = xnd.Module()
42    elements = {} # maps (name, xmlns) to (xnd.Element, content set, attrname->xnd.Attr map)
43    procinsts = {} # maps name to xnd.ProcInst
44
45    for path in iterpath(node):
46        node = path[-1]
47        if "Element" in type(node).__name__:
48            (name, xmlns) = getelementname(node)
49            try:
50                entry = elements[(name, xmlns)]
51            except KeyError:
52                xndnode = xnd.Element(name, xmlns=xmlns)
53                entry = elements[(name, xmlns)] = (xndnode, set(), {})
54                ns(xndnode)
55            else:
56                xndnode = entry[0]
57            for attrname in node.keys():
58                if not attrname.startswith("{") and attrname not in entry[2]:
59                    attr = xnd.Attr(attrname, type=xsc.TextAttr)
60                    entry[0](attr)
61                    entry[2][attrname] = attr
62        elif "ProcessingInstruction" in type(node).__name__:
63            name = node.target
64            try:
65                xndnode = procinsts[name]
66            except KeyError:
67                procinst = xnd.ProcInst(name)
68                procinsts[name] = procinst
69                xndnode = procinst
70            ns(xndnode)
71        elif "Comment" in type(node).__name__:
72            xndnode = "#comment"
73        elif isinstance(node, basestring):
74            if node.isspace():
75                xndnode = "#whitespace"
76            else:
77                xndnode = "#text"
78        if len(path) >= 2:
79            parent = path[-2]
80            if "Element" in type(parent).__name__:
81                parententry = elements[getelementname(parent)]
82                parententry[1].add(xndnode)
83
84    # Put sims info into the element definitions
85    if sims == "none":
86        pass
87    elif sims == "simple":
88        for entry in elements.itervalues():
89            entry[0].modeltype = bool(entry[1])
90    elif sims == "full":
91        for entry in elements.itervalues():
92            if not entry[1]:
93                entry[0].modeltype = "sims.Empty"
94            else:
95                elements = [el for el in entry[1] if isinstance(el, xnd.Element)]
96                if not elements:
97                    if "#text" in entry[1]:
98                        entry[0].modeltype = "sims.NoElements"
99                    else:
100                        entry[0].modeltype = "sims.NoElementsOrText"
101                else:
102                    if "#text" in entry[1]:
103                        entry[0].modeltype = "sims.ElementsOrText"
104                    else:
105                        entry[0].modeltype = "sims.Elements"
106                    entry[0].modelargs = elements
107    else:
108        raise ValueError("unknown sims mode %r" % sims)
109    return ns
110
111
112def stream2xnd(stream, sims="simple", parser="etree"):
113    if parser == "etree":
114        from xml.etree import cElementTree
115        node = cElementTree.parse(stream).getroot()
116    elif parser == "lxml":
117        from lxml import etree
118        node = etree.parse(stream).getroot()
119    else:
120        raise ValueError("unknown parser %r" % parser)
121   
122    return etree2xnd(sims, node)
123
124
125def main(args=None):
126    p = optparse.OptionParser(usage="usage: %prog [options] <input.xml >output.py")
127    p.add_option("-p", "--parser", dest="parser", help="parser module to use for XML parsing (etree or lxml)", choices=("etree", "lxml"), default="etree")
128    choices = ["none", "simple", "full"]
129    p.add_option("-s", "--sims", dest="sims", help="Create sims info? (%s)" % ", ".join(choices), metavar="MODE", default="simple")
130
131    (options, args) = p.parse_args(args)
132    if len(args) != 0:
133        p.error("incorrect number of arguments")
134        return 1
135    print stream2xnd(sys.stdin, sims=options.sims, parser=options.parser).aspy()
136
137
138if __name__ == "__main__":
139    sys.exit(main())
Note: See TracBrowser for help on using the browser.