root/livinglogic.python.xist/src/ll/xist/scripts/xml2xsc.py @ 2980:9c8572b2440a

Revision 2980:9c8572b2440a, 3.7 KB (checked in by Walter Doerwald <walter@…>, 12 years ago)

Rename variable.

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