root/livinglogic.python.xist/src/ll/xist/scripts/xml2xsc.py @ 4113:90434cb52f2b

Revision 4113:90434cb52f2b, 3.7 KB (checked in by Walter Doerwald <walter@…>, 9 years ago)

Use argparse instead of optparse.

Line 
1#!/usr/bin/env python
2# -*- coding: utf-8 -*-
3
4## Copyright 1999-2010 by LivingLogic AG, Bayreuth/Germany
5## Copyright 1999-2010 by Walter Dörwald
6##
7## All Rights Reserved
8##
9## See ll/__init__.py for the license
10
11
12import sys, argparse
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(model, 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    # Iterate through the tree a collect: which elements are encountered and how they are nested
46    for path in iterpath(node):
47        node = path[-1]
48        if "Element" in type(node).__name__:
49            (name, xmlns) = getelementname(node)
50            try:
51                entry = elements[(name, xmlns)]
52            except KeyError:
53                xndnode = xnd.Element(name, xmlns=xmlns)
54                entry = elements[(name, xmlns)] = (xndnode, set(), {})
55                ns(xndnode)
56            else:
57                xndnode = entry[0]
58            for attrname in node.keys():
59                if not attrname.startswith("{") and attrname not in entry[2]:
60                    attr = xnd.Attr(attrname, type=xsc.TextAttr)
61                    entry[0](attr)
62                    entry[2][attrname] = attr
63        elif "ProcessingInstruction" in type(node).__name__:
64            name = node.target
65            try:
66                xndnode = procinsts[name]
67            except KeyError:
68                procinst = xnd.ProcInst(name)
69                procinsts[name] = procinst
70                xndnode = procinst
71            ns(xndnode)
72        elif "Comment" in type(node).__name__:
73            xndnode = "#comment"
74        elif isinstance(node, basestring):
75            if node.isspace():
76                xndnode = "#whitespace"
77            else:
78                xndnode = "#text"
79        if len(path) >= 2:
80            parent = path[-2]
81            if "Element" in type(parent).__name__:
82                parententry = elements[getelementname(parent)]
83                parententry[1].add(xndnode)
84
85    # Put sims info into the element definitions
86    if model == "none":
87        pass
88    elif model == "simple":
89        for entry in elements.itervalues():
90            entry[0].modeltype = bool(entry[1])
91    elif model == "full":
92        for entry in elements.itervalues():
93            if not entry[1]:
94                entry[0].modeltype = "sims.Empty"
95            else:
96                elements = [el for el in entry[1] if isinstance(el, xnd.Element)]
97                if not elements:
98                    if "#text" in entry[1]:
99                        entry[0].modeltype = "sims.NoElements"
100                    else:
101                        entry[0].modeltype = "sims.NoElementsOrText"
102                else:
103                    if "#text" in entry[1]:
104                        entry[0].modeltype = "sims.ElementsOrText"
105                    else:
106                        entry[0].modeltype = "sims.Elements"
107                    entry[0].modelargs = elements
108    else:
109        raise ValueError("unknown sims mode {0!r}".format(model))
110    return ns
111
112
113def stream2xnd(stream, model="simple", parser="etree"):
114    if parser == "etree":
115        from xml.etree import cElementTree
116        node = cElementTree.parse(stream).getroot()
117    elif parser == "lxml":
118        from lxml import etree
119        node = etree.parse(stream).getroot()
120    else:
121        raise ValueError("unknown parser {0!r}".format(parser))
122
123    return etree2xnd(model, node)
124
125
126def main(args=None):
127    p = argparse.ArgumentParser(description="Convert XML (on stdin) to XIST namespace (on stdout)")
128    p.add_argument("-p", "--parser", dest="parser", help="parser module to use for XML parsing (etree or lxml)", choices=("etree", "lxml"), default="etree")
129    p.add_argument("-m", "--model", dest="model", help="Create sims info?", choices=("none", "simple", "full"), default="simple")
130
131    args = p.parse_args(args)
132    print stream2xnd(sys.stdin, model=args.model, parser=args.parser).aspy()
133
134
135if __name__ == "__main__":
136    sys.exit(main())
Note: See TracBrowser for help on using the browser.