You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用OpenAI GPT-4翻译带CDATA的XML并保留CDATA结构?

问题:GPT-4翻译XML时无法保留CDATA结构

我使用OpenAI GPT-4将XML内容从英文翻译为法语,但遇到了无法保留XML中CDATA结构的问题。XML包含带CDATA段的字符串,需要翻译后的输出维持CDATA结构。

输入XML示例

<resources>
    <string name="app_name">RoomThermometer</string>
    <string name="instructions" formatted="false">
        <![CDATA[
        <b>How it works? </b><br />
        The thermometer app is using your phone temperature sensors to measure room temperature.<br /><br />
        <b>Why this thermometer is the best one?</b><br />
        We use AI-powered algorithm to get the most accurate measure by ± 3°C. The more you use the thermometer, the more accurate it is!<br /><br />
        <b>How to get the best room temperature measure?</b><br />
        You want to prevent the phone from overheating, follow the next steps:<br />
        <b>1-</b> take your case off<br />
        <b>2-</b> Your phone is charging or just charged, let it cool down<br />
        <b>3-</b> Turn off unnecessary apps running in the background<br />
        ]]>
    </string>
</resources>

当前错误输出

<resources>
    <string name="app_name">Thermomètre de Chambre</string>
    <string name="instructions" formatted="false">
        '&lt;b&gt;Comment ça marche?&lt;/b&gt;&lt;br/&gt;
        L'application de thermomètre utilise les capteurs de température de votre téléphone pour mesurer la température ambiante.&lt;br/&gt;&lt;br/&gt;
        &lt;b&gt;Pourquoi ce thermomètre est le meilleur?&lt;/b&gt;&lt;br/&gt;
        Nous utilisons un algorithme alimenté par l'IA pour obtenir la mesure la plus précise à ± 3°C. Plus vous utilisez le thermomètre, plus il est précis!&lt;br/&gt;&lt;br/&gt;
        &lt;b&gt;Comment obtenir la meilleure mesure de température ambiante?&lt;/b&gt;&lt;br/&gt;
        Vous voulez éviter que le téléphone ne surchauffe, suivez les étapes suivantes:&lt;br/&gt;
        &lt;b&gt;1-&lt;/b&gt; retirez votre coque&lt;br/&gt;
        &lt;b&gt;2-&lt;/b&gt; Votre téléphone est en charge ou vient d'être chargé, laissez-le refroidir&lt;br/&gt;
        &lt;b&gt;3-&lt;/b&gt; Arrêtez l'application inutile qui fonctionne en arrière-plan&lt;br/&gt;'
    </string>
</resources>

期望输出

<resources>
    <string name="app_name">Thermomètre de Chambre</string>
    <string name="instructions" formatted="false">
        <![CDATA[
        <b>Comment ça fonctionne ? </b><br />
        L'application thermomètre utilise les capteurs de température de votre téléphone pour mesurer la température de la pièce.<br /><br />
        <b>Pourquoi ce thermomètre est le meilleur ?</b><br />
        Nous utilisons un algorithme alimenté par l'IA pour obtenir la mesure la plus précise à ± 3°C. Plus vous utilisez le thermomètre, plus il est précis !<br /><br />
        <b>Comment obtenir la meilleure mesure de la température de la pièce ?</b><br />
        Vous voulez empêcher le téléphone de surchauffer, suivez les étapes suivantes :<br />
        <b>1-</b> retirez votre étui<br />
        <b>2-</b> Votre téléphone est en train de charger ou vient de se charger, laissez-le refroidir<br />
        <b>3-</b> Fermez les applications inutiles qui tournent en arrière-plan<br />
        ]]>
    </string>
</resources>

问题代码

原脚本中处理XML的函数存在两处核心问题:

  1. Python标准库xml.etree.ElementTree解析XML时会自动剥离CDATA标记,导致代码中的CDATA判断条件无法触发
  2. 手动拼接CDATA字符串会被ElementTree转义,无法生成合法的CDATA段
