root/livinglogic.python.xist/src/ll/xist/scripts/dtd2xsc.py @ 3128:db1435a72dfc

Revision 3128:db1435a72dfc, 4.9 KB (checked in by Walter Doerwald <walter@…>, 12 years ago)

Shorted names of many doc elements to something more familiar.

* function to func;
* method to meth;
* module to mod;
* property to prop;
* title to h;
* par to p;
* olist to ol;
* ulist to ul;
* dlist to dl;
* item to li or dd (depending on whether it's inside an ol, ul or dl);
* term to dt;
* link to a.

Line 
1#! /usr/bin/env python
2# -*- coding: utf-8 -*-
3
4## Copyright 1999-2008 by LivingLogic AG, Bayreuth/Germany
5## Copyright 1999-2008 by Walter Dörwald
6##
7## All Rights Reserved
8##
9## See xist/__init__.py for the license
10
11
12"""
13<p>Module that helps to create &xist; namespace modules from &dtd;s.
14Needs <app>xmlproc</app> from the <app>PyXML</app> package.
15For usage information type:</p>
16<prog>
17dtd2xsc --help
18</prog>
19"""
20
21
22import sys, os.path, optparse
23
24from xml.parsers.xmlproc import dtdparser
25
26from ll import url
27from ll.xist import xsc, parsers, xnd
28
29
30__docformat__ = "xist"
31
32
33def getxmlns(dtd):
34    """
35    Extract the value of all fixed <lit>xmlns</lit> attributes
36    """
37    found = set()
38    for elemname in dtd.get_elements():
39        element = dtd.get_elem(elemname)
40        for attrname in element.get_attr_list():
41            attr = element.get_attr(attrname)
42            if attrname=="xmlns" or u":" in attrname:
43                if attr.decl=="#FIXED":
44                    found.add(attr.default)
45                    continue # skip a namespace declaration
46    return found
47
48
49def dtd2xnd(dtd, xmlns=None):
50    """
51    Convert &dtd; information from the &url; <arg>dtdurl</arg> to an &xist; &dom;
52    using the <pyref module="ll.xist.xnd"><mod>xnd</mod></pyref> functionality.
53    """
54
55    dtd = dtdparser.load_dtd_string(dtd)
56
57    ns = xnd.Module()
58
59    if xmlns is None:
60        # try to guess the namespace name from the dtd
61        xmlns = getxmlns(dtd)
62        if len(xmlns) == 1:
63            xmlns = iter(xmlns).next()
64        else:
65            xmlns = None
66
67    # Add element info
68    elements = dtd.get_elements()
69    elements.sort()
70    for elemname in elements:
71        dtd_e = dtd.get_elem(elemname)
72        e = xnd.Element(elemname, xmlns=xmlns)
73
74        # Add attribute info for this element
75        attrs = dtd_e.get_attr_list()
76        if len(attrs):
77            attrs.sort()
78            for attrname in attrs:
79                dtd_a = dtd_e.get_attr(attrname)
80                if attrname=="xmlns" or u":" in attrname:
81                    continue # skip namespace declarations and global attributes
82                values = []
83                if dtd_a.type == "ID":
84                    type = "xsc.IDAttr"
85                else:
86                    type = "xsc.TextAttr"
87                    if isinstance(dtd_a.type, list):
88                        if len(dtd_a.type)>1:
89                            values = dtd_a.type
90                        else:
91                            type = "xsc.BoolAttr"
92                default = dtd_a.default
93                if dtd_a.decl=="#REQUIRED":
94                    required = True
95                else:
96                    required = None
97                a = xnd.Attr(name=attrname, type=type, default=default, required=required)
98                for v in values:
99                    a.values.append(v)
100                e.attrs.append(a)
101        ns.content.append(e)
102
103    # Iterate through the elements a second time and add model information
104    for elemname in elements:
105        e = dtd.get_elem(elemname)
106        model = e.get_content_model()
107        if model is None:
108            modeltype = "sims.Any"
109            modelargs = None
110        elif model == ("", [], ""):
111            modeltype = "sims.Empty"
112            modelargs = None
113        else:
114            def extractcont(model):
115                if len(model) == 3:
116                    result = {}
117                    for cont in model[1]:
118                        result.update(extractcont(cont))
119                    return result
120                else:
121                    return {model[0]: None}
122            model = extractcont(model)
123            modeltype = "sims.Elements"
124            modelargs = []
125            for cont in model:
126                if cont == "#PCDATA":
127                    modeltype = "sims.ElementsOrText"
128                elif cont == "EMPTY":
129                    modeltype = "sims.Empty"
130                else:
131                    modelargs.append(ns.element(cont))
132            if not modelargs:
133                if modeltype == "sims.ElementsOrText":
134                    modeltype = "sims.NoElements"
135                else:
136                    modeltype = "sims.NoElementsOrText"
137        e = ns.element(elemname)
138        e.modeltype = modeltype
139        e.modelargs = modelargs
140
141    # Add entities
142    ents = dtd.get_general_entities()
143    ents.sort()
144    for entname in ents:
145        if entname not in ("quot", "apos", "gt", "lt", "amp"):
146            ent = parsers.parsestring(dtd.resolve_ge(entname).value)
147            ns.content.append(xnd.CharRef(entname, codepoint=ord(unicode(ent[0])[0])))
148
149    # if the DTD has exactly one value for all fixed "xmlns" attributes and the user didn't specify xmlns, use this one
150    if xmlns is None and len(foundxmlns)==1:
151        ns.xmlns = foundxmlns.pop()
152    return ns
153
154
155def stream2xnd(stream, xmlns, shareattrs):
156    xnd = dtd2xnd(stream.read(), xmlns)
157
158    if shareattrs=="dupes":
159        xnd.shareattrs(False)
160    elif shareattrs=="all":
161        xnd.shareattrs(True)
162    return xnd
163
164
165def main(args=None):
166    p = optparse.OptionParser(usage="usage: %prog [options] <input.dtd >output_xmlns.py")
167    p.add_option("-x", "--xmlns", dest="xmlns", help="the namespace name for this module")
168    p.add_option("-s", "--shareattrs", dest="shareattrs", help="Should identical attributes be shared among elements?", choices=("none", "dupes", "all"), default="dupes")
169    p.add_option("-m", "--model", dest="model", default="once", help="Add sims information to the namespace", choices=("no", "all", "once"))
170    p.add_option("-d", "--defaults", action="store_true", dest="defaults", help="Output default values for attributes")
171
172    (options, args) = p.parse_args(args)
173    if len(args) != 0:
174        p.error("incorrect number of arguments")
175        return 1
176    print stream2xnd(sys.stdin, options.xmlns, options.shareattrs).aspy(model=options.model, defaults=options.defaults)
177
178
179if __name__ == "__main__":
180    sys.exit(main())
Note: See TracBrowser for help on using the browser.