Project

General

Profile

« Previous | Next » 

Revision 886

xpath.py: get(): Added full support for returning multiple matches

View differences:

lib/xpath.py
150 150
    if last_only == None: last_only = create
151 151
    if type(xpath) == str: xpath = parse(xpath)
152 152
    
153
    if xpath == []: return parent
154
    if create and not is_positive(xpath): return None
153
    if xpath == []: return [parent]
154
    if create and not is_positive(xpath): return []
155 155
    doc = parent.ownerDocument
156 156
    root = doc.documentElement
157 157
    elem = xpath[0]
......
172 172
        is_match = elem.value == None or xml_dom.value(child) == elem.value
173 173
        for attr in elem.keys:
174 174
            if not is_match: break
175
            is_match = (get(child, attr, False, last_only) != None)\
176
            == is_positive(attr)
175
            is_match = ((get(child, attr, False, last_only) != [])
176
                == is_positive(attr))
177 177
        if is_match:
178 178
            nodes.append(child)
179 179
            if limit != None and len(nodes) >= limit: break
180
    try: node = nodes[0]
181
    except IndexError: node = None
182 180
    
183 181
    # Create node
184
    if node == None:
185
        if not create: return None
182
    if nodes == []:
183
        if not create: return []
186 184
        if elem.is_attr:
187 185
            parent.setAttribute(elem.name, '')
188 186
            node = parent.getAttributeNode(elem.name)
189 187
        else: node = parent.appendChild(doc.createElement(elem.name))
190 188
        if elem.value != None: xml_dom.set_value(node, elem.value)
191
    if create:
192
        for attr in elem.keys + elem.attrs: get(node, attr, create, last_only)
189
        nodes.append(node)
193 190
    
194 191
    xpath = xpath[1:] # rest of XPath
195 192
    
196
    # Follow pointer
197
    if elem.is_ptr:
198
        xpath = copy.deepcopy(xpath)
199
        id_path = backward_id(xpath[instance_level])
200
        if id_path != None: # backward (child-to-parent) pointer with ID key
201
            id_path[0].name = expand_abbr(id_path[0].name, node.tagName)
202
            set_value(id_path, xml_dom.get_id(node)) # modify id key of xpath
203
        else: # forward (parent-to-child) pointer
204
            id_ = xml_dom.value(node)
205
            obj_xpath = obj(xpath) # target object
206
            if id_ == None or get(root, obj_xpath, False, True) == None:
207
                # no target or target keys don't match
208
                if not create: return None
209
                
210
                # Use last target object's ID + 1
211
                obj_xpath[-1].keys = [] # just get by tag name
212
                last = get(root, obj_xpath, False, True)
213
                if last != None: id_ = str(int(xml_dom.get_id(last)) + 1)
214
                else: id_ = '0'
215
                
216
                # Will append if target keys didn't match.
217
                # Use lookahead assertion to avoid this.
218
                xml_dom.set_value(node, id_)
219
            else: last_only = False
220
            set_id(xpath, id_)
221
    else: root = node
222
    next = get(root, xpath, create, last_only)
193
    next = []
194
    for node in nodes:
195
        # Create attrs
196
        if create:
197
            for attr in elem.keys + elem.attrs:
198
                get(node, attr, create, last_only)
199
        
200
        # Follow pointer
201
        if elem.is_ptr:
202
            xpath = copy.deepcopy(xpath)
203
            id_path = backward_id(xpath[instance_level])
204
            if id_path != None: # backward (child-to-parent) pointer with ID key
205
                id_path[0].name = expand_abbr(id_path[0].name, node.tagName)
206
                set_value(id_path, xml_dom.get_id(node)) # modify xpath's id key
207
            else: # forward (parent-to-child) pointer
208
                id_ = xml_dom.value(node)
209
                obj_xpath = obj(xpath) # target object
210
                if id_ == None or get(root, obj_xpath, False, True) == []:
211
                    # no target or target keys don't match
212
                    if not create: continue
213
                    
214
                    # Use last target object's ID + 1
215
                    obj_xpath[-1].keys = [] # just get by tag name
216
                    last = get(root, obj_xpath, False, True)
217
                    if last != []: id_ = str(int(xml_dom.get_id(last[0])) + 1)
218
                    else: id_ = '0'
219
                    
220
                    # Will append if target keys didn't match.
221
                    # Use lookahead assertion to avoid this.
222
                    xml_dom.set_value(node, id_)
223
                else: last_only = False
224
                set_id(xpath, id_)
225
        else: root = node
226
        next += get(root, xpath, create, last_only)
227
        
228
        for branch in elem.other_branches:
229
            branch = copy.deepcopy(branch)
230
            set_value(branch, value(xpath))
231
            next += get(node, branch, create, last_only)
223 232
    
224
    for branch in elem.other_branches:
225
        branch = copy.deepcopy(branch)
226
        set_value(branch, value(xpath))
227
        get(node, branch, create, last_only)
228
    
229 233
    return next
230 234

  
231 235
def put_obj(root, xpath, id_, has_types, value=None):
bin/map
154 154
            def get_value(in_, row):
155 155
                pkey, = row
156 156
                in_ = in_.cloneNode(True) # don't modify orig value!
157
                xml_dom.set_id(xpath.get(in_, in_root), pkey)
157
                xml_dom.set_id(xpath.get(in_, in_root)[0], pkey)
158 158
                value = sql.value_or_none(db_xml.get(in_db, in_, in_pkeys))
159 159
                if value != None: return str(value)
160 160
                else: return None
......
163 163
            in_db.close()
164 164
        elif in_is_xml:
165 165
            def get_value(in_, row):
166
                node = xpath.get(row, in_)
167
                if node != None: return xml_dom.value(node)
166
                nodes = xpath.get(row, in_)
167
                if nodes != []: return xml_dom.value(nodes[0])
168 168
                else: return None
169
            row0 = xpath.get(doc0.documentElement, in_root)
170
            if row0 == None: raise SystemExit('Map error: Root "'+in_root
169
            rows = xpath.get(doc0.documentElement, in_root)
170
            if rows == []: raise SystemExit('Map error: Root "'+in_root
171 171
                +'" not found in input')
172
            map_rows(get_value, xml_dom.NodeElemIter(row0.parentNode))
172
            map_rows(get_value, xml_dom.NodeElemIter(rows[0].parentNode))
173 173
        else: # input is CSV
174 174
            map_ = dict(mappings)
175 175
            reader = csv.reader(sys.stdin)

Also available in: Unified diff