def translate_xml_file(xml_file_path, target_language="French"):
    # Parse the XML file
    tree = ET.parse(xml_file_path)
    root = tree.getroot()

    # Iterate over each 'string' element
    for string_element in root.iter('string'):
        # Check if the element contains text
        if string_element.text:
            string_text = string_element.text.strip()

            # Check if the text is within a CDATA section
            if string_text.startswith("<![CDATA[") and string_text.endswith("]]>"):
                # Extract the content from CDATA
                cdata_content = string_text[9:-3]

                # Translate the content
                translated_cdata_content = translate_string(cdata_content, target_language)

                # Manually wrap with CDATA and set back to element
                string_element.text = "<![CDATA[" + translated_cdata_content + "]]>"
            else:
                # Translate normal text
                translated_text = translate_string(string_text, target_language)
                string_element.text = translated_text

    return tree

解决方案

步骤1:自定义CDATA处理类(标准库兼容)

扩展ElementTree,让它能识别并输出CDATA段:

import xml.etree.ElementTree as ET

class CDATA(ET.Element):
    def __init__(self, text):
        super().__init__()
        self.text = text

def _serialize_cdata(write, elem, encoding, qnames, namespaces):
    write(f"<![CDATA[{elem.text}]]>".encode(encoding))

# 替换默认的XML序列化逻辑
ET._original_serialize_xml = ET._serialize_xml
def _serialize_xml(write, elem, encoding, qnames, namespaces, orig=ET._original_serialize_xml):
    if isinstance(elem, CDATA):
        _serialize_cdata(write, elem, encoding, qnames, namespaces)
    else:
        orig(write, elem, encoding, qnames, namespaces)

ET._serialize_xml = _serialize_xml

步骤2:修改XML解析逻辑,捕获CDATA标记

自定义解析器,记录哪些元素原本包含CDATA:

class CDATAExtractor(ET.TreeBuilder):
    def cdata(self, data):
        # 标记当前元素包含CDATA
        self._last_is_cdata = True
        super().data(data)
    
    def end(self, tag):
        elem = super().end(tag)
        if hasattr(self, '_last_is_cdata') and self._last_is_cdata:
            elem.set('__is_cdata', 'True')
            delattr(self, '_last_is_cdata')
        return elem

步骤3:更新翻译函数

修改后的函数能正确识别并保留CDATA结构:

def translate_xml_file(xml_file_path, target_language="French"):
    # 使用自定义解析器捕获CDATA信息
    parser = ET.XMLParser(target=CDATAExtractor())
    tree = ET.parse(xml_file_path, parser=parser)
    root = tree.getroot()

    for string_element in root.iter('string'):
        if string_element.text:
            string_text = string_element.text.strip()
            # 检查是否为CDATA元素
            is_cdata = string_element.get('__is_cdata') == 'True'
            if is_cdata:
                string_element.attrib.pop('__is_cdata')
            
            if is_cdata:
                # 翻译时提示GPT保留HTML标签
                prompt = f"Translate the following text to {target_language}, keep all HTML tags (like <b>, <br>) unchanged, do not escape them:\n{string_text}"
                translated_content = translate_string(prompt, target_language)
                # 替换为CDATA元素
                string_element.text = None
                string_element.append(CDATA(translated_content))
            else:
                translated_text = translate_string(string_text, target_language)
                string_element.text = translated_text

    return tree

步骤4:保存XML时的注意事项

调用write方法时需指定编码,避免乱码:

tree = translate_xml_file("input.xml")
tree.write("output.xml", encoding='utf-8', xml_declaration=True)

补充说明

  • 确保translate_string函数中的GPT prompt明确要求保留HTML标签,避免GPT转义标签
  • 如果可以使用第三方库lxml,可以简化CDATA的处理(lxml原生支持CDATA对象)

内容的提问来源于stack exchange,提问作者user22833873

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 09:50:54