Changeset 2989:b46e34472b05 in livinglogic.python.xist for src/ll/xist/scripts/dtd2xsc.py

Show
Ignore:
Timestamp:
09/25/07 18:10:22 (12 years ago)
Author:
Walter Doerwald <walter@…>
Branch:
newparser
Message:

Move xnd.fromdtd() to dtd2xsc script. Change script to work with stdin/stdout.

Files:
1 modified

Legend:

Unmodified
Added
Removed
  • src/ll/xist/scripts/dtd2xsc.py

    r2903 r2989  
    2828 
    2929 
    30 def dtd2xsc(dtdurl, outurl, verbose, xmlns, shareattrs, model, defaults): 
    31     if verbose: 
    32         print "Parsing DTD %s ..." % dtdurl 
    33     d = dtdparser.load_dtd(dtdurl.url) 
     30def dtd2xnd(dtd, xmlns=None): 
     31    """ 
     32    Convert &dtd; information from the &url; <arg>dtdurl</arg> to an &xist; &dom; 
     33    using the <pyref module="ll.xist.xnd"><module>xnd</module></pyref> functionality. 
     34    """ 
    3435 
    35     if verbose: 
    36         print "Converting ..." 
    37     data = xnd.fromdtd(d, xmlns) 
     36    dtd = dtdparser.load_dtd_string(dtd) 
     37 
     38    ns = xnd.Module() 
     39 
     40    foundxmlns = set() # collects all the values of fixed xmlns attributes 
     41 
     42    # Add element info 
     43    elements = dtd.get_elements() 
     44    elements.sort() 
     45    for elemname in elements: 
     46        dtd_e = dtd.get_elem(elemname) 
     47        e = xnd.Element(elemname, xmlns=xmlns) 
     48 
     49        # Add attribute info for this element 
     50        attrs = dtd_e.get_attr_list() 
     51        if len(attrs): 
     52            attrs.sort() 
     53            for attrname in attrs: 
     54                dtd_a = dtd_e.get_attr(attrname) 
     55                if attrname=="xmlns": 
     56                    if dtd_a.decl=="#FIXED": 
     57                        foundxmlns.add(dtd_a.default) 
     58                    continue # skip a namespace declaration 
     59                elif u":" in attrname: 
     60                    continue # skip global attributes 
     61                values = [] 
     62                if dtd_a.type == "ID": 
     63                    type = "xsc.IDAttr" 
     64                else: 
     65                    type = "xsc.TextAttr" 
     66                    if isinstance(dtd_a.type, list): 
     67                        if len(dtd_a.type)>1: 
     68                            values = dtd_a.type 
     69                        else: 
     70                            type = "xsc.BoolAttr" 
     71                default = dtd_a.default 
     72                if dtd_a.decl=="#REQUIRED": 
     73                    required = True 
     74                else: 
     75                    required = None 
     76                a = xnd.Attr(name=attrname, type=type, default=default, required=required) 
     77                for v in values: 
     78                    a.values.append(v) 
     79                e.attrs.append(a) 
     80        ns.content.append(e) 
     81 
     82    # Iterate through the elements a second time and add model information 
     83    for elemname in elements: 
     84        e = dtd.get_elem(elemname) 
     85        model = e.get_content_model() 
     86        if model is None: 
     87            modeltype = "sims.Any" 
     88            modelargs = None 
     89        elif model == ("", [], ""): 
     90            modeltype = "sims.Empty" 
     91            modelargs = None 
     92        else: 
     93            def extractcont(model): 
     94                if len(model) == 3: 
     95                    result = {} 
     96                    for cont in model[1]: 
     97                        result.update(extractcont(cont)) 
     98                    return result 
     99                else: 
     100                    return {model[0]: None} 
     101            model = extractcont(model) 
     102            modeltype = "sims.Elements" 
     103            modelargs = [] 
     104            for cont in model: 
     105                if cont == "#PCDATA": 
     106                    modeltype = "sims.ElementsOrText" 
     107                elif cont == "EMPTY": 
     108                    modeltype = "sims.Empty" 
     109                else: 
     110                    modelargs.append(ns.element(cont)) 
     111            if not modelargs: 
     112                if modeltype == "sims.ElementsOrText": 
     113                    modeltype = "sims.NoElements" 
     114                else: 
     115                    modeltype = "sims.NoElementsOrText" 
     116        e = ns.element(elemname) 
     117        e.modeltype = modeltype 
     118        e.modelargs = modelargs 
     119 
     120    # Add entities 
     121    ents = dtd.get_general_entities() 
     122    ents.sort() 
     123    for entname in ents: 
     124        if entname not in ("quot", "apos", "gt", "lt", "amp"): 
     125            ent = parsers.parsestring(dtd.resolve_ge(entname).value) 
     126            ns.content.append(xnd.CharRef(entname, codepoint=ord(unicode(ent[0])[0]))) 
     127 
     128    # if the DTD has exactly one value for all fixed "xmlns" attributes and the user didn't specify xmlns, use this one 
     129    if xmlns is None and len(foundxmlns)==1: 
     130        ns.xmlns = foundxmlns.pop() 
     131    return ns 
     132 
     133 
     134def stream2xnd(stream, xmlns, shareattrs): 
     135    xnd = dtd2xnd(stream.read(), xmlns) 
    38136 
    39137    if shareattrs=="dupes": 
    40         data.shareattrs(False) 
     138        xnd.shareattrs(False) 
    41139    elif shareattrs=="all": 
    42         data.shareattrs(True) 
    43  
    44     if verbose: 
    45         print "Writing to %s ..." % outurl 
    46     file = outurl.openwrite() 
    47     file.write(data.aspy(model=model, defaults=defaults)) 
    48     file.close() 
     140        xnd.shareattrs(True) 
     141    return xnd 
    49142 
    50143 
    51144def main(): 
    52     p = optparse.OptionParser(usage="usage: %prog [options] inputurl.dtd") 
    53     p.add_option("-o", "--output", dest="output", metavar="FILE", help="write output to FILE") 
    54     p.add_option("-v", "--verbose", action="store_true", dest="verbose") 
     145    p = optparse.OptionParser(usage="usage: %prog [options] <input.dtd >output_xmlns.py") 
    55146    p.add_option("-x", "--xmlns", dest="xmlns", help="the namespace name for this module") 
    56147    p.add_option("-s", "--shareattrs", dest="shareattrs", help="Should identical attributes be shared among elements?", choices=("none", "dupes", "all"), default="dupes") 
     
    59150 
    60151    (options, args) = p.parse_args() 
    61     if len(args) != 1: 
     152    if len(args) != 0: 
    62153        p.error("incorrect number of arguments") 
    63154        return 1 
    64     input = url.URL(args[0]) 
    65     if options.output is None: 
    66         output = url.File(input.withext("py").file) 
    67     else: 
    68         output = url.URL(options.output) 
    69     dtd2xsc(input, output, options.verbose, options.xmlns, options.shareattrs, options.model, options.defaults) 
     155    print stream2xnd(sys.stdin, options.xmlns, options.shareattrs).aspy(model=options.model, defaults=options.defaults) 
    70156 
    71157