Changeset 2989:b46e34472b05 in livinglogic.python.xist

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:
3 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 
  • src/ll/xist/xnd.py

    r2978 r2989  
    425425        self.defaults = defaults 
    426426        self.model = model 
    427  
    428  
    429 def fromdtd(dtd, xmlns=None): 
    430     """ 
    431     Convert &dtd; information (in the format that is returned by <app>xmlproc</app>s 
    432     <function>dtdparser.load_dtd</function> function) to an &xist; &dom; using the 
    433     <pyref module="ll.xist.xnd"><module>xnd</module></pyref> namespace. 
    434     """ 
    435  
    436     ns = Module(xmlns) 
    437  
    438     foundxmlns = set() # collects all the values of fixed xmlns attributes 
    439  
    440     # Add element info 
    441     elements = dtd.get_elements() 
    442     elements.sort() 
    443     for elemname in elements: 
    444         dtd_e = dtd.get_elem(elemname) 
    445         e = Element(name=elemname) 
    446  
    447         # Add attribute info for this element 
    448         attrs = dtd_e.get_attr_list() 
    449         if len(attrs): 
    450             attrs.sort() 
    451             for attrname in attrs: 
    452                 dtd_a = dtd_e.get_attr(attrname) 
    453                 if attrname=="xmlns": 
    454                     if dtd_a.decl=="#FIXED": 
    455                         foundxmlns.add(dtd_a.default) 
    456                     continue # skip a namespace declaration 
    457                 elif u":" in attrname: 
    458                     continue # skip global attributes 
    459                 values = [] 
    460                 if dtd_a.type == "ID": 
    461                     type = "xsc.IDAttr" 
    462                 else: 
    463                     type = "xsc.TextAttr" 
    464                     if isinstance(dtd_a.type, list): 
    465                         if len(dtd_a.type)>1: 
    466                             values = dtd_a.type 
    467                         else: 
    468                             type = "xsc.BoolAttr" 
    469                 default = dtd_a.default 
    470                 if dtd_a.decl=="#REQUIRED": 
    471                     required = True 
    472                 else: 
    473                     required = None 
    474                 a = Attr(name=attrname, type=type, default=default, required=required) 
    475                 for v in values: 
    476                     a.values.append(v) 
    477                 e.attrs.append(a) 
    478         ns.content.append(e) 
    479  
    480     # Iterate through the elements a second time and add model information 
    481     for elemname in elements: 
    482         e = dtd.get_elem(elemname) 
    483         model = e.get_content_model() 
    484         if model is None: 
    485             modeltype = "sims.Any" 
    486             modelargs = None 
    487         elif model == ("", [], ""): 
    488             modeltype = "sims.Empty" 
    489             modelargs = None 
    490         else: 
    491             def extractcont(model): 
    492                 if len(model) == 3: 
    493                     result = {} 
    494                     for cont in model[1]: 
    495                         result.update(extractcont(cont)) 
    496                     return result 
    497                 else: 
    498                     return {model[0]: None} 
    499             model = extractcont(model) 
    500             modeltype = "sims.Elements" 
    501             modelargs = [] 
    502             for cont in model: 
    503                 if cont == "#PCDATA": 
    504                     modeltype = "sims.ElementsOrText" 
    505                 elif cont == "EMPTY": 
    506                     modeltype = "sims.Empty" 
    507                 else: 
    508                     modelargs.append(ns.element(cont)) 
    509             if not modelargs: 
    510                 if modeltype == "sims.ElementsOrText": 
    511                     modeltype = "sims.NoElements" 
    512                 else: 
    513                     modeltype = "sims.NoElementsOrText" 
    514         e = ns.element(elemname) 
    515         e.modeltype = modeltype 
    516         e.modelargs = modelargs 
    517  
    518     # Add entities 
    519     ents = dtd.get_general_entities() 
    520     ents.sort() 
    521     for entname in ents: 
    522         if entname not in ("quot", "apos", "gt", "lt", "amp"): 
    523             ent = parsers.parsestring(dtd.resolve_ge(entname).value) 
    524             ns.content.append(CharRef(entname, codepoint=ord(unicode(ent[0])[0]))) 
    525  
    526     # if the DTD has exactly one value for all fixed "xmlns" attributes and the user didn't specify xmlns, use this one 
    527     if xmlns is None and len(foundxmlns)==1: 
    528         ns.xmlns = foundxmlns.pop() 
    529     return ns 
  • test/test_dtd2xsc.py

    r2903 r2989  
    1313 
    1414from ll.xist import xsc, xnd, sims 
     15from ll.xist.scripts import dtd2xsc 
    1516 
    1617 
    1718def dtd2mod(s, xmlns=None, shareattrs=None): 
    18     from xml.parsers.xmlproc import dtdparser 
    19  
    20     dtd = dtdparser.load_dtd_string(s) 
    21     data = xnd.fromdtd(dtd, xmlns) 
     19    xnd = dtd2xsc.dtd2xnd(s, xmlns) 
    2220 
    2321    if shareattrs is not None: 
    24         data.shareattrs(shareattrs) 
     22        xnd.shareattrs(shareattrs) 
    2523 
    2624    mod = types.ModuleType("test") 
    2725    mod.__file__ = "test.py" 
    2826    encoding = "iso-8859-1" 
    29     code = data.aspy(encoding=encoding).encode(encoding) 
     27    code = xnd.aspy(encoding=encoding).encode(encoding) 
    3028    code = compile(code, "test.py", "exec") 
    3129    exec code in mod.__dict__