0

I am trying to write a Python script that reads an XML file, replaces some variables with placeholders, translates the text using Google Translate API, restores the variables and writes the output to another XML file.

However, when I run my script, I get this error:

Traceback (most recent call last): File "C:\Users\lazar\AppData\Local\Programs\Python\Python311\Lib\xml\etree\ElementTree.py", line 757, in _get_writer write = file_or_filename.write ^^^^^^^^^^^^^^^^^^^^^^ AttributeError: 'str' object has no attribute 'write'

During handling of the above exception, another exception occurred:

Traceback (most recent call last): File "\translate.py", line 48, in _serialize_xml return ET._serialize_xml(write, elem, qnames, namespaces, short_empty_elements=short_empty_elements) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "\translate.py", line 48, in _serialize_xml return ET._serialize_xml(write, elem, qnames, namespaces, short_empty_elements=short_empty_elements) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "./translate.py", line 48, in _serialize_xml return ET._serialize_xml(write, elem, qnames, namespaces, short_empty_elements=short_empty_elements) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ [Previous line repeated 997 more times] RecursionError: maximum recursion depth exceeded

I have searched online and found out that this error occurs because the Python interpreter has exceeded the recursion limit allowed.

Here is my code:

import xml.etree.ElementTree as ET
import re
from google.cloud import translate_v2 as translate
from google.oauth2 import service_account

credentials_dict = {
#keys goes here
}


credentials = service_account.Credentials.from_service_account_info(credentials_dict)

client = translate.Client(credentials=credentials)

tree = ET.parse("input.xml")
root = tree.getroot()

def replace_variables(text):
    variables = re.findall(r"\{.*?\}", text)
    for i, variable in enumerate(variables):
        text = text.replace(variable, "~" * (i + 1))
    return text, variables

def restore_variables(text, variables):
    placeholders = re.findall(r"~+", text)
    for i, placeholder in enumerate(placeholders):
        if len(variables) > i:
            text = text.replace(placeholder, variables[i])
    return text

def CDATA(text=None):
    element = ET.Element('![CDATA[')
    element.text = text
    return element

def _serialize_xml(write, elem, qnames, namespaces, *, short_empty_elements=True):
    if elem.tag == '![CDATA[':
        write("\n<%s%s]]>\n" % (elem.tag, elem.text))
        return
    return ET._serialize_xml(write, elem, qnames, namespaces, short_empty_elements=short_empty_elements)

ET._serialize_xml = _serialize_xml

new_elements = []
for i, element in enumerate(root.iter()):
    if element.text is not None:
        text = element.text.strip()
        modified_text, variables = replace_variables(text)
        translation = client.translate(modified_text, target_language="es")
        translated_text = translation["translatedText"]
        restored_text = restore_variables(translated_text, variables)
        print(text + " -> " + restored_text)

        cdata_element = CDATA(restored_text)
        new_element = element.makeelement(element.tag, element.attrib)
        new_element.append(cdata_element)
        new_elements.append(new_element)

for i, new_element in enumerate(new_elements):
    if i < len(root):
        root[i] = new_element
    else:
        root.append(new_element)
tree.write("output.xml", encoding="utf-8", xml_declaration=True)

Can anyone help me fix this error or suggest a better way to write my script? Any advice would be greatly appreciated.

Thank you very much.

I don’t know how to fix this error or why it occurs.

1
  • You have _serialize_xml calling ET._serialize_xml, which you then change on the next line to be _serialize_xml. So _serialize_xml does nothing but call itself. Why are you redefining ET._serialize_xml? Commented Mar 10, 2023 at 18:51

1 Answer 1

0

Modify the _serialize_xml() function to avoid calling itself when the tag of the current element is ![CDATA[.

def _serialize_xml(write, elem, qnames, namespaces, *, short_empty_elements=True):
    if elem.tag == '![CDATA[':
        write("\n<%s%s]]>\n" % (elem.tag, elem.text))
        return
    else:
        return ET._serialize_xml(write, elem, qnames, namespaces, short_empty_elements=short_empty_elements)
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.