Why does my Python XML parser break after the first file?
Question: I am working on a Python (3) XML parser that should extract the text content
of specific nodes from every xml file within a folder. Then, the script should
write the collected data into a tab-separated text file. So far, all the
functions seem to be working. The script returns all the information that I
want from the first file, but it always breaks, I believe, when it starts to
parse the second file.

When it breaks, it returns "TypeError: 'str' object is not callable." I've
checked the second file and found that the functions work just as well on that
as the first file when I remove the first file from the folder. I'm very new
to Python/XML. Any advice, help, or useful links would be greatly appreciated.
Thanks!

    
    
    import xml.etree.ElementTree as ET
    import re
    import glob
    import csv
    import sys
    
    content_file = open('WWP Project/WWP_texts.txt','wt')
    quotes_file = open('WWP Project/WWP_quotes.txt', 'wt')
    list_of_files = glob.glob("../../../Documents/WWPtextbase/distribution/*.xml")
    
    ns = {'wwp':'http://www.wwp.northeastern.edu/ns/textbase'}
    
    def content(tree):
        lines = ''.join(ET.tostring(tree.getroot(),encoding='unicode',method='text')).replace('\n',' ').replace('\t',' ').strip()
        clean_lines = re.sub(' +',' ', lines)
        return clean_lines.lower()
    
    def quotes(tree):
        quotes_list = []
        for node in tree.findall('.//wwp:quote', namespaces=ns):
            quote = ET.tostring(node,encoding='unicode',method='text')
            clean_quote = re.sub(' +',' ', quote)
            quotes_list.append(clean_quote)
        return ' '.join(str(v) for v in quotes_list).replace('\t','').replace('\n','').lower()
    
    def pid(tree):
        for node in tree.findall('.//wwp:sourceDesc//wwp:author/wwp:persName[1]', namespaces=ns):
            pid = node.attrib.get('ref')
        return pid.replace('personography.xml#','') # will need to replace 'p:'
    
    
    def trid(tree): # this function will eventually need to call OT (.//wwp:publicationStmt//wwp:idno)
        for node in tree.findall('.//wwp:sourceDesc',namespaces=ns):
            trid = node.attrib.get('n')
        return trid
    
    content_file.write('pid' + '\t' + 'trid' + '\t' +'text' + '\n')
    quotes_file.write('pid' + '\t' + 'trid' + '\t' + 'quotes' + '\n')
    
    for file_name in list_of_files:
        file = open(file_name, 'rt')
        tree = ET.parse(file)
        file.close()
        pid = pid(tree)
        trid = trid(tree)
        content = content(tree)
        quotes = quotes(tree)
        content_file.write(pid + '\t' + trid + '\t' + content + '\n')
        quotes_file.write(pid + '\t' + trid + '\t' + quotes + '\n')
    
    content_file.close()
    quotes_file.close()
    


Answer: You are overwriting your function calls with the values they returned.
changing the function names should fix it.

    
    
    import xml.etree.ElementTree as ET
    import re
    import glob
    import csv
    import sys
    
    content_file = open('WWP Project/WWP_texts.txt','wt')
    quotes_file = open('WWP Project/WWP_quotes.txt', 'wt')
    list_of_files = glob.glob("../../../Documents/WWPtextbase/distribution/*.xml")
    
    ns = {'wwp':'http://www.wwp.northeastern.edu/ns/textbase'}
    
    def get_content(tree):
        lines = ''.join(ET.tostring(tree.getroot(),encoding='unicode',method='text')).replace('\n',' ').replace('\t',' ').strip()
        clean_lines = re.sub(' +',' ', lines)
        return clean_lines.lower()
    
    def get_quotes(tree):
        quotes_list = []
        for node in tree.findall('.//wwp:quote', namespaces=ns):
            quote = ET.tostring(node,encoding='unicode',method='text')
            clean_quote = re.sub(' +',' ', quote)
            quotes_list.append(clean_quote)
        return ' '.join(str(v) for v in quotes_list).replace('\t','').replace('\n','').lower()
    
    def get_pid(tree):
        for node in tree.findall('.//wwp:sourceDesc//wwp:author/wwp:persName[1]', namespaces=ns):
            pid = node.attrib.get('ref')
        return pid.replace('personography.xml#','') # will need to replace 'p:'
    
    
    def get_trid(tree): # this function will eventually need to call OT (.//wwp:publicationStmt//wwp:idno)
        for node in tree.findall('.//wwp:sourceDesc',namespaces=ns):
            trid = node.attrib.get('n')
        return trid
    
    content_file.write('pid' + '\t' + 'trid' + '\t' +'text' + '\n')
    quotes_file.write('pid' + '\t' + 'trid' + '\t' + 'quotes' + '\n')
    
    for file_name in list_of_files:
        file = open(file_name, 'rt')
        tree = ET.parse(file)
        file.close()
        pid = get_pid(tree)
        trid = get_trid(tree)
        content = get_content(tree)
        quotes = get_quotes(tree)
        content_file.write(pid + '\t' + trid + '\t' + content + '\n')
        quotes_file.write(pid + '\t' + trid + '\t' + quotes + '\n')
    
    content_file.close()
    quotes_file.close()
    

