summaryrefslogtreecommitdiffstats
path: root/lib/jython/Lib/xml/parsers/xmlproc/namespace.py
blob: adb27ab6d91f44a0730ae84f803170422b360840 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
"""
A parser filter for namespace support. Placed externally to the parser
for efficiency reasons.

$Id: namespace.py,v 1.4 2000/09/26 14:43:10 loewis Exp $
"""

import string
import xmlapp

# --- ParserFilter

class ParserFilter(xmlapp.Application):
    "A generic parser filter class."

    def __init__(self):
        xmlapp.Application.__init__(self)
        self.app=xmlapp.Application()

    def set_application(self,app):
        "Sets the application to report events to."
        self.app=app
        
    # --- Methods inherited from xmlapp.Application
        
    def set_locator(self,locator):
        xmlapp.Application.set_locator(self,locator)
        self.app.set_locator(locator)
    
    def doc_start(self):
        self.app.doc_start()
        
    def doc_end(self):
        self.app.doc_end()
	
    def handle_comment(self,data):
        self.app.handle_comment(data)

    def handle_start_tag(self,name,attrs):
        self.app.handle_start_tag(name,attrs)

    def handle_end_tag(self,name):
        self.app.handle_end_tag(name)
    
    def handle_data(self,data,start,end):
        self.app.handle_data(data,start,end)

    def handle_ignorable_data(self,data,start,end):
        self.app.handle_ignorable_data(data,start,end)
    
    def handle_pi(self,target,data):
        self.app.handle_pi(target,data)

    def handle_doctype(self,root,pubID,sysID):
        self.app.handle_doctype(root,pubID,sysID)
    
    def set_entity_info(self,xmlver,enc,sddecl):
        self.app.set_entity_info(xmlver,enc,sddecl)

# --- NamespaceFilter
        
class NamespaceFilter(ParserFilter):
    """An xmlproc application that processes qualified names and reports them
    as 'URI local-part' names. It reports errors through the error reporting
    mechanisms of the parser."""   

    def __init__(self,parser):
        ParserFilter.__init__(self)
        self.ns_map={}       # Current prefix -> URI map
        self.ns_stack=[]     # Pushed for each element, used to maint ns_map
        self.rep_ns_attrs=0  # Report xmlns-attributes?
        self.parser=parser

    def set_report_ns_attributes(self,action):
        "Tells the filter whether to report or delete xmlns-attributes."
        self.rep_ns_attrs=action
        
    # --- Overridden event methods
        
    def handle_start_tag(self,name,attrs):
        old_ns={} # Reset ns_map to these values when we leave this element
        del_ns=[] # Delete these prefixes from ns_map when we leave element

        # attrs=attrs.copy()   Will have to do this if more filters are made

        # Find declarations, update self.ns_map and self.ns_stack
        for (a,v) in attrs.items():
            if a[:6]=="xmlns:":
                prefix=a[6:]
                if string.find(prefix,":")!=-1:
                    self.parser.report_error(1900)

                if v=="":
                    self.parser.report_error(1901)
            elif a=="xmlns":
                prefix=""
            else:
                continue

            if self.ns_map.has_key(prefix):
                old_ns[prefix]=self.ns_map[prefix]
            else:
                del_ns.append(prefix)

            if prefix=="" and v=="":
                del self.ns_map[prefix]
            else:
                self.ns_map[prefix]=v

            if not self.rep_ns_attrs:
                del attrs[a]

        self.ns_stack.append((old_ns,del_ns))
        
        # Process elem and attr names
        name=self.__process_name(name)

        parts=string.split(name)
        if len(parts)>1:
            ns=parts[0]
        else:
            ns=None
            
        for (a,v) in attrs.items():
            del attrs[a]
            aname=self.__process_name(a,ns)
            if attrs.has_key(aname):
                    self.parser.report_error(1903)                
            attrs[aname]=v
        
        # Report event
        self.app.handle_start_tag(name,attrs)

    def handle_end_tag(self,name):
        name=self.__process_name(name)

        # Clean up self.ns_map and self.ns_stack
        (old_ns,del_ns)=self.ns_stack[-1]
        del self.ns_stack[-1]

        self.ns_map.update(old_ns)
        for prefix in del_ns:
            del self.ns_map[prefix]        
            
        self.app.handle_end_tag(name)

    # --- Internal methods
        
    def __process_name(self,name,default_to=None):
        n=string.split(name,":")
        if len(n)>2:
            self.parser.report_error(1900)
            return name
        elif len(n)==2:
            if n[0]=="xmlns":
                return name 
                
            try:
                return "%s %s" % (self.ns_map[n[0]],n[1])
            except KeyError:
                self.parser.report_error(1902)
                return name
        elif default_to!=None:
            return "%s %s" % (default_to,name)
        elif self.ns_map.has_key("") and name!="xmlns":
            return "%s %s" % (self.ns_map[""],name)
        else:
            return name